Android - インストールされてアプリリストをインポートする

By JS | Last updated: September 13, 2020

AndroidからPackageManagerを利用すると、デバイスにインストールされてアプリのリストを取得することができます。 PackageManagerは、デバイスにインストールされたパッケージを管理し、パッケージに関する情報を見つけることができるQuery APIを提供しています。

次のAPIを使用すると、デバイスにインストールされてPackageリストを得ることができます。

  • PackageManager.getInstalledPackages()
  • PackageManager.getInstalledApplications()

PackageManager.getInstalledPackages()

getInstalledPackages()はインストールされてアプリの情報をPackageInfoリストで返します。 引数としてflagsを転送します。特別なフラグを設定したくない場合は0を渡します。その後、基本的にはインストールされているアプリのリストが返されます。

val packageManager = context.packageManager
val packages: List<PackageInfo> = packageManager.getInstalledPackages(0)
for (info: PackageInfo in packages) {
    Log.d("Test", "packageName: ${info.packageName}"
            + ", versionName: ${info.versionName}"
            + ", lastUpdateTime: ${info.lastUpdateTime}"
            + ", targetSdk: ${info.applicationInfo.targetSdkVersion}"
            + ", minSdk: ${info.applicationInfo.minSdkVersion}"
            + ", sourceDir: ${info.applicationInfo.sourceDir}"
            + ", uid: ${info.applicationInfo.uid}"
            + ", label: ${info.applicationInfo.loadLabel(packageManager)}")
}

ログを確認してみると、次のようにインストールされているアプリの情報が出力されます。

09-13 15:56:22.717 13291 13323 D Test    : packageName: com.google.android.youtube, versionName: 14.19.57, lastUpdateTime: 1569045019000, targetSdk: 28, minSdk: 21, sourceDir: /system/product/app/YouTube/YouTube.apk, uid: 10132, label: YouTube
....

システムアプリのリストのみが戻さ

インストールされたシステムアプリリストだけを得たい場合は、フラグ引数として MATCH_SYSTEM_ONLYを提供します。

val packages: List<PackageInfo> = packageManager.getInstalledPackages(
        PackageManager.MATCH_SYSTEM_ONLY)

削除されたアプリのリストも一緒に返さ

Androidはマルチユーザシステムをサポートします。いくつかのアプリが現在実行中のUserにはインストールされておらず、他のUserにインストールされていることがあります。 このような場合には、このアプリは、現在のUserにはインストールされていない状態であるため、 getInstalledPackages(0)の結果として返されません。

現在のUserに削除されたアプリの情報もすべて取得したい場合、フラグ引数として MATCH_UNINSTALLED_PACKAGESを引数として渡します。

val packages: List<PackageInfo> = packageManager.getInstalledPackages(
        PackageManager.MATCH_UNINSTALLED_PACKAGES)

無効化されアプリリストも一緒に返さ

いくつかのアプリはインストールされているが無効になっている可能性があります。無効(disabled)されると、実行が不可能な状態で、Launcherもアイコンが表示されない状態です。 このようなアプリの情報もすべて取得したい場合、フラグ引数として MATCH_DISABLED_COMPONENTSを提供します。

val packages: List<PackageInfo> = packageManager.getInstalledPackages(
        PackageManager.MATCH_DISABLED_COMPONENTS)

User Locked時点でインストールされたアプリのリストを取得する

Android 7.0にDirect Bootが適用されました。 もし起動後、ユーザーがLockを解除しないとUserはLocked状態になります。 User Locked状態のとき DIRECT_BOOT_AWAREに設定されていないアプリは実行が不可能な状態になります。

この時点で getInstalledPackages(0)を呼び出すと、 DIRECT_BOOT_AWAREに設定されたアプリのリストのみが戻されます。 もしインストールされてすべてのアプリのリストを取得したい場合 PackageManager.MATCH_DIRECT_BOOT_UNAWAREフラグを引数として渡す必要があります。

しかし、次のように、一つのフラグだけ提供するよりも、AWAREとUNAWARE二つのフラグをすべて転送するように実装されることをお勧めします。 (Direct bootに影響を受けずにすべてのパッケージを探してたい意図を示すことができます。)

val flags = PackageManager.MATCH_DIRECT_BOOT_AWARE or PackageManager.MATCH_DIRECT_BOOT_UNAWARE
val packages: List<PackageInfo> = packageManager.getInstalledPackages(flags)

PackageManager.getInstalledApplications()

getInstalledPackages() APIはPackageInfoリストを返します。 PackageInfoはApplicationInfoを持っています。

