真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Androidso庫的熱更新問題

本來想寫資源的熱修復(fù)的,雖然方案差不多已經(jīng)完成了,但是考慮到一些敏感問題,資源修復(fù)就不寫了。那就來寫寫so的熱修復(fù),其原理和class的修復(fù)是一樣的,但是so的熱修復(fù)的需求并不高,就當(dāng)做學(xué)習(xí)吧。

成都創(chuàng)新互聯(lián)專注于網(wǎng)站建設(shè)|網(wǎng)站建設(shè)維護(hù)|優(yōu)化|托管以及網(wǎng)絡(luò)推廣,積累了大量的網(wǎng)站設(shè)計(jì)與制作經(jīng)驗(yàn),為許多企業(yè)提供了網(wǎng)站定制設(shè)計(jì)服務(wù),案例作品覆蓋成都陽光房等行業(yè)。能根據(jù)企業(yè)所處的行業(yè)與銷售的產(chǎn)品,結(jié)合品牌形象的塑造,量身制作品質(zhì)網(wǎng)站。

首先來總結(jié)一下Android的ClassLoader方式的熱更新,這種方式類的查找過程是通過BaseDexClassLoader來完成的,最終會(huì)通過成員變量DexPathList對(duì)象中的findClass方法來查找類,代碼如下:

public Class findClass(String name, List suppressed) {
  for (Element element : dexElements) {
    DexFile dex = element.dexFile;
    if (dex != null) {
      Class clazz = dex.loadClassBinaryName(name, definingContext, suppressed);
      if (clazz != null) {
        return clazz;
      }
    }
  }
  if (dexElementsSuppressedExceptions != null) {
    suppressed.addAll(Arrays.asList(dexElementsSuppressedExceptions));
  }
  return null;
}

只需將patch的class插入到dexElements最前面即可完成熱更新,當(dāng)然還需要防止類被打上校驗(yàn)的標(biāo)記,做法就是在class中插入一段字節(jié)碼引用其他dex中的類。

參考class的修復(fù)方式,我們可以在BaseDexClassLoader中找到加載so的邏輯。

@Override
public String findLibrary(String name) {
  return pathList.findLibrary(name);
}

最終也會(huì)調(diào)用DexPathList對(duì)象中的方法進(jìn)行處理,其函數(shù)內(nèi)容為

public String findLibrary(String libraryName) {
  String fileName = System.mapLibraryName(libraryName);
  for (File directory : nativeLibraryDirectories) {
    String path = new File(directory, fileName).getPath();
    if (IoUtils.canOpenReadOnly(path)) {
      return path;
    }
  }
  return null;
}

可以看到邏輯和class是類似的,首先會(huì)調(diào)用System.mapLibraryName函數(shù)獲得so的名字,比如我傳入的參數(shù)是Test(這個(gè)Test就是在調(diào)用System.loadLibrary(“Test”)時(shí)傳入的),則這個(gè)函數(shù)的作用就是將其轉(zhuǎn)換為類似libTest.so這樣的名字,然后遍歷nativeLibraryDirectories數(shù)組,這是一個(gè)File文件夾數(shù)組,看其文件夾下是否存在對(duì)應(yīng)的so,并且是否可讀,如果滿足條件,則直接返回。

那么我們就可以將我們的patch的so所在目錄插入到這個(gè)數(shù)組最前面即可完成so的修復(fù)。具體代碼就不貼了,實(shí)踐后得出的結(jié)論是這種方式是完全可行的,只不過Android 6.0中這部分代碼邏輯發(fā)生了改變。

在Android 4.0-5.1中,只需要將文件夾目錄插入到nativeLibraryDirectories數(shù)組最前面即可,這個(gè)過程直接使用反射插入patch的so所在目錄到數(shù)組最前面。

/** List of native library directories. */
private final File[] nativeLibraryDirectories;

但是在Android 6.0中,查找邏輯轉(zhuǎn)為了Elements查找

/** List of native library path elements. */
private final Element[] nativeLibraryPathElements;
public String findLibrary(String libraryName) {
  String fileName = System.mapLibraryName(libraryName);
  for (Element element : nativeLibraryPathElements) {
    String path = element.findNativeLibrary(fileName);
    if (path != null) {
      return path;
    }
  }
  return null;
}

所以在6.0中需要將so的patch目錄轉(zhuǎn)換為Element對(duì)象,插入到nativeLibraryPathElements最前面,Element的對(duì)象可以直接用反射去實(shí)現(xiàn)下面的代碼進(jìn)行構(gòu)造即可。

//偽代碼,類不可見,需要用反射
Element e=new Element(fileDir, true, null, null)

當(dāng)然你也可以直接反射調(diào)用makePathElements方法創(chuàng)建Element數(shù)組。

最后的難點(diǎn)就是如何將對(duì)應(yīng)cpu類型的so拿到,這個(gè)過程還是十分復(fù)雜的,比如說一個(gè)so同時(shí)存在x86,armeabi-v7a,armeabi的patch,而手機(jī)cpu是armeabi-v7a的,這時(shí)候就應(yīng)該加載armeabi-v7a的so??傊@種情況組合起來會(huì)十分復(fù)雜了。

手機(jī)的cpu結(jié)構(gòu)類型可以通過Build.CPU_ABI和Build.CPU_ABI2拿到,后面做的事就是根據(jù)這兩個(gè)值去加載對(duì)應(yīng)目錄下的so,其實(shí)把這兩個(gè)目錄都插進(jìn)去就沒問題了。

總結(jié)

以上所述是小編給大家介紹的Android so庫的熱更新問題,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)創(chuàng)新互聯(lián)網(wǎng)站的支持!


網(wǎng)頁名稱:Androidso庫的熱更新問題
路徑分享:http://weahome.cn/article/pdgsgc.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部