《Android插件化開(kāi)發(fā)指南》百度網(wǎng)盤(pán)pdf最新全集下載:
創(chuàng)新互聯(lián)-專(zhuān)業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價(jià)比慶云網(wǎng)站開(kāi)發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫(kù),直接使用。一站式慶云網(wǎng)站制作公司更省心,省錢(qián),快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋慶云地區(qū)。費(fèi)用合理售后完善,十年實(shí)體公司更值得信賴(lài)。
鏈接:
?pwd=qn54 提取碼: qn54
簡(jiǎn)介:本書(shū)不僅詳細(xì)介紹Android插件化技術(shù)如何實(shí)現(xiàn),而且包含大量Android系統(tǒng)的底層知識(shí),有助于App開(kāi)發(fā)人員深入理解Android系統(tǒng),從而寫(xiě)出更健壯的代碼。 ?
前面插件化一和二說(shuō)了下插樁式加載未安裝的APK,主要是重寫(xiě)了getResource和getClassloader兩個(gè)方法來(lái)實(shí)現(xiàn)的。以及每個(gè)組件要實(shí)現(xiàn)一個(gè)接口,通過(guò)接口注入上下文來(lái)達(dá)到它的生命周期。
那么插樁式和hook式的實(shí)現(xiàn)方式有什么不同呢?
插樁式是怎么加載到插件中的class文件呢,是通過(guò)將將APK轉(zhuǎn)化成插件的Classloader,然后想要加載插件的class文件,我們的去拿這個(gè)插件的classloader去loadClass。所以是有一個(gè)中間者的。
hook式呢是將插件apk融入到了我們的宿主apk,那直接在里面就可以直接loadClass了,在不用這個(gè)插件的ClassLoader了,這樣的話對(duì)于插件和宿主就沒(méi)什么區(qū)別了,不像插樁式有一個(gè)中間者。
那么要實(shí)現(xiàn)hook式 就要知道android中一個(gè)class文件式怎樣被加載到內(nèi)存中去的。其實(shí)就是通過(guò)PathClassLoader來(lái)加載的。
那么我們先看下ClassLoader
任何一個(gè)java程序都是由一個(gè)或者多個(gè)class組成的,在程序運(yùn)行時(shí),需要將class文件加載到JVM中才可以使用,負(fù)責(zé)加載這些class文件的就是java的類(lèi)加載機(jī)制。CLassLoader的作用就是加載class文件提供給程序運(yùn)行時(shí)使用,每個(gè)Class對(duì)象內(nèi)部都有一個(gè)ClassLoader來(lái)標(biāo)示自己是有那個(gè)classLoade加載的。
Android app的所有的java文件都是通過(guò)PathClassLoader來(lái)加載的,那么它的父類(lèi)是BaseDexClassLoader,還有一個(gè)兄弟類(lèi)是DexClassLoader,那么他們有什么區(qū)別呢。
從上面可以看出這兩個(gè)類(lèi)的構(gòu)造函數(shù)不同。(在26的源碼中DexClassLoader中的optimizedDirectory也廢棄了)
PathClassLoader:用于Android應(yīng)用程序類(lèi)加載器??梢约虞d指定的dex,以及jar、zip、apk中的classes.dex
DexClassLoader:加載指定的dex以及jar、zip、apk中的classes.dex。
可以看到創(chuàng)建ClassLoader的時(shí)候需要接收一個(gè)CLassLoader parent的參數(shù),這個(gè)parent的目的就在于實(shí)現(xiàn)類(lèi)加載的委托。
某個(gè)類(lèi)加載器在接到加載類(lèi)的請(qǐng)求時(shí),首先將加載任務(wù)委托給父類(lèi)加載器,一次遞歸,如果父加載器可以完成加載任務(wù),那么就返回,只有當(dāng)父加載器無(wú)法完成加載任務(wù)時(shí),才自己去加載。
因此我們自己創(chuàng)建的ClassLoader:newPathClassLoader("/sdcard/xx.dex",getClassLoader()),并不僅僅只能加載我們的xx.dex中的class。
需要注意的是,findBootstrapClassOrNull 這個(gè)方法,當(dāng)parent為null的時(shí)候,去這個(gè)BootCLassLoader進(jìn)行加載,
但是在Android當(dāng)中的實(shí)現(xiàn):
所以new PathClassLoader("/sdcard/xx.dex",null),是不能加載Activity.class的。
上面分析了加載了一個(gè)class,是利用了雙親委托機(jī)制,那么要是都找不到那就開(kāi)始調(diào)用自己的findCLass方法
在ClassLoader類(lèi)中findClass:
任何ClassLoader的子類(lèi),都可以重寫(xiě)loadClass和findClass。如果你不想使用雙親委托,就重寫(xiě)loadClas修改實(shí)現(xiàn),重寫(xiě)findClass則表示在雙親委托機(jī)制下,父ClassLoader都找不到class的情況下,定義自己去查找一個(gè)class。
而我們的PathClassLoader會(huì)自己負(fù)責(zé)加載Activity這樣的類(lèi),利用雙親委托父類(lèi)去加載activity,而我們的PathClassLoader沒(méi)有重寫(xiě)findClass,是在它的父類(lèi)里面。因此我們可以看看父類(lèi)的findClass是如何實(shí)現(xiàn)的。
可以看到加載PathClassLoader加載class,轉(zhuǎn)化為從DexPathList中加載class了,那么我們看看DexPathList中的findClass
那么從上面分析得到
到這里我們想要加載一個(gè)插件的apk ,其實(shí)最終加載的是一個(gè)dex文件(先說(shuō)class文件,加載資源后面說(shuō)),有沒(méi)有辦法吧這個(gè)dex文件給轉(zhuǎn)化成一個(gè) Element 對(duì)象,給放到 Elemeng數(shù)組 當(dāng)中,這樣直接就可以加載我們插件中的類(lèi)了。
1、首先我們肯定是要得到插件APK的的中DexPathList對(duì)象中的dexElement數(shù)組
2、插件的dexElements數(shù)組我們拿到了,那么是不是要開(kāi)始拿我們系統(tǒng)里面的 ,我們反射獲取,和上面的一樣。
3、上面我們獲取到了系統(tǒng)和我們插件的dexElement數(shù)組,然后我們將這個(gè)數(shù)組合并到一個(gè)新的數(shù)組里面去,并且給注入到系統(tǒng)里面
至此,加載插件的一個(gè)流程基本就完成了。但是上面只是處理了class文件,沒(méi)有處理資源。資源的話我們也是采用hook的方式去實(shí)現(xiàn)
在宿主的Application中hook這個(gè)方法,然后去重寫(xiě)getAsserts和getResources兩個(gè)方法:
然后在插件的BaseActivity中繼續(xù)重寫(xiě)getAssets和getResources兩個(gè)方法
這樣就可以完成hook式加載一個(gè)未安裝的APK了。至此基本就完成了插樁式和Hook式插件化的基本實(shí)現(xiàn)。(后面幾篇是優(yōu)化)。
原理:實(shí)現(xiàn)原理上都選擇盡量少的hook,通過(guò)在manifest上預(yù)埋一些組件實(shí)現(xiàn)四大組件的插件化。其中Small更形成了一個(gè)跨平臺(tái)、組件化的框架。
VirtulApp:
能夠完全模擬app的運(yùn)行環(huán)境,能夠?qū)崿F(xiàn)免安裝應(yīng)用和雙開(kāi)技術(shù)。
Atlas:
阿里出品,號(hào)稱(chēng)是一個(gè)容器化框架,結(jié)合了組件化和熱更新技術(shù)。
Android中有兩種類(lèi)加載器,DexClassLoader和PathClassLoader,它們都繼承于BaseDexClassLoader。
兩者的區(qū)別:DexClassLoader多了一個(gè)optimizedDirectory的路徑參數(shù),這個(gè)目錄必須是內(nèi)部存儲(chǔ)路徑,用于緩存系統(tǒng)創(chuàng)建的Dex文件。
所以我們可以使用DexClassLoader去加載外部Apk中的類(lèi)。
ClassLoader調(diào)用loadClass方法加載類(lèi)采用了雙親委托機(jī)制來(lái)避免重復(fù)加載類(lèi)。
首先,ClassLoader會(huì)查看自身已經(jīng)加載的類(lèi)中是否已經(jīng)存在此類(lèi),如不存在,然后,則會(huì)使用父類(lèi)來(lái)加載此類(lèi),如不能成功加載,則會(huì)使用自身重載于BaseDexClassLoader的findClass()方法來(lái)加載此類(lèi)。
DexClass的DexPathList在DexClass的構(gòu)造器中生成,findClass()方法則是從DexPathList下面找出對(duì)應(yīng)的DexFile,循環(huán)DexElements,通過(guò)dexElement.dexFile取出對(duì)應(yīng)的DexFile,再通過(guò)DexFile.loadClassBinaryName()加載對(duì)應(yīng)的類(lèi)。
作用:使用插件DexClassLoader加載出需要的類(lèi)。
通過(guò)每一個(gè)插件的DexClassLoader加載出自身所需要的類(lèi),當(dāng)每一個(gè)插件需要加載相同的類(lèi)庫(kù)時(shí),可采用該類(lèi)庫(kù)的不同版本來(lái)使用。
通過(guò)把每一個(gè)插件的pathList(DexFile)合并到主app的DexClassLoader上,來(lái)使各個(gè)插件和主app直接能夠相互調(diào)用類(lèi)和方法,并且各個(gè)插件中相同的功能可以抽取出來(lái)作為一個(gè)Common插件供其它插件使用。
插件調(diào)用主工程
在ClassLoader構(gòu)造時(shí)指定主工程的DexClassLoader為父加載器即可直接調(diào)用主工程中的類(lèi)和方法。
主工程調(diào)用插件
如果是多DexClassLoader的情況,則需要通過(guò)插件的DexClassLoader加載對(duì)應(yīng)的類(lèi)并反射調(diào)用其方法。此種情況,主工程一般會(huì)在一個(gè)統(tǒng)一的地方對(duì)訪問(wèn)插件中的類(lèi)和方法做一些訪問(wèn)權(quán)限的管理及配置。
如果是單DexClassLoader的情況,則可以直接調(diào)用插件中的類(lèi)和方法。但是當(dāng)多個(gè)插件引用的庫(kù)的版本不同時(shí),會(huì)出現(xiàn)錯(cuò)誤,因此,建議采用Gradle版本依賴(lài)管理統(tǒng)一處理主工程及各個(gè)插件的庫(kù)依賴(lài)。
Android通過(guò)Resource來(lái)加載資源,只要有插件apk,就可以使用assertManager.addAssertPath(apkPath)的方式來(lái)生成assertManager,再使用其new出對(duì)應(yīng)的Resource對(duì)象即可。
注意:由于AssertManager并不是Public,所以需要通過(guò)反射的方式去調(diào)用它。并且由于一些Rom對(duì)Resource的處理,所以,需要兼容處理。
有2種處理方式:
產(chǎn)生的原因:由于主工程和各個(gè)插件引用的Resource id重復(fù)產(chǎn)生的沖突。
解決思路:Android中的資源在系統(tǒng)中是以8位16進(jìn)制0XPPTTRRRR的方式存在,其中PP即是資源區(qū)分的區(qū)域(Android系統(tǒng)只用它來(lái)區(qū)分系統(tǒng)資源和應(yīng)用資源),只要讓每一個(gè)插件的PP段取不同的值即可解決資源id沖突的問(wèn)題。
具體解決方式:
1.修改aapt源碼,編譯期修改PP段。
2.修改Resource的arsc文件,其中的每一條都包含了資源id和映射路徑。
Activity的處理最為復(fù)雜,有兩種處理方式:
1.ProxyActivity的方式。
2.預(yù)埋StubActivity,hook系統(tǒng)啟動(dòng)Activity的過(guò)程。
原理:VirtualAPK通過(guò)替換了系統(tǒng)的Instrumentation,hook了Activity的啟動(dòng)和創(chuàng)建,省去了手動(dòng)管理插件Activity生命周期的繁瑣,讓插件Activity像正常的Activity一樣被系統(tǒng)管理,并且插件Activity在開(kāi)發(fā)時(shí)和常規(guī)一樣,即能獨(dú)立運(yùn)行又能作為插件被主工程調(diào)用。
Android插件化方向主要有2個(gè)方向:
Android 插件化
文章題目:android插件化,android插件化開(kāi)發(fā)
URL網(wǎng)址:http://chinadenli.net/article46/dsdejhg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供小程序開(kāi)發(fā)、外貿(mào)網(wǎng)站建設(shè)、網(wǎng)站建設(shè)、定制開(kāi)發(fā)、關(guān)鍵詞優(yōu)化、自適應(yīng)網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)