activity插件化hook

動態(tài)加載:

加載已安裝和未安裝的apk

動態(tài)加載技術(shù)就是使用類加載器加載相應(yīng)的apk思劳、dex呆细、jar(必須含有dex文件)侨嘀,再通過反射獲得該apk臭挽、dex、jar內(nèi)部的資源

(class咬腕、圖片欢峰、color等等)進(jìn)而供宿主app使用。

PathClassLoader 獲取已安裝的apk

linux user id宿主app和插件app的manifest上都定義一個相同的sharedUserId

PackageInfo.sharedUserId

獲取手機(jī)內(nèi)存在的所有插件涨共,沒有找到則提示去下載

/第一個參數(shù)為包含dex的apk或者jar的路徑纽帖,第二個參數(shù)為父加載器

PathClassLoader pathClassLoader = new PathClassLoader(pluginContext.getPackageResourcePath

(),ClassLoader.getSystemClassLoader());

兩種方式獲取

1、Class<?> clazz = pathClassLoader.loadClass(packageName + ".R$mipmap");//通過使用自身的加載器反射出mipmap類進(jìn)而使用

該類的功能

2举反、//參數(shù):1懊直、類的全名,2火鼻、是否初始化類室囊,3、加載時使用的類加載器

Class<?> clazz = Class.forName(packageName + ".R$mipmap", true, pathClassLoader);

Field field = clazz.getDeclaredField("one");

int resourceId = field.getInt(R.mipmap.class);

創(chuàng)建插件的上下文

Context plugnContext = this.createPackageContext(packageName, CONTEXT_IGNORE_SECURITY | CONTEXT_INCLUDE_CODE);

DexClassLoader不需要提前安裝apk

首先我們得到事先知道我們的插件apk存放在哪個目錄下魁索,然后分別得到插件apk的信息(名稱融撞、包名等),然后顯示可用的插件粗蔚,最

后動態(tài)加載apk獲得資源

1尝偎、獲取未安裝的apk信息public PackageInfo getPackageArchiveInfo(String archiveFilePath, int flags)

