插件加载---之一

来源:互联网 发布:游戏程序员必看书籍 编辑:程序博客网 时间:2024/06/13 21:48

7,插件加载

插件其实是Apk安装包,如果要使用必须先要安装和解析,以便知道插件Apk的相关信息。

1,安装、更新插件,使用如下方法:

int PluginManager.getInstance().installPackage(String filepath, int flags)

2, 卸载插件,使用如下方法:

int PluginManager.getInstance().deletePackage(String packageName,int flags);

说明:从插件系统中卸载某个插件,packageName传插件包名即可,flags传0。

7.1 插件加载过程概述

加载插件会调用PluginManager的installPackage方法,该方法如下,

int result = mPluginManager.installPackage(filepath, flags);

直接调用IpluginManagerImpl的installPackage方法, installPackage主要包括插件的替换或者安装。替换过程在此就不论述了,

主要是安装过程。安装过程的主要逻辑如下,

1,获取插件的文件

apkfile = PluginDirHelper.getPluginApkFile(mContext, info.packageName);

2,调用forceStopPackage()停止要安装插件的进程,这个函数其实是通过ActivityManagerService获取当前系统中正在运行的进程,

然后在进程列表中查找插件包名是否已经运行在进程中,如果是这kill掉此进程。删除/data/data/宿主进程报名/plugin/plugin包名

/apk/base-1.apk文件,将要安装的插件apk复制到刚刚删除的Apk文件中。

forceStopPackage(info.packageName);

3, 创建PluginPackageParser 类对象parser完成插件Apk文件的解析工作。

PluginPackageParser parser = new PluginPackageParser(mContext, new File(apkfile));

4,权限检查,

PackageInfo pkgInfo = parser.getPackageInfo(PackageManager.GET_PERMISSIONS | PackageManager.GET_SIGNATURES);if (pkgInfo != null && pkgInfo.requestedPermissions != null && pkgInfo.requestedPermissions.length > 0) {      for (String requestedPermission : pkgInfo.requestedPermissions) {            boolean b = false;            try {               b = pm.getPermissionInfo(requestedPermission, 0) != null;            } catch (NameNotFoundException e) {            }          if (!mHostRequestedPermission.contains(requestedPermission) && b) {            Log.e(TAG, "No Permission %s", requestedPermission);            new File(apkfile).delete();            return PluginManager.INSTALL_FAILED_NO_REQUESTEDPERMISSION;      }  }}saveSignatures(pkgInfo);

通过parser获取搜集插件Apk签名信息和需要的权限,并检查插件Apk所需要的权限是否已经在宿主进程权限声明,

如果没有则结束插件安装,提示安装失败,并删除相关之前复制的插件Apk文件。(也就是说插件Apk文件,要声明的权限

必须要在宿主进程中预先声明,才行。)

解析成功之后,保存插件Apk的签名。

5, 将插件Apk文件中的Lib目录下的so包保存到/data/data/宿主进程报名/plugin/plugin包名/lib文件中.

copyNativeLibs(mContext, apkfile, parser.getApplicationInfo(0));dexOpt(mContext, apkfile, parser);mPluginCache.put(parser.getPackageName(), parser);

调用dexOpt()通过PluginClassLoader解压Apk保存Apk dex文件和library文件到/data/data/宿主进程包名/plugin/plugin包名

/lib和/data/data/宿主进程报名/plugin/plugin包名/dalvik-cache目录下面。

将插件包名以及PluginPackageParser 的对象parser在mPluginCache中。

dexOpt方法如下,

private void dexOpt(Context hostContext, String apkfile, PluginPackageParser parser) throws Exception {  String packageName = parser.getPackageName();  String optimizedDirectory = PluginDirHelper.getPluginDalvikCacheDir(hostContext, packageName);  String libraryPath = PluginDirHelper.getPluginNativeLibraryDir(hostContext, packageName);  ClassLoader classloader = new PluginClassLoader(apkfile, optimizedDirectory, libraryPath, ClassLoader.getSystemClassLoader());}

ClassLoader机制在此就不论述了。在构造PluginClassLoader过程中完成插件apk的加载。

6, 发送插件安装成功的广播,插件安装完成。

sendInstalledBroadcast(info.packageName);

