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

时间:2015-12-02 19:39:30

标签: java android c android-studio android-ndk

切换到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),所以打包不应该是问题......我决定根据我的测试设备并查看/ data / app-lib下我的应用程序文件夹的实际内容,其中的本机库应该在安装后 - 我发现我的应用程序的本机库之一应用程序安装在设备上后,(libmylib.so)丢失了。 libmylib.so和libmyotherlib.so是预先构建的.so文件放在src / main / jniLibs中,而libtest.so是从test.c编译的src / main / jni。

这只是在我切换到Android Studio后才开始;我已经验证了在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 <jni.h>

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的源代码) )?我的问题听起来类似于here所讨论的问题,但该人似乎在最终安装的应用程序中只看到一个共享库;我只看到了一个共享库。

第二个问题: 在Android Studio版本中包含预先构建的.so文件的当前正确方法是什么? Clues around the 'net似乎因Android Studio版本而异乎寻常(我使用的是Android Studio 1.5,Gradle版本2.4,Android插件版本1.3.0)是否还需要将jniLibs.srcDir变量重定向到src / main / libs?

1 个答案:

答案 0 :(得分:1)

是的,最好的方法是定义 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'
    }
}

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