【问题标题】:How to migrate an Android NDK project based on Android.mk files to Gradle when a native shared library depends on a static library?当原生共享库依赖静态库时,如何将基于 Android.mk 文件的 Android NDK 项目迁移到 Gradle?
【发布时间】:2014-05-28 22:45:10
【问题描述】:

我有一个 Android NDK 项目,它使用 Android.mk 文件构建和运行良好,它包含我作为共享库构建的本机代码(一个 C 文件),此代码依赖于第三方静态库(.一个文件)。

现在我正在尝试将其迁移到 Gradle。我目前的配置如下:

/static_libs folder下的静态库Android.mk



    LOCAL_PATH := $(call my-dir)

    include $(CLEAR_VARS)

    LOCAL_MODULE    := opus
    LOCAL_SRC_FILES := lib/libopus.a
    LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include

    include $(PREBUILT_STATIC_LIBRARY) 

主模块Android.mk文件:(通常的jni/文件夹下)



    LOCAL_PATH := $(call my-dir)
    $(call import-add-path,$(LOCAL_PATH)/../static_libs)

    include $(CLEAR_VARS)

    LOCAL_MODULE:=opus_jni

    LOCAL_SRC_FILES:= opus_jni.c

    LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog -ldl 
    LOCAL_WHOLE_STATIC_LIBRARIES := opus
    include $(BUILD_SHARED_LIBRARY)

    $(call import-module,opus) 

当我在主模块上运行 ndk-build 时,唯一的输出是一个文件 libopus_jni.so,它是唯一用于构建最终 APK 的文件。

现在在 Gradle 上,我现在唯一想做的就是使用相同的预构建共享库和相同的代码创建一个 APK,所以我将生成的库复制到 jniLibs/ 文件夹中(如果文件放在这里,我知道从 0.9 Gradle 开始支持 JNI 库)。项目构建并且最终的 APK 确实包含 libs/ 文件夹内的 .so 文件。 (我通过解压生成的 APK 验证)

问题是,当我尝试使用任何本机方法时,我收到以下错误:



    05-28 14:57:53.393    3370-3370/com.opusgradle.app D/OB-OpusCodec﹕ testPcmToOpus()
    05-28 14:57:53.393    3370-3370/com.opusgradle.app D/dalvikvm﹕ Trying to load lib /data/app-lib/com.opusgradle.app-2/libopus_jni.so 0x42630b18
    05-28 14:57:53.393    3370-3370/com.opusgradle.app D/dalvikvm﹕ Added shared lib /data/app-lib/com.opusgradle.app-2/libopus_jni.so 0x42630b18
    05-28 14:57:53.393    3370-3370/com.opusgradle.app D/OB-OpusCodec﹕ Trying to initialize...
    05-28 14:57:53.393    3370-3370/com.opusgradle.app W/dalvikvm﹕ No implementation found for native Lcom/opusgradle/app/OpusCodec;.initOpusEncoder:(II)V
    05-28 14:57:53.393    3370-3370/com.opusgradle.app D/AndroidRuntime﹕ Shutting down VM
    05-28 14:57:53.393    3370-3370/com.opusgradle.app W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0x415e0ba8)
    05-28 14:57:53.393    3370-3370/com.opusgradle.app E/AndroidRuntime﹕ FATAL EXCEPTION: main
        Process: com.opusgradle.app, PID: 3370
        java.lang.UnsatisfiedLinkError: Native method not found: com.opusgradle.app.OpusCodec.initOpusEncoder:(II)V
                at com.opusgradle.app.OpusCodec.initOpusEncoder(Native Method)
                at com.opusgradle.app.OpusCodec.(OpusCodec.java:23)
                at com.opusgradle.app.MainActivity.testPcmToOpus(MainActivity.java:78)
                at com.opusgradle.app.MainActivity.access$000(MainActivity.java:22)
                at com.opusgradle.app.MainActivity$1.onClick(MainActivity.java:64)
                at android.view.View.performClick(View.java:4438)
                at android.view.View$PerformClick.run(View.java:18422)
                at android.os.Handler.handleCallback(Handler.java:733)
                at android.os.Handler.dispatchMessage(Handler.java:95)
                at android.os.Looper.loop(Looper.java:136)
                at android.app.ActivityThread.main(ActivityThread.java:5017)
                at java.lang.reflect.Method.invokeNative(Native Method)
                at java.lang.reflect.Method.invoke(Method.java:515)
                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
                at dalvik.system.NativeStart.main(Native Method)

如您所见,.so 文件已找到并已加载,但对本机函数的调用失败。 Java 代码与原始项目中的代码相同,运行良好,基本上对库的调用如下所示:



    static 
    {
     System.loadLibrary("opus_jni");
    }

似乎需要静态库时,Gradle 需要将其他内容复制到 jniLibs 文件夹中,我也尝试将 .a 文件复制到 jniLibs/ 文件夹中,但没有成功。

对于在 Gradle 上正确构建具有静态库依赖项的预构建共享库是否还有其他要求?

【问题讨论】:

    标签: android android-ndk java-native-interface android-gradle-plugin android.mk


    【解决方案1】:

    很可能,您更改了使用本机库的 Java 类的 名称。通常,本地方法名称被硬编码以满足 JNI 自动绑定。这就是为什么你不能使用预建的libopus_jni.so

    最简单的解决方法是将类 com.opusgradle.app 重命名回来(是 com.opus.app 吗?)。您可以在不重命名AndroidManifest.xml 中的应用包的情况下更改此类。

    或者,您可以重命名 opus_jni.c 中的 Jni 本机方法名称,重建库,然后将其复制到 jniLibs/ 文件夹以供 gradle 使用。

    【讨论】:

    • 确实是这样,我在测试应用程序上构建了所​​有内容,然后将这些类移动到实际应用程序中的不同包中,谢谢。
    猜你喜欢
    • 1970-01-01
    • 2021-11-21
    • 2011-12-01
    • 1970-01-01
    • 2014-03-22
    • 1970-01-01
    • 1970-01-01
    • 2012-11-04
    • 1970-01-01
    相关资源
    最近更新 更多