转自: https://segmentfault.com/a/1190000002919135


之前看到简书Android客户端使用的编辑器,甚是喜欢,它的优雅以及高性能的特点让我爱不释手,很想自己也去做一个。此前实现过一个在Android上的Markdown编辑器但是界面以及所见即所得的效果非常不好看,所以一直耿耿于怀。

然后冒昧看了下简书的布局系统,看见了几个奇怪的类,包括类似XWalkContentView,于是Google了下,就查到了CrossWalk这个hybrid框架了。第一眼并不觉得它有啥不一样,以为是一个Cordova的轮子。后来细看,发现是自个儿编辑了整个Chrominum,屌屌屌!

运行个demo,wrapper了一个http://sf.gg 发现体验真的是不错啊,webview性能到这个水平内心都宽慰了,但是为何安装速度那么慢呢?一看apk大小,足足有40M+,感觉天都要塌了。SegmentFault for Android 客户端才3.03M,我要是包上这玩意,估计就没多少人下了吧。。。然后又看看简书,整个apk大小才8M,在启动编辑器的时候,提示需要下载编辑器,下载了一会,然后再打开。顿时就明白了,看来它的库是从外部载入的,记得以前看到过从外部加载动态链接库想想很是简单,于是入坑了。

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

一看这个路径,泪奔了,原来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//下的任意路径,因为我们的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就认为库已经加载成功了。

本人最近做一个的项目,大概逻辑是需要使用CrossWalk浏览的APP,但是CrossWalk的so文件比较大,所以不能与apk包一起发布,需要安装完以后从网络下载动态加载,但是用系统System.load(pathName)加载完毕后使用XWalkInitializer初始化还是失败,期间也考虑过使用官方的共享模式,但需要下载安装apk(CrossWalk的运行库),体验较差。最终阅读楼主的博客完美解决动态加载so文件的问题。

更多相关文章

  1. Android中WebView的使用,加载H5
  2. Android(安卓)高清加载巨图方案 拒绝压缩图片
  3. 关于 Android(安卓)进程保活,你所需要知道的一切(转)
  4. Android(安卓)Wear和二维码
  5. Android中对媒体的使用
  6. 在Android(安卓)开发中使用Protobuf的实践和经验分享
  7. 箭头函数的基础使用
  8. NPM 和webpack 的基础使用
  9. Python list sort方法的具体使用

随机推荐

  1. java for android sqlite数据的操作:说实
  2. Android面试题(基础部分1)
  3. Android(安卓)第四天(晚上)
  4. 创建Gridview视图
  5. Android的merge标签用法
  6. android:activity生命周期及几个主要函数
  7. Android消息机制,从Java层到Native层剖析
  8. Android中ListView使用- 网络图片的异步
  9. ADB使用方法及常用命令
  10. android 拖动效果 Gallery 实例