【问题标题】:Android native libs disappearing once app is installed一旦安装了应用程序,Android 本机库就会消失
【发布时间】:2016-03-07 05:05:14
【问题描述】:

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

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

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

这只是在我切换到 Android Studio 后才开始的;我已经验证在 Eclipse ADT 中使用相同代码构建的 apk 在安装后具有 /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构建的app后的相关/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 实际上是为 armeabi 以外的 abi 编译的,而 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?

【问题讨论】:

  • 我的猜测是它的一些 gradle 任务正在破坏构建
  • 首先,你不需要root来访问/data/app-lib/com.myapp.test-1/中的库
  • @AlexCohn 是的,但是您确实需要 root 才能通过 adb shell 'ls -al /data/app-lib' 列出 /data/app-lib 的内容,而我不想这样做必须在运行时从 Context::getApplicationInfo().nativeLibraryDir 获取我的应用程序文件夹的名称
  • @CCJ 如果您正在运行调试应用程序,则不需要:stackoverflow.com/a/7712173/4758618

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


【解决方案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:gradle: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 插件上启用拆分,所以我不会误导您那里的语法更改。

【讨论】:

  • 嗯,很奇怪。我想知道 libmyotherlib 如何/为什么让它通过安装过程?最终的 apk 对所有 abis 进行了 libtest,包括 armeabi-v7a,但 libmyotherlib 仅存在于 armeabi...
  • 安装程序能否检测到设备的 /system/lib 目录中有一个名为 libmylib 的库可用?如果是这样,那就可以解释为什么 libmyotherlib 通过安装成功而 libmylib 被丢弃了——我正在加载的实际库是在我的测试设备上的 /system/lib 下找到的库的修改版本,因此和/或 abi你提到的最佳过滤可以解释我看到的行为
猜你喜欢
  • 2011-04-17
  • 1970-01-01
  • 1970-01-01
  • 2021-03-14
  • 1970-01-01
  • 2013-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多