? private String[] getUninstallApkInfo(Context context, String archiveFilePath) {

? ? ? ? String[] info = new String[2];

? ? ? ? PackageManager pm = context.getPackageManager();

? ? ? ? PackageInfo pkgInfo = pm.getPackageArchiveInfo(archiveFilePath, PackageManager.GET_ACTIVITIES);

? ? ? ? if (pkgInfo != null) {

? ? ? ? ? ? ApplicationInfo appInfo = pkgInfo.applicationInfo;

? ? ? ? ? ? String versionName = pkgInfo.versionName;//版本號

? ? ? ? ? ? Drawable icon = pm.getApplicationIcon(appInfo);//圖標(biāo)

? ? ? ? ? ? String appName = pm.getApplicationLabel(appInfo).toString();//app名稱

? ? ? ? ? ? String pkgName = appInfo.packageName;//包名

? ? ? ? ? ? info[0] = appName;

? ? ? ? ? ? info[1] = pkgName;

? ? ? ? }

? ? ? ? return info;

2、得到對應(yīng)未安裝apk的Resource對象鹏控,我們需要通過反射來獲得:反射調(diào)用addAssetPath致扯,將未安裝的Apk文件的添加進(jìn)

AssetManager中趁窃,第二個參數(shù)為apk文件的路徑帶apk名

通過得到AssetManager中的內(nèi)部的方法addAssetPath,將未安裝的apk路徑傳入從而添加進(jìn)assetManager中急前,然后通過new Resource把

assetManager傳入構(gòu)造方法中醒陆,進(jìn)而得到未安裝apk對應(yīng)的Resource對象。

? private Resources getPluginResources(String apkName) {

? ? ? ? try {

? ? ? ? ? ? AssetManager assetManager = AssetManager.class.newInstance();

? ? ? ? ? ? Method addAssetPath = assetManager.getClass().getMethod("addAssetPath", String.class);//反射調(diào)用方法

addAssetPath(String path)

? ? ? ? ? ? //第二個參數(shù)是apk的路徑:Environment.getExternalStorageDirectory().getPath()+File.separator

+"plugin"+File.separator+"apkplugin.apk"

? ? ? ? ? ? addAssetPath.invoke(assetManager, apkDir+File.separator+apkName);//將未安裝的Apk文件的添加進(jìn)AssetManager

中裆针,第二個參數(shù)為apk文件的路徑帶apk名

? ? ? ? ? ? Resources superRes = this.getResources();

? ? ? ? ? ? Resources mResources = new Resources(assetManager, superRes.getDisplayMetrics(),

? ? ? ? ? ? ? ? ? ? superRes.getConfiguration());

? ? ? ? ? ? return mResources;

? ? ? ? } catch (Exception e) {

? ? ? ? ? ? e.printStackTrace();

? ? ? ? }

? ? ? ? return null;

3刨摩、加載未安裝的apk獲得它的內(nèi)部資源

? /**

? ? * 加載apk獲得內(nèi)部資源

? ? * @param apkDir apk目錄

? ? * @param apkName apk名字,帶.apk

? ? * @throws Exception

? ? */

? ? private void dynamicLoadApk(String apkDir, String apkName, String apkPackageName) throws Exception {

? ? ? ? File optimizedDirectoryFile = getDir("dex", Context.MODE_PRIVATE);//在應(yīng)用安裝目錄下創(chuàng)建一個名為app_dex文件夾

目錄,如果已經(jīng)存在則不創(chuàng)建

? ? ? ? Log.v("zxy", optimizedDirectoryFile.getPath().toString());// /data/data/com.example.dynamicloadapk/app_dex

? ? ? ? //參數(shù):1、包含dex的apk文件或jar文件的路徑世吨,2澡刹、apk、jar解壓縮生成dex存儲的目錄耘婚,3罢浇、本地library庫目錄,一般為

null沐祷,4嚷闭、父ClassLoader

? ? ? ? DexClassLoader dexClassLoader = new DexClassLoader(apkDir+File.separator+apkName,

optimizedDirectoryFile.getPath(), null, ClassLoader.getSystemClassLoader());

? ? ? ? Class<?> clazz = dexClassLoader.loadClass(apkPackageName + ".R$mipmap");//通過使用apk自己的類加載器,反射出R

類中相應(yīng)的內(nèi)部類進(jìn)而獲取我們需要的資源id

? ? ? ? Field field = clazz.getDeclaredField("one");//得到名為one的這張圖片字段

? ? ? ? int resId = field.getInt(R.id.class);//得到圖片id

? ? ? ? Resources mResources = getPluginResources(apkName);//得到插件apk中的Resource

? ? ? ? if (mResources != null) {

? ? ? ? ? ? //通過插件apk中的Resource得到resId對應(yīng)的資源

? ? ? ? ? ? findViewById(R.id.background).setBackgroundDrawable(mResources.getDrawable(resId));

? ? ? ? }

首先通過類加載器去加載apk中activity的類并創(chuàng)建一個新對象赖临,然后通過反射去調(diào)用這個對象的setProxy方法和onCreate方法胞锰,

setProxy方法的作用是將activity內(nèi)部的執(zhí)行全部交由宿主程序中的proxy(也是一個activity),onCreate方法是activity的入口兢榨,

setProxy以后就調(diào)用onCreate方法嗅榕,這個時候activity就被調(diào)起來了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末吵聪,一起剝皮案震驚了整個濱河市凌那,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌吟逝,老刑警劉巖帽蝶,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異澎办,居然都是意外死亡嘲碱,警方通過查閱死者的電腦和手機(jī)金砍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進(jìn)店門局蚀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人恕稠,你說我怎么就攤上這事琅绅。” “怎么了鹅巍?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵千扶,是天一觀的道長料祠。 經(jīng)常有香客問我,道長澎羞,這世上最難降的妖魔是什么髓绽? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮妆绞,結(jié)果婚禮上顺呕,老公的妹妹穿的比我還像新娘。我一直安慰自己括饶,他們只是感情好株茶,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著图焰,像睡著了一般启盛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上技羔,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天僵闯,我揣著相機(jī)與錄音,去河邊找鬼藤滥。 笑死棍厂,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的超陆。 我是一名探鬼主播牺弹,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼时呀!你這毒婦竟也來了张漂?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤谨娜,失蹤者是張志新(化名)和其女友劉穎航攒,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體趴梢,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡漠畜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了坞靶。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片憔狞。...
    茶點(diǎn)故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖彰阴,靈堂內(nèi)的尸體忽然破棺而出瘾敢,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布簇抵,位于F島的核電站庆杜,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏碟摆。R本人自食惡果不足惜晃财,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望典蜕。 院中可真熱鬧拓劝,春花似錦、人聲如沸嘉裤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽屑宠。三九已至厢洞,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間典奉,已是汗流浹背躺翻。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留卫玖,地道東北人公你。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像假瞬,于是被迫代替她去往敵國和親陕靠。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評論 2 355