以前看到简书
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.load
和System.loadLibrary
函数么,直接调用呗,因而我就先暂时把绝对路径给写了下来,直接调用System.load
函数。框架
再次启动,发现CrossWalk
报Shared 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
就认为库已经加载成功了。