Android - PackageManager로 Package 정보 가져오기

PackageManager는 Package, Application 정보를 얻을 수 있는 API를 제공합니다.

  • PackageManager.getInstalledPackages(int flags)
  • PackageManager.getPackageInfo(String packageName, int flags)
  • PackageManager.getApplicationInfo(String packageName, int flags)

또한, PackageManager는 Activity, Service, Provider, Receiver 정보를 얻을 수 있는 Query api를 제공합니다.

  • PackageManager.queryIntentActivities(Intent intent, int flags)
  • PackageManager.queryBroadcastReceivers(Intent intent, int flags)
  • PackageManager.queryIntentServices(Intent intent, int flags)
  • PackageManager.queryIntentContentProviders(Intent intent, int flags)

위 API들을 사용하여 Package 정보 및 App의 Component 정보들을 얻을 수 있습니다.

각각의 API를 사용하는 방법을 소개하겠습니다.

Package 정보

다음 API를 사용하여 Package 정보를 얻을 수 있으며 PackageInfo 객체로 전달됩니다.

  • getPackageInfo(String packageName, int flags): 인자로 전달된 패키지 이름에 대한 패키지 정보를 PackageInfo로 리턴
  • getInstalledPackages(int flags): 디바이스에 설치된 모든 패키지에 대한 정보를 PackageInfo 리스트로 리턴

getPackageInfo()

getPackageInfo()는 다음과 같이 인자로 전달된 package name에 대한 PackageInfo 객체를 리턴합니다. 보통 flags는 0을 전달하면 됩니다. PackageInfo는 packageName, versionName, ApplicationInfo 등의 정보를 갖고 있습니다.

val pi : PackageInfo = packageManager.getPackageInfo("com.example.sample", 0)

val packageName = pi.packageName
val versionName = pi.versionName
val applicationInfo = pi.applicationInfo

PackageInfo가 제공하는 데이터들은 Android Developer - PackageInfo를 참고하시면 됩니다.

flags

getPackageInfo()에 전달되는 flags는 다음과 같은 것들을 전달할 수 있으며, 사용하는 이유는 다음과 같습니다. 만약 현재 설치되어있고, 사용 가능한 App을 대상으로 정보를 얻는다면 flags는 0을 전달하시면 됩니다.

  • PackageManager.MATCH_UNINSTALLED_PACKAGES : uninstalled 상태에 있는 패키지 정보도 가져옵니다. 간혹 system app은 uninstalled 상태인 앱들이 있습니다. 또는 다른 User에 설치되어있지만 App이 실행 중인 User에는 설치되지 않은 상태인 경우도 있습니다.
  • PackageManager.MATCH_DISABLED_COMPONENTS : disabled 상태에 있는 패키지 정보도 가져옵니다.

앞으로 소개하는 API의 flags 인자의 목적 및 사용 방법도 이와 동일합니다.

Package visibility

만약 원하는 데이터가 리턴되지 않는다면 자신의 앱이 Package visibility라는 기능에 대해서 조치가 되어있는지 확인하셔야 합니다.

Android 11에서 Package visibility라는 기능이 적용되었습니다. API 30을 타게팅하는 앱은 다른 패키지의 정보를 찾을 수 없는 제약사항 입니다. 필요하다면 AndroidManifest에 특정 패키지를 탐색하고 싶다고 요청을 해야 합니다.

만약 다음과 같이 Manifest에 퍼미션을 추가하면 모든 패키지를 탐색할 수 있습니다.

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

getInstalledPackages()

getInstalledPackages()는 다음과 같이 사용할 수 있으며 디바이스에 설치된 모든 패키지에 대한 PackageInfo를 리스트로 리턴합니다.

val pis : List<PackageInfo> = packageManager.getInstalledPackages(0)

getApplicationInfo()

getApplicationInfo()는 인자로 전달된 package name에 대한 ApplicationInfo 객체를 리턴합니다. getPackageInfo()와 비교할 때 PackageInfo가 아닌 ApplicationInfo를 리턴하는 차이점이 있습니다.

val ai : ApplicationInfo = packageManager.getApplicationInfo("com.example.sample", 0)

ApplicationInfo가 제공하는 데이터들은 Android Developer - ApplicationInfo를 참고하시면 됩니다.

Component 정보

아래 4개의 API는 Activity, BroadcastReceiver, ContentProvider, Service에 대해 검색하고 결과를 ResolveInfo 리스트로 리턴합니다. 사용 방법은 모두 동일하기 때문에 queryIntentActivities()에 대해서만 소개하겠습니다.

  • PackageManager.queryIntentActivities(Intent intent, int flags)
  • PackageManager.queryBroadcastReceivers(Intent intent, int flags)
  • PackageManager.queryIntentServices(Intent intent, int flags)
  • PackageManager.queryIntentContentProviders(Intent intent, int flags)

queryIntentActivities()

queryIntentActivities()는 인자로 Intent와 flags를 받습니다. 이 API는 인자로 전달된 Intent를 해석하고 이것과 관련된 Activity들을 ResolveInfo 리스트로 리턴합니다. ResolveInfo는 Activity 1개에 대한 정보가 담겨있다고 생각하시면 됩니다.

아래 코드에서 Intent는 Launchable Activity를 대표하는 Intent입니다. 이 Intent를 인자로 전달하면 Launchable Activity들의 정보가 리턴됩니다. ResolveInfo를 통해서 packageName, Label, Icon 등의 정보를 얻을 수 있습니다.

val intent = Intent(Intent.ACTION_MAIN)
intent.addCategory(Intent.CATEGORY_LAUNCHER)
val ris : List<ResolveInfo> = packageManager.queryIntentActivities(intent, 0)

for (ri in ris) {
    val packageName = ri.activityInfo.packageName
    val className = ri.activityInfo.name
    val label = ri.loadLabel(packageManager).toString()
    val icon = ri.loadIcon(packageManager)
}

ResolveInfo가 제공하는 데이터들은 Android Developer - ResolveInfo를 참고하시면 됩니다.

정리

PackageManager API를 사용하여 디바이스에 설치된 Package 정보 및 Component의 정보를 얻는 방법을 알아보았습니다. 일반적으로 인자 flags는 0을 사용하시면 되며, 더 많은 정보를 얻고 싶을 때 필요한 flags를 추가하시면 됩니다.

Loading script...

Related Posts

codechachaCopyright ©2019 codechacha