PackageManager解析

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);
        }
    }

输出

08-12 15:30:36.783 2329-2329/? D/TestPackageManager: gid:1023
08-12 15:30:36.783 2329-2329/? D/TestPackageManager: gid:10
二、getPackagesForUid
ProviderInfo getProviderInfo (ComponentName component, int flags);
    public void testGetPackagesForUid(){
        String[] packagesForUid = mPm.getPackagesForUid(1000);
        if(packagesForUid!=null){
            for(String package1 : packagesForUid){
                Log.d(TAG, "Package name in 1000:"+package1);
            }
        }
    }

输出

08-12 16:42:38.730 4736-4736/? D/TestPackageManager: Package name in 1000:com.mediatek
08-12 16:42:38.730 4736-4736/? D/TestPackageManager: Package name in 1000:com.mediatek.thermalmanager
08-12 16:42:38.730 4736-4736/? D/TestPackageManager: Package name in 1000:com.mediatek.batterywarning
08-12 16:42:38.730 4736-4736/? D/TestPackageManager: Package name in 1000:com.mediatek.connectivity
08-12 16:42:38.730 4736-4736/? D/TestPackageManager: Package name in 1000:com.android.server.telecom
08-12 16:42:38.730 4736-4736/? D/TestPackageManager: Package name in 1000:com.android.inputdevices
08-12 16:42:38.730 4736-4736/? D/TestPackageManager: Package name in 1000:com.android.settings
08-12 16:42:38.730 4736-4736/? D/TestPackageManager: Package name in 1000:android
08-12 16:42:38.730 4736-4736/? D/TestPackageManager: Package name in 1000:com.mediatek.atci.service
08-12 16:42:38.730 4736-4736/? D/TestPackageManager: Package name in 1000:com.android.providers.settings
08-12 16:42:38.730 4736-4736/? D/TestPackageManager: Package name in 1000:com.android.vpndialogs
08-12 16:42:38.730 4736-4736/? D/TestPackageManager: Package name in 1000:com.mediatek.ppl
08-12 16:42:38.730 4736-4736/? D/TestPackageManager: Package name in 1000:com.android.location.fused
08-12 16:42:38.730 4736-4736/? D/TestPackageManager: Package name in 1000:com.mediatek.nlpservice
08-12 16:42:38.730 4736-4736/? D/TestPackageManager: Package name in 1000:com.mediatek.schpwronoff
08-12 16:42:38.730 4736-4736/? D/TestPackageManager: Package name in 1000:com.android.keychain
三、查询一个uid对应的名字
String getNameForUid (int uid);
    public void testGetNameForUid(){
        String name = mPm.getNameForUid(1000);
        Log.d(TAG,"Name for uid 1000 is:"+name);
    }

输出

08-13 16:55:05.207 8899-8899/? D/TestPackageManager: Name for uid 1000 is:android.uid.system:1000

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, 0, PackageManager.MATCH_ALL);
        if (pis != null) {
            for (ProviderInfo pri : pis) {
                Log.d(TAG, "Provider info:" + pri);
            }
        }
    }

输出

08-15 11:41:39.758 18259-18259/? D/TestPackageManager: Provider info:ContentProviderInfo{name=settings className=com.android.providers.settings.SettingsProvider}
08-15 11:41:39.758 18259-18259/? D/TestPackageManager: Provider info:ContentProviderInfo{name=com.tencent.mm.plugin.ext.NearBy className=com.tencent.mm.plugin.ext.provider.ExtControlProviderNearBy}
08-15 11:41:39.758 18259-18259/? 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。

08-15 14:23:59.909 18954-18954/? 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 = 0;
    // 系统程序
    public static final int FILTER_SYSTEM_APP = 1;
    // 第三方应用程序
    public static final int FILTER_THIRD_APP = 2;
    // 安装在SDCard的应用程序
    public static final int FILTER_SDCARD_APP = 3;

    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) != 0) {
                        getAppInfo(info);
                    }
                }
                break;
            case FILTER_THIRD_APP:
                for (ApplicationInfo info : list) {
                    if ((info.flags & ApplicationInfo.FLAG_SYSTEM) <= 0) {
                        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
这里写图片描述


参考文章

  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值