简体   繁体   English

当本机共享库依赖静态库时,如何将基于Android.mk文件的Android NDK项目迁移到Gradle?

[英]How to migrate an Android NDK project based on Android.mk files to Gradle when a native shared library depends on a static library?

I have an Android NDK project which builds and runs fine with Android.mk files, it consists of my native code (one C file) built as a shared library, this code has a dependency to a third party static library (.a file). 我有一个Android NDK项目,该项目可与Android.mk文件一起构建并运行良好,它包含作为共享库构建的本机代码(一个C文件),此代码对第三方静态库(.a文件)具有依赖性。

Right now I am trying to migrate it to Gradle. 现在,我正在尝试将其迁移到Gradle。 My current configuration is as follows: 我当前的配置如下:

Static library Android.mk that is under the /static_libs folder /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) 

Main module Android.mk file: (under the usual jni/ folder) 主模块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) 

When I run ndk-build on the main module the only output is one file libopus_jni.so that is the only one used to build the final APK. 当我在主模块上运行ndk-build时,唯一的输出是一个文件libopus_jni.so ,这是唯一用于构建最终APK的文件。

Now on Gradle, the only thing I want to do for now is create an APK with this same prebuilt shared library and the same code, so I copied my generated library into jniLibs/ folder (I know as of 0.9 Gradle already supports JNI libraries if the files are put here) . 现在在Gradle上,我现在唯一要做的就是使用相同的预构建共享库和相同的代码创建一个APK,因此我将生成的库复制到jniLibs/文件夹中(我知道从0.9开始,Gradle已支持JNI库,如果文件放在这里) The project builds and the final APK does contain the .so file inside the libs/ folder. 该项目已构建,最终的APK确实在libs/文件夹中包含.so文件。 (I verified by unzipping the generated APK) (我通过解压缩生成的APK进行了验证)

The problem is that when I try to use any of the native methods I get the following error: 问题是,当我尝试使用任何本机方法时,都会出现以下错误:



    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)

As you can see the .so file is found and loaded but the call to the native function fails. 如您所见, .so文件已找到并加载,但对本机函数的调用失败。 The Java code is the same as in the original project that works fine, basically the invocation to the library looks like this: Java代码与可以正常工作的原始项目相同,基本上对库的调用如下所示:



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

It seems that when a static library is required, Gradle needs something else copied into the jniLibs folder, I tried copying the .a file to the jniLibs/ folder too without any success. 看来,当需要静态库时,Gradle需要将其他内容复制到jniLibs文件夹中,我也尝试将.a文件复制到jniLibs/文件夹中也没有成功。

Is there any other requirement for pre-built shared librares with a static library dependency to build correctly on Gradle? 对于具有静态库依赖关系的预构建共享库,是否还有其他要求才能在Gradle上正确构建?

Most likely, you changed the package name for the Java class that uses your native library. 您很可能更改了使用本机库的Java类的名称。 Usually, the native method names are hardcoded to satisfy JNI automatic binding. 通常,本机方法名称经过硬编码以满足JNI自动绑定。 That's why you cannot use the prebuilt libopus_jni.so . 这就是为什么您不能使用预构建的libopus_jni.so

The easiest resolution would be to rename the class com.opusgradle.app back (was it com.opus.app ?). 最简单的解决方法是将类com.opusgradle.app重命名(是com.opus.app吗?)。 You can change this class without renaming the app package in AndroidManifest.xml . 您可以在不重命名AndroidManifest.xml的应用程序包的情况下更改此类。

Alternatively, you can rename the Jni native method names in opus_jni.c , rebuild the library, and copy it to the jniLibs/ folder for gradle. 另外,您可以在opus_jni.c中重命名Jni本机方法名称,重新opus_jni.c库,然后将其复制到jniLibs/文件夹中进行gradle。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM