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를 추가하시면 됩니다.
Related Posts
- Android 14 - 사진/동영상 파일, 일부 접근 권한 소개
- Android - adb push, pull로 파일 복사, 다운로드
- Android 14 - 암시적 인텐트 변경사항 및 문제 해결
- Jetpack Compose - Row와 Column
- Android 13, AOSP 오픈소스 다운로드 및 빌드
- Android 13 - 세분화된 미디어 파일 권한
- Android 13에서 Notification 권한 요청, 알림 띄우기
- Android 13에서 'Access blocked: ComponentInfo' 에러 해결
- 에러 해결: android gradle plugin requires java 11 to run. you are currently using java 1.8.
- 안드로이드 - 코루틴과 Retrofit으로 비동기 통신 예제
- 안드로이드 - 코루틴으로 URL 이미지 불러오기
- Android - 진동, Vibrator, VibrationEffect 예제
- Some problems were found with the configuration of task 에러 수정
- Query method parameters should either be a type that can be converted into a database column or a List
- 우분투에서 Android 12 오픈소스 다운로드 및 빌드
- Android - ViewModel을 생성하는 방법
- Android - Transformations.map(), switchMap() 차이점
- Android - Transformations.distinctUntilChanged() 소개
- Android - TabLayout 구현 방법 (+ ViewPager2)
- Android - 휴대폰 전화번호 가져오는 방법
- Android 12 - Splash Screens 알아보기
- Android 12 - Incremental Install (Play as you Download) 소개
- Android - adb 명령어로 bugreport 로그 파일 추출
- Android - adb 명령어로 App 데이터 삭제
- Android - adb 명령어로 앱 비활성화, 활성화
- Android - adb 명령어로 특정 패키지의 PID 찾기
- Android - adb 명령어로 퍼미션 Grant 또는 Revoke
- Android - adb 명령어로 apk 설치, 삭제
- Android - adb 명령어로 특정 패키지의 프로세스 종료
- Android - adb 명령어로 screen capture 저장
- Android - adb 명령어로 System 앱 삭제, 설치
- Android - adb 명령어로 settings value 확인, 변경
- Android 12 - IntentFilter의 exported 명시적 선언
- Android - adb 명령어로 공장초기화(Factory reset)
- Android - adb logcat 명령어로 로그 출력