PackageManager:管理應用程式包
功能:
- 安裝,解除安裝應用
- 查詢permission相關資訊
- 查詢Application相關資訊(application,activity,receiver,service,provider及相應屬性等)
- 查詢已安裝應用
- 增加,删除permission
- 清除使用者資料、緩存,代碼段等
使用方法:
在Android中,為應用包的安裝,删除各種操作服務的,是PackageManagerSerivce,簡稱PMS.
如果想要調用PMS的服務,則可以通過Context去調用getPackageManager方法。
/** Return PackageManager instance to find global package information. */
public abstract PackageManager getPackageManager();
這個定義于Context.java中:
查詢Application相關資訊
應用元件集合查詢API
一、根據包名擷取應用資訊
ApplicationInfo getApplicationInfo (String packageName,int flags)
參數:flags
- GET_SHARED_LIBRARY_FILES:擷取so庫的安裝路徑,然後可以通過ApplicationInfo的sharedLibraryFiles屬性來讀取相關資訊。
- MATCH_SYSTEM_ONLY:隻包括帶有系統屬性的
- MATCH_UNINSTALLED_PACKAGES:即使是應用被uninstall了,但隻要保留了資料,也可以被搜出來。
二、擷取目前系統上安裝的所有的應用程式
List<ApplicationInfo> getInstalledApplications (int flags);
參數:flags
- GET_META_DATA:
- GET_SHARED_LIBRARY_FILES:擷取so庫的安裝路徑,然後可以通過ApplicationInfo的sharedLibraryFiles屬性來讀取相關資訊。
- MATCH_SYSTEM_ONLY:隻包括帶有系統屬性的
- MATCH_UNINSTALLED_PACKAGES:即使是應用被uninstall了,但隻要保留了資料,也可以被搜出來。
三、擷取目前系統中安裝的所有包
List<PackageInfo> getInstalledPackages (int flags)
參數:flags
* PackageManager.GET_ACTIVITIES
* PackageManager.GET_CONFIGURATIONS
* PackageManager.GET_GIDS
* PackageManager.GET_INSTRUMENTATION
* PackageManager.GET_INTENT_FILTERS
* PackageManager.GET_META_DATA
* PackageManager.GET_PERMISSIONS
* PackageManager.GET_PROVIDERS
* PackageManager.GET_RECEIVERS
* PackageManager.GET_SERVICES
* PackageManager.GET_SHARED_LIBRARY_FILES
* PackageManager.GET_SIGNATURES
* PackageManager.GET_URI_PERMISSION_PATTERN
四、根據包名擷取一個包的資訊
PackageInfo getPackageInfo (String packageName, int flags);
參數:flags
* PackageManager.GET_ACTIVITIES
* PackageManager.GET_CONFIGURATIONS
* PackageManager.GET_GIDS
* PackageManager.GET_INSTRUMENTATION
* PackageManager.GET_INTENT_FILTERS
* PackageManager.GET_META_DATA
* PackageManager.GET_PERMISSIONS
* PackageManager.GET_PROVIDERS
* PackageManager.GET_RECEIVERS
* PackageManager.GET_SERVICES
* PackageManager.GET_SHARED_LIBRARY_FILES
* PackageManager.GET_SIGNATURES
* PackageManager.GET_URI_PERMISSION_PATTERN
五、從封包件中讀取getPackageArchiveInfo
public PackageInfo getPackageArchiveInfo(String archiveFilePath, int flags)
參數:flags
* PackageManager.GET_ACTIVITIES
* PackageManager.GET_CONFIGURATIONS
* PackageManager.GET_GIDS
* PackageManager.GET_INSTRUMENTATION
* PackageManager.GET_INTENT_FILTERS
* PackageManager.GET_META_DATA
* PackageManager.GET_PERMISSIONS
* PackageManager.GET_PROVIDERS
* PackageManager.GET_RECEIVERS
* PackageManager.GET_SERVICES
* PackageManager.GET_SHARED_LIBRARY_FILES
* PackageManager.GET_SIGNATURES
* PackageManager.GET_URI_PERMISSION_PATTERN
六、根據Activity的名稱來擷取ActivityInfo
ActivityInfo getActivityInfo (ComponentName component, int flags)
ComponentName是個什麼類呢?其實就是包名和類名的組合:
//Create a new component identifier.
ComponentName(String pkg, String cls);
特别要注意,類名是要全路徑名,不然會找不到的!
try {
final ActivityInfo ai = mPm.getActivityInfo(new ComponentName("com.android.htmlviewer","com.android.htmlviewer.HTMLViewerActivity"),
PackageManager.GET_META_DATA | PackageManager.MATCH_ALL);
Log.d(TAG,"ActivityInfo:"+ai.toString());
Log.d(TAG,"ActivityInfo,parentActivityName is:"+ai.parentActivityName);
} catch (PackageManager.NameNotFoundException e) {
Log.e(TAG,"testGetActivityInfo error",e);
}
參數:
flags
七、根據名字擷取Instrumentation資訊,這個資訊在AndroidManifest.xml中的中定義
InstrumentationInfo getInstrumentationInfo (ComponentName className, int flags);
八、通過ComponentName擷取ServiceInfo
ServiceInfo getServiceInfo (ComponentName component, int flags);
九、根據ComponentName擷取ReceiverInfo
有同學問了,既然可以查詢ActivityInfo,ServiceInfo,ReceiverInfo,四大元件中都有三個了,那麼為什麼沒有查詢ProviderInfo的呢?
getProviderInfo這個API直到Android 2.3時才有
ActivityInfo getReceiverInfo (ComponentName component, int flags);
十、Android 2.3新增API - getProviderInfo
ProviderInfo getProviderInfo (ComponentName component, int flags);
Uid/Gid相關查詢API
一、讀取和包名相關的Group id
ProviderInfo getProviderInfo (ComponentName component, int flags);
public void testGetPackageGids(){
try {
int[] gids = mPm.getPackageGids("com.android.externalstorage");
if(gids!=null){
for(int gid:gids){
Log.d(TAG,"gid:"+gid);
}
}
} catch (PackageManager.NameNotFoundException e) {
Log.e(TAG,"testGetPackageGids error",e);
}
}
輸出
- :: -/? D/TestPackageManager: gid:
- :: -/? D/TestPackageManager: gid:
二、getPackagesForUid
ProviderInfo getProviderInfo (ComponentName component, int flags);
public void testGetPackagesForUid(){
String[] packagesForUid = mPm.getPackagesForUid();
if(packagesForUid!=null){
for(String package1 : packagesForUid){
Log.d(TAG, "Package name in 1000:"+package1);
}
}
}
輸出
- :: -/? D/TestPackageManager: Package name in :com.mediatek
- :: -/? D/TestPackageManager: Package name in :com.mediatek.thermalmanager
- :: -/? D/TestPackageManager: Package name in :com.mediatek.batterywarning
- :: -/? D/TestPackageManager: Package name in :com.mediatek.connectivity
- :: -/? D/TestPackageManager: Package name in :com.android.server.telecom
- :: -/? D/TestPackageManager: Package name in :com.android.inputdevices
- :: -/? D/TestPackageManager: Package name in :com.android.settings
- :: -/? D/TestPackageManager: Package name in :android
- :: -/? D/TestPackageManager: Package name in :com.mediatek.atci.service
- :: -/? D/TestPackageManager: Package name in :com.android.providers.settings
- :: -/? D/TestPackageManager: Package name in :com.android.vpndialogs
- :: -/? D/TestPackageManager: Package name in :com.mediatek.ppl
- :: -/? D/TestPackageManager: Package name in :com.android.location.fused
- :: -/? D/TestPackageManager: Package name in :com.mediatek.nlpservice
- :: -/? D/TestPackageManager: Package name in :com.mediatek.schpwronoff
- :: -/? D/TestPackageManager: Package name in :com.android.keychain
三、查詢一個uid對應的名字
String getNameForUid (int uid);
public void testGetNameForUid(){
String name = mPm.getNameForUid();
Log.d(TAG,"Name for uid 1000 is:"+name);
}
輸出
- :: -/? D/TestPackageManager: Name for uid is:android.uid.system:
Uid/Gid相關查詢API
一、查詢系統中運作的ContentProvider
List<ProviderInfo> queryContentProviders (String processName,int uid,int flags)
參數:
程序名:如果希望列出所有的,就為空
uid:如果程序名不為空,需要指定uid
标志位:match的屬性
public void testQueryContentProviders() {
List<ProviderInfo> pis = mPm.queryContentProviders(null, , PackageManager.MATCH_ALL);
if (pis != null) {
for (ProviderInfo pri : pis) {
Log.d(TAG, "Provider info:" + pri);
}
}
}
輸出
- :: -/? D/TestPackageManager: Provider info:ContentProviderInfo{name=settings className=com.android.providers.settings.SettingsProvider}
- :: -/? D/TestPackageManager: Provider info:ContentProviderInfo{name=com.tencent.mm.plugin.ext.NearBy className=com.tencent.mm.plugin.ext.provider.ExtControlProviderNearBy}
- :: -/? D/TestPackageManager: Provider info:ContentProviderInfo{name=mwimsg className=com.android.providers.telephony.MwiProvider}
二、根據包名查詢Instrumentation
List<InstrumentationInfo> queryInstrumentation (String targetPackage,int flags);
參數:
包名:如果是所有的包,則給null
标志:隻支援GET_META_DATA這一個。
public void testQueryInstrumentation(){
List<InstrumentationInfo> list = mPm.queryInstrumentation(null,PackageManager.GET_META_DATA);
if(list!=null){
for(InstrumentationInfo ii : list){
Log.d(TAG,"Instrumentation info:"+ii.toString());
}
}
}
根據Intent查詢相關元件的API
一、根據Intent查詢可以處理這個Intent的所有BroadcastReceivers
List<ResolveInfo> queryBroadcastReceivers (Intent intent,int flags);
二、查詢可以處理這個Intent的所有Activity
List<ResolveInfo> queryIntentActivities (Intent intent,int flags);
參數:
Intent
參數:MATCH_ALL等
三、queryIntentActivityOptions跟queryIntentActivities基本一樣,支援更多的查詢條件
List<ResolveInfo> queryIntentActivityOptions (ComponentName caller, Intent[] specifics, Intent intent,int flags);
四、查詢可以處理這個Intent的所有Service
List<ResolveInfo> queryIntentServices (Intent intent,int flags);
大家都知道,Android有四大元件:Activity, Service, BroadcastReceiver和ContentProvider。前面三個元件都可以通過Intent查詢了,為什麼沒有queryIntentContentProviders呢?
queryIntentContentProviders直到Android 4.4才增加進來。
五、Android 4.4新增API: queryIntentContentProviders,查詢可以處理這個Intent的所有ContentProvider們
List<ResolveInfo> queryIntentContentProviders (Intent intent, int flags);
根據Intent查詢最佳應用元件API
一、resolveActivity:查找最适合些Intent的Activity
ResolveInfo resolveActivity (Intent intent, int flags);
二、resolveContentProvider:查找最适合些Intent的ContentProvider
ResolveInfo resolveContentProvider (Intent intent, int flags);
三、resolveService:查找最适合些Intent的服務
ResolveInfo resolveService (Intent intent, int flags);
上面3個API都是拿到了Intent再去判斷它最适合的應用元件。那麼,我們想要做逆運算,知道一個包了,如何去得到啟動它的Intent呢?
這個API直到Android 1.5(API 3)時才加入系統中:getLaunchIntentForPackage
事、resolveService:查找最适合些Intent的服務
Intent getLaunchIntentForPackage (String packageName);
例程:我們想擷取微信的啟動Intent:
public void testGetLaunchIntentForPackage() {
Intent intent = mPm.getLaunchIntentForPackage("com.tencent.mm");
if (intent != null) {
Log.d(TAG, "Intent for Launch this is:" + intent.toString());
}
}
運作結果如下,原來啟動微信的界面是com.tencent.mm.ui.LauncherUI。
- :: -/? D/TestPackageManager: Intent for Launch this is:Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=x10000000 pkg=com.tencent.mm cmp=com.tencent.mm/.ui.LauncherUI }
一個查詢應用資訊的例子
package com.bourne.android_common.PackageManagerDemo;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.InstrumentationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import com.bourne.android_common.R;
import com.bourne.common_library.utils.Logout;
import java.util.Collections;
import java.util.List;
public class PackagerManagerActivity extends AppCompatActivity {
// 所有應用程式
public static final int FILTER_ALL_APP = ;
// 系統程式
public static final int FILTER_SYSTEM_APP = ;
// 第三方應用程式
public static final int FILTER_THIRD_APP = ;
// 安裝在SDCard的應用程式
public static final int FILTER_SDCARD_APP = ;
private PackageManager pm;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_packager_manager);
// Logout.e("擷取所有程式資訊");
// getPackageInfo();
// Logout.e("根據包名擷取應用資訊");
// getAppInfoByPackageName("com.bourne.android_common");
// Logout.e("擷取所有程式的Activity");
// getInstalledPackages();
Logout.e("系統程式");
filterApp(FILTER_SYSTEM_APP);
Logout.e("第三方應用程式");
filterApp(FILTER_THIRD_APP);
Logout.e("安裝在SDCard的應用程式");
filterApp(FILTER_SDCARD_APP);
}
/**
* 擷取所有程式資訊
* 通過PackageManager的queryIntentActivities方法,
* 查詢系統中所有滿足ACTION_MAIN和CATEGORY_LAUNCHER的應用程式,
* 擷取他們的程式名、包名、入口類名。
*/
private void getPackageInfo() {
pm = this.getPackageManager();
//action為ACTION_MAIN的
Intent intent = new Intent(Intent.ACTION_MAIN, null);
intent.addCategory(Intent.CATEGORY_DEFAULT);
List<ResolveInfo> list = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
//根據顯示名稱排序
Collections.sort(list, new ResolveInfo.DisplayNameComparator(pm));
for (ResolveInfo info : list) {
//應用名
String appName = info.loadLabel(pm).toString();
//包名
String packageName = info.activityInfo.packageName;
//入口類名
String launchClassName = info.activityInfo.name;
Logout.i("應用名:" + appName + "\n包名:" + packageName + "\n入口類名:" + launchClassName);
}
}
/**
* 篩選
*
* @param type
*/
private void filterApp(int type) {
pm = this.getPackageManager();
//getInstalledApplications:擷取目前系統上安裝的所有的應用程式
List<ApplicationInfo> list = pm.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES);
Collections.sort(list, new ApplicationInfo.DisplayNameComparator(pm));
switch (type) {
case FILTER_ALL_APP:
for (ApplicationInfo info : list) {
getAppInfo(info);
}
break;
case FILTER_SYSTEM_APP:
for (ApplicationInfo info : list) {
if ((info.flags & ApplicationInfo.FLAG_SYSTEM) != ) {
getAppInfo(info);
}
}
break;
case FILTER_THIRD_APP:
for (ApplicationInfo info : list) {
if ((info.flags & ApplicationInfo.FLAG_SYSTEM) <= ) {
getAppInfo(info);
}
}
break;
case FILTER_SDCARD_APP:
for (ApplicationInfo info : list) {
if (info.flags == ApplicationInfo.FLAG_SYSTEM) {
getAppInfo(info);
}
}
break;
}
}
/**
* 擷取應用資訊
*/
private void getAppInfo(ApplicationInfo applicationInfo) {
// 應用名
String appName = applicationInfo.loadLabel(pm).toString();
// 包名
String packageName = applicationInfo.packageName;
//入口類名
String launchClassName = applicationInfo.name;
//程序名
String processName = applicationInfo.processName;
Logout.i("應用名:" + appName + "\n包名:" + packageName + "\n入口類名:" + launchClassName + "\n程序名:" + processName);
}
/**
* 根據包名擷取應用資訊
*/
private void getAppInfoByPackageName(String packageName) {
pm = this.getPackageManager();
ApplicationInfo ai = null;
try {
ai = pm.getApplicationInfo(packageName,
PackageManager.GET_META_DATA | PackageManager.GET_SHARED_LIBRARY_FILES);
// 應用名
String appName = ai.loadLabel(pm).toString();
//入口類名
String launchClassName = ai.name;
//程序名
String processName = ai.processName;
//描述
String loadDescription = "" + ai.loadDescription(pm);
//共享庫
String nativeLibraryDir = ai.nativeLibraryDir;
Logout.i("應用名:" + appName + "\n入口類名:" + launchClassName + "\n程序名:" + processName + "\n描述:" + loadDescription + "\n共享庫:" + nativeLibraryDir);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}
/**
* 擷取目前系統中安裝的所有包
*/
public void getInstalledPackages() {
pm = this.getPackageManager();
List<PackageInfo> piList = pm.getInstalledPackages(PackageManager.GET_ACTIVITIES |
PackageManager.GET_CONFIGURATIONS |
PackageManager.GET_GIDS |
PackageManager.GET_INSTRUMENTATION |
PackageManager.GET_INTENT_FILTERS |
PackageManager.GET_META_DATA |
PackageManager.GET_PERMISSIONS |
PackageManager.GET_PROVIDERS |
PackageManager.GET_RECEIVERS |
PackageManager.GET_SERVICES |
PackageManager.GET_SHARED_LIBRARY_FILES |
PackageManager.GET_SIGNATURES |
PackageManager.GET_URI_PERMISSION_PATTERNS);
if (piList != null) {
for (PackageInfo pi : piList) {
Logout.i("包資訊:" + pi.toString());
Logout.i("包名:" + pi.packageName);
Logout.i("包共享user id" + pi.sharedUserId);
final ActivityInfo[] ais = pi.activities;
if (ais != null) {
for (ActivityInfo ai : ais) {
Logout.i("Activity:{" + pi.packageName + "}:" + ai.name);
}
}
final InstrumentationInfo[] iis = pi.instrumentation;
if (iis != null) {
for (InstrumentationInfo is : iis) {
Logout.i("Instrumentation資訊" + is.toString());
}
}
final ProviderInfo[] pis = pi.providers;
if (pis != null) {
for (ProviderInfo pri : pis) {
Logout.i("Provider資訊:" + pri);
}
}
}
}
}
}
系統應用資訊:
第三方應用資訊
擷取所有的activity
參考文章
- Android應用生死輪回的那些事兒(4) - 武器庫(2)-應用元件查詢相關
- Android應用生死輪回的那些事兒(2) - PackageManager
- 幾個Info系列的種的總結
- Android随筆之——PackageManager詳解
- Android中擷取應用程式(包)的資訊—–PackageManager的使用(一)
- Android擷取應用程式資訊——PackageManager的基本使用