CrossWalk - android 動態加載so庫文件實踐

以前看到簡書Android客戶端使用的編輯器,甚是喜歡,它的優雅以及高性能的特色讓我愛不釋手,很想本身也去作一個。
此前實現過一個在Android上的Markdown編輯器
可是界面以及所見即所得的效果很是很差看,因此一直耿耿於懷。java

而後冒昧看了下簡書的佈局系統,看見了幾個奇怪的類,包括相似XWalkContentView,因而Google了下,就查到了CrossWalk這個hybrid框架了。第一眼並不以爲它有啥不同,覺得是一個Cordova的輪子。後來細看,發現是自個兒編輯了整個Chrominum,屌屌屌!git

運行個demo,wrapper了一個http://sf.gg 發現體驗真的是不錯啊,webview性能到這個水平心裏都寬慰了,可是爲什麼安裝速度那麼慢呢?一看apk大小,足足有40M+,感受天都要塌了。SegmentFault for Android 客戶端才3.03M,我要是包上這玩意,估計就沒多少人下了吧。。。而後又看看簡書,整個apk大小才8M,在啓動編輯器的時候,提示須要下載編輯器,下載了一會,而後再打開。頓時就明白了,看來它的庫是從外部載入的,記得之前看到過從外部加載動態連接庫想一想非常簡單,因而入坑了。github

好嘛,我把so文件先不放進apk中,讓apk裝好以後,放入/data/data/<app>/lib目錄下,啓動app,直接crash。
看日誌入下:web

DavlikDexClassLoader Unsatisfied Link library['/xxxx/xxx.apk', '/vendor/lib', '/system/lib']app

一看這個路徑,淚奔了,原來library path只有三個路徑下去檢查,算了,咱們不是有System.loadSystem.loadLibrary函數麼,直接調用唄,因而我就先暫時把絕對路徑給寫了下來,直接調用System.load函數。框架

再次啓動,發現CrossWalkShared Library should use SharedXWalkView。可是使用SharedXWalkView有許多的限制,好比須要安裝一個CrossWalk Runtime的apk,奇怪了,它怎麼知道我是用Shared Library的呢?並且簡書也沒有說要安裝apk啊。編輯器

因而我繼續研究,開始看CrossWalk的源碼,找到ReflectionHelper這個類裏面有一行代碼shouldUseLibrary(),它會去調用System.loadLibrary()若是沒有報異常,則返回false,不然返回true函數

咱們知道System.loadLibrary這個函數,會去java.library.path這個環境變量的路徑下面尋找庫,而Android是不容許咱們更改這個環境變量的值的,就致使CrossWalk認爲並無加載它的runtime而去開啓Shared模式。佈局

OK,知道怎麼解決就方便了,首先,咱們要把so文件放入到/data/data/<app>/下的任意路徑,由於咱們的apk有這個權限在這裏放東西,而後使用System.load加載這個so庫,最後使用反射的方式欺騙CrossWalk框架,告訴它咱們的類庫已經加載完畢。性能

咱們仔細研究下它的源碼,發現有幾個標誌位須要更改,具體代碼以下:

System.load(libPath);
try {
    LibraryLoader loader = LibraryLoader.get(1);
    Class c = Class.forName("org.xwalk.core.internal.XWalkViewDelegate");
    Field field = c.getDeclaredField("sLibraryLoaded");
    field.setAccessible(true);
    field.setBoolean(null, true);
    field.setAccessible(false);

    field = LibraryLoader.class.getDeclaredField("mLoaded");
    field.setAccessible(true);
    field.setBoolean(loader, true);
    field.setAccessible(false);
    PathUtils.setPrivateDataDirectorySuffix("xwalkcore");

} catch (NoSuchFieldException e) {
    e.printStackTrace();
} catch (IllegalAccessException e) {
    e.printStackTrace();
} catch (ClassNotFoundException e) {
    e.printStackTrace();
} catch (ProcessInitException e) {
    e.printStackTrace();
}

只要把以上的類中的標誌位更改掉,那麼CrossWalk就認爲庫已經加載成功了。

相關文章
相關標籤/搜索