我们知道程序信息存储在Androidmanifest.xml文件中
SDK提供了PackageInfo类,该类包含了从Androidmanifest.xml文件中收集的所有信息。
查看PackageInfo源码
//PackageInfo进行了序列化,可在进程间传递
public class PackageInfo implements Parcelable {
//程序包名
public String packageName;
//版本名
public String versionName;
//版本号
public int versionCode;
//共享用户ID,签名相同的情况下程序之间数据共享
public String sharedUserId;
//安装时间,忽略之前安装后卸载情况,单位ms
public long firstInstallTime
//最后更新时间,单位ms,经验证版本号相同的APK覆盖安装,该值也是会发生变化的
public long lastUpdateTime
//请求的权限
public String[] requestedPermissions;
//<Application .../>中的信息,程序名,icon等
public ApplicationInfo applicationInfo;
//注册的Activity
public ActivityInfo[] activities;
//注册的广播
public ActivityInfo[] receivers;
//注册的服务
public ServiceInfo[] services;
//注册的Contentprovider
public ProviderInfo[] providers;
}
PackageInfo的子类ApplicationInfo中封装了:
程序名称
程序图标等信息
如何获取这些信息的呢?
查看ApplicationInfo源码
//ApplicationInfo类的继承关系,进行了序列化,可在进程间传递
public class ApplicationInfo extends PackageItemInfo implements Parcelable {
//ApplicationInfo类中的属性
public int flags = 0;
//判断是否是系统程序用到的常量,这里为什么用<<(逻辑左移)没搞明白,计算后的值十进制还是1
public static final int FLAG_SYSTEM = 1<<0;
/**判断是否是系统程序计算方法,
(flags & ApplicationInfo.FLAG_SYSTEM) != 0表示是系统程序*/
}
ApplicationInfo继承PackageItemInfo类。
查看PackageItemInfo源码
//具体实现方法封装在父类PackageItemInfo类中
public class PackageItemInfo {
//获取程序名称
public CharSequence loadLabel(PackageManager pm);
//获取程序图标
public Drawable loadIcon(PackageManager pm);
}
知道了程序信息封装在PackageInfo类中。如何获取PackageInfo对象?
SDK提供了包管理类PackageManager,负责获取PackageInfo对象的。
查看PackageManager源码
public abstract class PackageManager {//是一个抽象类
/**以下都是抽象方法*/
//第一个参数:包名 ;第二个参数:为附加条件选项(如:GET_CONFIGURATIONS获取配置)
PackageInfo getPackageInfo(String packageName, int flags);
//获取已安装程序信息对象的列表
List<PackageInfo> getInstalledPackages(int flags);
//根据程序申请的权限过滤,申请某些特定权限的程序
List<PackageInfo> getPackagesHoldingPermissions(String[] permissions,
int flags);
List<PackageInfo> getPreferredPackages(int flags);
//获取程序大小,遗憾是@hide方法,只能通过反射机制调用
void getPackageSizeInfo(String packageName, IPackageStatsObserver observer);
}
获取程序大小请移步到另一篇文章,详细讲解获取程序大小
具体实现,这篇文章不去详细讲解。
我们需要追踪到哪个类中可获取该对象实例即可,查看源码,
ContextWrapper类中提供获取PackageManager对象的函数
//ContextWrapper类中getPackageManager函数可获取到PackageManager对象
public class ContextWrapper extends Context {
public PackageManager getPackageManager() {
return mBase.getPackageManager();
}
}
ContextWrapper类的子类
//从以下继承关系可以知道这些对象都可直接调用getPackageManager方法得到PackageManager对象
class Application extends ContextWrapper;
class ContextThemeWrapper extends ContextWrapper;
class Activity extends ContextThemeWrapper;
//Service为抽象类,需要实现Service调用getPackageManager方法获取PackageManager对象
public abstract class Service extends ContextWrapper;
开发中常遇到以下两种情形:
- 1知道包名,获取该程序的信息
- 2获取已安装的程序信息
获取包管理类PackageManager
// Application Activity Service中都可直接调用getPackageManager()方法获取PackageManager
PackageManager pm ;
pm= Application.getPackageManager();
pm = Activity.getPackageManager();
pm = Service.getPackageManager();
包管理对象获取程序信息
// 知道包名,获取该程序信息
PackageInfo pi = pm.getPackageInfo(packageName,PackageManager.GET_CONFIGURATIONS);
//获取设备上安装的程序信息
//PackageManager.GET_UNINSTALLED_PACKAGES常量代表已经卸载的也会收集到
List<PackageInfo> apps;
apps = pm.getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES);
获取到PackageInfo对象,任务完成,获取你想要的数据吧。