sendInstalledBroadcast方法如下,

private void sendInstalledBroadcast(String packageName) {    Intent intent = new Intent(PluginManager.ACTION_PACKAGE_ADDED);    intent.setData(Uri.parse("package://" + packageName));    mContext.sendBroadcast(intent);}

这几个步骤中,最主要的是插件apk解析过程, PluginPackageParser主要模仿android系统PMS解析过程。主要包括四大组件等信息。

7.2 PluginPackageParser分析

PluginPackageParser的主要变量如下,

private final File mPluginFile;//插件文件private final PackageParser mParser;// PackageParser对象,真正解析的类private final String mPackageName;//插件包名private final Context mHostContext;//进程上下文private final PackageInfo mHostPackageInfo;//宿主包名

private Map<ComponentName, Object> mActivityObjCache = new TreeMap<ComponentName, Object>(new ComponentNameComparator());private Map<ComponentName, Object> mServiceObjCache = new TreeMap<ComponentName, Object>(new ComponentNameComparator());private Map<ComponentName, Object> mProviderObjCache = new TreeMap<ComponentName, Object>(new ComponentNameComparator());private Map<ComponentName, Object> mReceiversObjCache = new TreeMap<ComponentName, Object>(new ComponentNameComparator());private Map<ComponentName, Object> mInstrumentationObjCache = new TreeMap<ComponentName, Object>(new ComponentNameComparator());private Map<ComponentName, Object> mPermissionsObjCache = new TreeMap<ComponentName, Object>(new ComponentNameComparator());private Map<ComponentName, Object> mPermissionGroupObjCache = new TreeMap<ComponentName, Object>(new ComponentNameComparator());private ArrayList<String> mRequestedPermissionsCache = new ArrayList<String>();

这几个变量主要保存解析插件Apk后Package对象内部对应的Activity,Service, Provider,Receiver等对应的数据(包名等信息)。

private Map<ComponentName, List<IntentFilter>> mActivityIntentFilterCache = new TreeMap<ComponentName, List<IntentFilter>>(new ComponentNameComparator());private Map<ComponentName, List<IntentFilter>> mServiceIntentFilterCache = new TreeMap<ComponentName, List<IntentFilter>>(new ComponentNameComparator());private Map<ComponentName, List<IntentFilter>> mProviderIntentFilterCache = new TreeMap<ComponentName, List<IntentFilter>>(new ComponentNameComparator());private Map<ComponentName, List<IntentFilter>> mReceiverIntentFilterCache = new TreeMap<ComponentName, List<IntentFilter>>(new ComponentNameComparator());

这四个变量主要保存四大组件ComponentName对应的IntentFilter。

private Map<ComponentName, ActivityInfo> mActivityInfoCache = new TreeMap<ComponentName, ActivityInfo>(new ComponentNameComparator());private Map<ComponentName, ServiceInfo> mServiceInfoCache = new TreeMap<ComponentName, ServiceInfo>(new ComponentNameComparator());private Map<ComponentName, ProviderInfo> mProviderInfoCache = new TreeMap<ComponentName, ProviderInfo>(new ComponentNameComparator());private Map<ComponentName, ActivityInfo> mReceiversInfoCache = new TreeMap<ComponentName, ActivityInfo>(new ComponentNameComparator());private Map<ComponentName, InstrumentationInfo> mInstrumentationInfoCache = new TreeMap<ComponentName, InstrumentationInfo>(new ComponentNameComparator());private Map<ComponentName, PermissionGroupInfo> mPermissionGroupInfoCache = new TreeMap<ComponentName, PermissionGroupInfo>(new ComponentNameComparator());private Map<ComponentName, PermissionInfo> mPermissionsInfoCache = new TreeMap<ComponentName, PermissionInfo>(new ComponentNameComparator());

保存四大组件等的相关信息, 之所以要保存这些信息,其实是效仿PackageManagerService,PackageManagerService不仅承担安装

解析AndroidManifest还保存了文件中定义四大组件等相关的信息,并提供了这些信息的查询,而的插件并没有安装到系统中,是无法

通过PackageManagerService中查到的,这个时候需要Hook PackageManagerService这样需要查询或者获取插件AndroidManifest文件

中相关信息是,能方便的查询。

原创粉丝点击