在Android 插件化技術中(宿主app和插件app設置相同的sharedUserId),動態載入apk有兩種方式: 一種是將資源主題包的apk安裝到手機上再讀取apk內的資源,這種方式的原理是將宿主app和插件app設置相同的sharedUserId,這樣兩個app將會在同一個進程中運行,並可以 ...
在Android 插件化技術中(宿主app和插件app設置相同的sharedUserId),動態載入apk有兩種方式:
- 一種是將資源主題包的apk安裝到手機上再讀取apk內的資源,這種方式的原理是將宿主app和插件app設置相同的sharedUserId,這樣兩個app將會在同一個進程中運行,並可以相互訪問內部資源了。
- 一種是不用安裝資源apk的方式。其原理是通過DexClassLoader類載入器去載入指定路徑下的apk、dex或者jar文件,反射出R類中相應的內部類然後根據資源名來獲取我們需要的資源id,然後根據資源id得到對應的圖片或者xml文件。
下麵介紹幾種常見的方法獲取資源以及代碼的方法。
- 獲取已安裝的APK中的資源
利用Context的createPackageContext方法,可以創建另外一個包的上下文,裡面有兩個參數packageName包名,flags 標誌位(CONTEXT_INCLUDE_CODE、CONTEXT_IGNORE_SECURITY)
用法如下
try { context = createPackageContext("com.test.resource", Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY); textView.setText(context.getResources().getText(R.string.message)); } catch (NameNotFoundException e) { e.printStackTrace(); }
- 獲取未安裝的APK中的資源
新建一個獲取資源的介面,傳入插件APK的路徑返回Resources對象
// 獲取插件apk的Resources對象 public Resources getBundleResource(Context context, String apkPath) { AssetManager assetManager = createAssetManager(apkPath); return new Resources(assetManager, context.getResources().getDisplayMetrics(), context.getResources().getConfiguration()); } private AssetManager createAssetManager(String apkPath) { try { AssetManager assetManager = AssetManager.class.newInstance(); AssetManager.class.getDeclaredMethod("addAssetPath", String.class) .invoke(assetManager, apkPath); return assetManager; } catch (Throwable th) { th.printStackTrace(); } return null; }
獲得了Resource 對象之後,就可以通過函數resources.getDrawable、resources.getString、resources.getLayout 獲取圖片、字元串、佈局文件了。
- 獲取插件APK的代碼
參考博客Android 熱修複原理解析