一旦安装了应用程序,Android原生库就会消失

切换到Android Studio后,我开始看到可怕的

java.lang.UnsatisfiedLinkError: dlopen failed: library '/data/app-lib/com.myapp.test-1/libmylib.so' not found 

错误。 当我解压缩apk时,我可以看到libmylib.so以及lib / armeabi文件夹下的所有其他本机库(libmyotherlib.so和libtest.so),所以打包不应该是问题…我决定root我的测试设备,并检查我的应用程序的文件夹/ data / app-lib下的实际内容,其中的本机库应该在安装后 – 我发现应用程序后我的应用程序的本机库之一(libmylib.so)丢失了安装在设备上。 libmylib.so和libmyotherlib.so是预先构建的.so文件放在src / main / jniLibs中,而libtest.so是从test.c在src / main / jni中编译的。

这只是在我切换到Android Studio后才开始的; 我已经validation了在Eclipse ADT中使用相同代码构建的apks在安装后在/data/app-lib/com.myapp.test-1下提供了所有必需的库。

Android Studio版本的相关build.gradle:

 apply plugin: 'com.android.application' android { compileSdkVersion 23 buildToolsVersion "21.1.2" defaultConfig { applicationId "com.myapp.test" minSdkVersion 17 targetSdkVersion 23 versionCode 1 versionName "1.0" ndk{ moduleName "test"//testing ndk integration } } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } repositories { // You can also use jcenter if you prefer mavenCentral() } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' //android support libs etc. compile 'com.android.support:appcompat-v7:23.1.0' compile 'com.android.support:support-v13:23.1.0' } 

相关的gradle.properties文件

 android.useDeprecatedNdk=true 

在src / main / jni下我只有test.c

 #include  int main(){ return 0; } 

在src / main / jniLibs / armeabi下我有

 libmylib.so libmyotherlib.so 

Eclipse ADT构建的相关Android.mk:

 include $(CLEAR_VARS) LOCAL_MODULE := test LOCAL_SRC_FILES += test.c include $(BUILD_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := myotherlib LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/libmyotherlib.so LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := mylib LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/libmylib.so LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include include $(PREBUILT_SHARED_LIBRARY) 

安装Android Studio构建的应用程序后的相关/ data / app-lib内容:

 root@SOLONE SL-K40:/ # ls /data/app-lib/com.myapp.test-1 libmyotherlib.so libtest.so 

安装Eclipse ADT构建的应用程序后的相关/ data / app-lib内容:

 root@SOLONE SL-K40:/ # ls /data/app-lib/com.myapp.test-1 libmylib.so libmyotherlib.so libtest.so 

我不小心发现加入了

 sourceSets { main { jni.srcDirs = [] } } 

到我的build.gradle我可以让libmylib.so在安装后再次出现,但这排除了在我的项目中有任何NDK源代码。

第一个问题:知道这里可能会发生什么吗? 可能是mylib实际上是为arme而不是armeabi编译而且Android正在丢弃它,因为它的实际abi与它在apk中的文件夹不匹配(我没有mylib的源代码)? 我的问题听起来类似于这里讨论的问题 ,但是这个人似乎在最终安装的应用程序中只看到一个共享库; 我只看到了一个共享库。

第二个问题:在Android Studio版本中包含预先构建的.so文件的当前正确方法是什么? Android网络版本(我使用Android Studio 1.5,Gradle版本2.4,Android插件版本1.3.0) 的网络似乎变化很大。是否仍需要将jniLibs.srcDir变量重定向到src / main /库?

是的,最好的方法是定义jniLibs.srcDir ,以便可以从那里复制所有预构建的库。

是的,ABI是问题最可能的来源。 如果预构建的库是为armeabi构建的,但设备(如今绝大多数设备)都支持armeabi-v7a ,那么安装程序会很乐意将未预构建的库的… v7a版本复制到/ data / app-lib / com .myapp.test-1 ,然后加载器会抱怨libmylib.so丢失了。

您应该指示Android Studio仅构建一个ABI。 如果你没有在Eclipse构建中做一些特别的事情,那么这很可能是armeabi

指示AS的方式取决于gradle插件的版本。

对于‘com.android.tools.build:grad:1.5.0’插件,我使用类似的东西

 android { defaultConfig.ndk { … abiFilter 'armeabi' } splits { abi { enable true reset() include 'armeabi' } } } 

对于… gradle-experimental:0.2.0 ,我用

 model { android.ndk { … abiFilters += 'armeabi' } } 

我没有必要在实验插件上启用拆分,所以我不会误解你那里的语法更改。