插件加载---之一
来源:互联网 发布:游戏程序员必看书籍 编辑:程序博客网 时间: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文件
中相关信息是,能方便的查询。
- 插件加载---之一
- android 插件加载机制之一
- 插件加载
- Wordpress 插件示例之一
- firefox插件开发之一
- Tapestry - 页面加载之一
- jquery插件之一 鼠标经过插件
- Jask动画切换插件之一
- 详解kettle插件开发之一
- python开发qgis插件之一
- android service插件化之一
- android contentprovider 插件化之一
- 【ListView】动态加载之一:滑动加载
- ImageLoader之一加载本地图片
- 网站加载优化方法之一
- Nutch插件加载分析
- 动态加载插件
- eclipse未加载插件
- Python起步之利用Turtle进行时钟绘制
- MAC地址小知识
- Spring统一异常处理之@ControllerAdvice 无法使用问题
- NGUI学习笔记(八):图片(UISprite)灰化效果
- 20、顺时针打印矩阵
- 插件加载---之一
- Linux下使用getopt函数来获取传入的参数
- Codeforces contest 295 recordings
- IPC之共享内存(3)
- Spring learn note
- 字符串匹配KMP算法
- Hibernate缓存总结
- 并发性:互斥和同步
- 进程总结