原文地址 http://www.jacpy.com/2016/05/10/gradle-compile-exclude-third-library-arm64-x86-64.html
在开发android应用时,一般都会用很多的第三方框架。有些框架会提供各个CPU的架构的SO库,比如arm、arm-v7a、x86、mips,有的甚至还提供64位的版本;而有的为了缩小应用包的体积只提供了一些常用的,比如arm,x86。如果应用中有的第三方框架提供了arm和x86的版本,而有的提供了arm,arm-v7a,x86三个版本,那么当运行在arm-v7a版本的CPU上,就会提示找不到只有arm和x86版本的SO库,这样很容易导致应用挂掉,报java.lang.UnsatisfiedLinkError
错误,提示native方法找不到实现。
按道理说arm-v7a的CPU会兼容arm版本,但系统去查找SO库的时候却只会在一个目录查找,找完了arm-v7a,没找到不会再去arm目录,这样就会导致兼容性问题。解决方法有两种:
-
一种是所有包含有SO库的第三方框架提供最新版本NDK支持的所有的CPU架构SO库,如:armeabi armeabi-v7a x86 mips arm64-v8a x86_64 mips64或者在编译时在Application.mk文件中配置
APP_ABI := all
。这样做一般不合适,这样会分散开发者的注意力。 -
第二种方法是:应用中所有的包含SO库的第三方框架只能取最小的子集,这种方法比较合适集成第三方框架。
下面以facebook的fresco框架为例来说明第二种方法的操作方式。
fresco框架中提供了各个CPU架构的SO库,包括64位的,而自己的应用其他第三方带有SO库的框架A还没有使用64位的SO库,如果不做处理,应用运行在64位手机上,当使用框架A的时候应用就会闪退,因为框架A没有64位的库。那么解决办法只有将fresco库的64位SO库都删除,只保留框架A的相同目录下面的SO库。下面是gradle文件中的配置:
dependencies {
compile fileTree(dir: 'libs', include: '*.jar')
compile project(':Base')
compile project(':widget:pullRefreshlibrary')
compile 'com.android.support:appcompat-v7:22.2.0'
compile 'com.android.support:design:22.2.0'
compile 'com.android.support:recyclerview-v7:22.2.0'
compile 'com.facebook.fresco:fresco:0.10.0'
}
// 将fresco库除armeabi和x86包以外的SO库删除
def deleteSO() {
def rootPath = rootProject.getRootDir().getAbsolutePath() + '/' + project.name
delete fileTree(dir: rootPath + "/build/intermediates/exploded-aar/com.facebook.fresco/imagepipeline/" + "0.10.0" + "/jni/", excludes: ['**/armeabi/**', '**/x86/**'])
}
project.afterEvaluate{
// debug模式下删除SO库
tasks.getByName('prepareDebugDependencies') { // Hook prepareDebugDependencies任务
it.doLast {
// prepareDebugDependencies任务执行完成后删除SO库
deleteSO()
}
}
// 打包的时候删除SO库
tasks.getByName('prepareReleaseDependencies') {
it.doLast {
deleteSO()
}
}
}