しかし、ApplicationInfoだけが必要な場合には、 getInstalledApplications() APIを使用することもできます。このAPIは、ApplicationInfoリストを返します。

次のように実装することができます。

val packageManager = context.packageManager
val flag = 0;
val applications: List<ApplicationInfo> = packageManager.getInstalledApplications(flag)
for (info: ApplicationInfo in applications) {
    Log.d("Test", "packageName: ${info.packageName}"
            + ", targetSdk: ${info.targetSdkVersion}"
            + ", minSdk: ${info.minSdkVersion}"
            + ", sourceDir: ${info.sourceDir}"
            + ", uid: ${info.uid}"
            + ", label: ${info.loadLabel(packageManager)}")
}

フラグを設定する方法は、 getInstalledPackages()で使用したのと同じ方法で使用ください。

特定のPackageインストールするかどうかを確認

上記のAPIは、すべてのパッケージのリストを返しました。 もし、特定のAppがインストールされていることを確認したいときは getPackageInfo(packageName, flags) APIを使用することができます。

次のように引数としてPackageNameを渡すと、このアプリの情報を得ることができます。 PackageInfoが返されればインストールされてアプリであり、 NameNotFoundExceptionが発生した場合、インストールされていないアプリです。

val packageManager = context.packageManager
val flag = 0;
val packageName = "com.google.android.youtube"
try {
    val info: PackageInfo = packageManager.getPackageInfo(
        packageName, flag
    )
} catch (e: PackageManager.NameNotFoundException) {
    Log.d("Test", "Not found package : $packageName")
}

次のように getApplicationInfo(packageName, flags)を使用することもできます。 アプリがインストールされていない場合は、NameNotFoundExceptionが返されます。

val info: ApplicationInfo = packageManager.getApplicationInfo(
        "com.google.android.youtube", flag)

Package Visibility

Android 11でPackage Visibilityと呼ばれる機能が追加されました。 Package VisibilityはTarget SDK 30のアプリにのみ適用となり、他のアプリの情報を取得するにはAndroidManifestに事前に定義をしなければならないということです。 そうでなければ、他のアプリの情報を得ることができません。

もし、他のアプリの情報を取得しようとし PackageManager.getInstalledPackages()を呼び出す場合は、いくつかの重要なシステムアプリを除いた他のアプリは、リストに含まれていません。

Manifestに次のようなパーミッションを追加すると、すべてのパッケージの情報を得ることができます。

<uses-permission android:name = "android.permission.QUERY_ALL_PACKAGES" />

詳細については、Package Visibilityをご確認ください。

adbコマンドでインストールされたパッケージの情報を確認

adb shell pm list packageコマンドを入力すると、デバイスにインストールされたパッケージの名前が出力されます。

$ adb shell pm list package
package:com.android.cts.priv.ctsshim
package:com.google.android.youtube
package:com.android.internal.display.cutout.emulation.corner
package:com.google.android.ext.services
package:com.android.internal.display.cutout.emulation.double
package:com.android.providers.telephony
package:com.android.dynsystem
package:com.google.android.googlequicksearchbox
package:com.android.providers.calendar
package:com.android.providers.media
....

特定のパッケージについて詳細な情報を知りたい場合は、 adb shell dumpsys package [package name]で確認することができます。

$ adb shell dumpsys package com.google.android.youtube
Packages:
  Package [com.google.android.youtube] (3d92a10):
    userId=10132
    pkg=Package{4e1cc5 com.google.android.youtube}
    codePath=/system/product/app/YouTube
    resourcePath=/system/product/app/YouTube
    legacyNativeLibraryDir=/system/product/app/YouTube/lib
    primaryCpuAbi=x86
    secondaryCpuAbi=null
    versionCode=1419573700 minSdk=21 targetSdk=28
    versionName=14.19.57
    splits=[base]
    apkSigningVersion=3
    applicationInfo=ApplicationInfo{ed73c com.google.android.youtube}
    flags=[ SYSTEM HAS_CODE ALLOW_CLEAR_USER_DATA ALLOW_BACKUP KILL_AFTER_RESTORE RESTORE_ANY_VERSION LARGE_HEAP ]
    privateFlags=[ PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION PRIVATE_FLAG_REQUEST_LEGACY_EXTERNAL_STORAGE HAS_DOMAIN_URLS PRODUCT ]
    dataDir=/data/user/0/com.google.android.youtube
    ....

Related Posts

codechachaCopyright ©2019 codechacha