插件化开发之获取APK的代码与资源"/>
Android 插件化开发之获取APK的代码与资源
插件化开发,可以分为3种形式:1,通过下载zip文件来应用资源。2,通过下载并安装APK来应用资源。3,通过下载但不安装APK的方式来应用资源。 第一种比较简单,就不做介绍了。
- 获取已安装的APK中的资源和代码
- 获取未安装的APK中的资源和代码
1.获取已安装的APK中的资源和代码
1.1获取插件APK的Context
Context packageContext = createPackageContext(pkName, Context.CONTEXT_INCLUDE_CODE| Context.CONTEXT_IGNORE_SECURITY)
1.2.获取代码
根据该Context获取到ClassLoader,有了ClassLoader,我们也可以去反射APK中的代码,然后就可以为所欲为了。(混淆类或者类方法被混淆,就无能为力了)
1.3.获取资源
根据该Context获取到Resource,有了Resource对象,我们就可以去加载插件APK中的资源文件。获取资源过程需要资源ID,但是主程序如何获取到插件APK的资源ID呢?方式有几种:
1.插件APK将ID保存在SharePreference等中并设置和主程序使用相同的shareUserId和签名,然后主程序去获取该ID。
2.通过反射R.java中的静态类(如drawable类),获取想要的某field值(如ic_launcher)。(混淆R文件或者混淆R文件中的静态类,就无能为力了)
3.通过getResources().getIdentifier(drawableName, “drawable”,context.getPackageName())方式获取。
2获取未安装的APK中的资源和代码
安卓中context.getResource()获取到的Resource对象其实是指向当前程序在沙盒(/data/data/程序包名.apk)中的apk,该resource只能获取当前程序的资源,无法获取到其他程序的资源。这就需要我们想办法得到一个能获取其他apk资源的Resource对象。跟踪context.getResource()源码会发现,内部有一段代码大致意思如下
AssetManager assetManager = new AssetManager();
…
assetManager.addAssetPath()//该方法需要传入assetPath,该assetPath就是context对应的ApplicationInfo.sourceDir值(即/data/data/程序包名.apk)。
依照该思路,我们加入未安装的apk的path进去,并创建一个新Resource对象,该对象就能获取插件APK中的资源对象了。
2.1.获取指向插件APK的Resource对象
AssetManager assetManager = AssetManager.class.newInstance(); Method addAssetPath = assetManager.getClass().getMethod("addAssetPath", String.class); addAssetPath.invoke(assetManager, dexPath_tmp); Resources superRes = mContext.getResources(); Resources skinResource=new Resources(assetManager, superRes.getDisplayMetrics(), superRes.getConfiguration());
2.2.获取插件APK的代码
通过DexClassLoader来加载未安装的APK的类,并执行相关代码
更多推荐
Android 插件化开发之获取APK的代码与资源
发布评论