我有一个Android NDK项目,它可以构建并运行良好的 Android.mk 文件,它由我的本机代码(一个C文件(组成,作为共享库构建,此代码依赖于第三方静态库(.a文件(。
现在我正在尝试将其迁移到 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 确实包含.so
文件libs/
文件夹中。 (我通过解压缩生成的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 上正确构建?
最有可能的是,您更改了使用本机库的 Java 类的包名称。通常,本机方法名称是硬编码的,以满足 JNI 自动绑定。这就是为什么您不能使用预构建的libopus_jni.so
。
最简单的解决方法是将类重命名com.opusgradle.app
(是com.opus.app
吗?可以更改此类,而无需在 AndroidManifest.xml
中重命名应用包。
或者,您可以在 opus_jni.c
中重命名 Jni 本机方法名称,重建库,并将其复制到 gradle 的jniLibs/
文件夹中。