我在Android上有一个libjpeg-turbo的JNI实现。
应用程序构建没有任何问题,我可以在内部生成的APK文件中看到本地libJPEGProcessing.so
库位于lib
文件夹中,用于不同的体系结构。
但是,当通过应用程序调用本机方法时,我将收到以下“未找到实现”消息,这将导致异常:
D/dalvikvm: No JNI_OnLoad found in /system/lib/libjpeg.so 0xa4fe3dc0, skipping init
D/dalvikvm: Trying to load lib /data/app-lib/com.google.test-2/libJPEGProcessing.so 0xa4fe3dc0
D/dalvikvm: Added shared lib /data/app-lib/com.google.test-2/libJPEGProcessing.so 0xa4fe3dc0
D/dalvikvm: No JNI_OnLoad found in /data/app-lib/com.google.test-2/libJPEGProcessing.so 0xa4fe3dc0, skipping init
W/dalvikvm: No implementation found for native Lcom/google/test/NativeMethods;.computeUsableDCTCoefficientsLinkedList:(Ljava/lang/String;)I
这是我在JNI中的方法:
extern "C" {
jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
JNIEnv* env;
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
return -1;
}
// Get jclass with env->FindClass.
// Register methods with env->RegisterNatives.
return JNI_VERSION_1_6;
}
JNIEXPORT jint JNICALL Java_com_google_test_NativeMethods_computeUsableDCTCoefficientsLinkedList
(JNIEnv *env, jobject obj, jstring javaString)
{
...
}
}
生成的头文件:
extern "C" {
/*
* Class: com_google_test_NativeMethods
* Method: computeUsableDCTCoefficientsLinkedList
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_com_google_test_NativeMethods_computeUsableDCTCoefficientsLinkedList
(JNIEnv *, jclass, jstring);
}
Java中的实现如下所示:
package com.google.test;
import java.util.ArrayList;
public class NativeMethods {
private String filename = null;
private int fromNative = -100;
private int numberInList = -100;
private ArrayList<DCTCoefficient> array = null;
static {
System.loadLibrary("jpeg");
System.loadLibrary("JPEGProcessing");
}
public static native int computeUsableDCTCoefficientsLinkedList(String filename);
}
Android.mk
的{{1}}:
ndk-build
在构建和编译期间没有错误,应用程序通常会在Android设备上启动。但是,我已经定义了JNI_OnLoad方法,该方法在Java类中加载本机库后也没有被调用。
修改
我在Gradle Console中发现以下警告,可能与之相关:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_C_FILES := ./libjpeg-turbo/
LOCAL_MODULE := JPEGProcessing
LOCAL_CFLAGS := -Ic:\AndroidStudioProjects\Test\Test\src\main\jni\ -Ic:\libjpeg-turbo-gcc\include\
LOCAL_SRC_FILES := JPEGProcessing.c
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_STATIC_LIBRARIES := c:\libjpeg-turbo-gcc\lib\libjpeg.a
include $(BUILD_SHARED_LIBRARY)
编辑2:
尝试在Linux上查看已编译的libJPEGProcessing.so:
Android NDK: WARNING:C:/AndroidStudioProjects/Test/Test/src/main/jni/Android.mk:JPEGProcessing: non-system libraries in linker flags: c:\libjpeg-turbo-gcc\lib\libjpeg.a
Android NDK: This is likely to result in incorrect builds. Try using LOCAL_STATIC_LIBRARIES
Android NDK: or LOCAL_SHARED_LIBRARIES instead to list the library dependencies of the
Android NDK: current module
没有导出的JNI方法和符号。这是对的吗?
编辑3:
nm libJPEGProcessing.so
nm: libJPEGProcessing.so: no symbols
nm -D libJPEGProcessing.so
00002004 A __bss_start
U __cxa_atexit
U __cxa_finalize
00002004 A _edata
00002004 A _end
的输出:
ndk-build.cmd -B V=1 APP_ABI=armeabi
答案 0 :(得分:0)
您的代码似乎没问题 - 我看不到任何签名问题,您似乎正在以所需方式加载库。但是,事实是日志说找到了库,但它找不到你的JNI_OnLoad实现。您是否有可能拥有多个版本的libJPEGProcessing.so,并且系统找到较旧的版本?当然,我不是在讨论各种架构的不同库。
答案 1 :(得分:0)
我发现尽管APK
已编译并正常工作,但本地库未正确编译并包含在APK
文件夹中的lib
文件中。
所以我将build.gradle
更改为不使用ndk-build
,而是使用预编译的本机库进行项目。在更改之后,APK
中包含本机库,一切正常:
sourceSets.main {
jniLibs.srcDir 'src/main/libs' //set libs as default directory for .so files inclusion, instead of jniLibs
jni.srcDirs = [] //disable automatic ndk-build call
}
我唯一需要做的改变是如果有任何更改,请在Android Studio外部编译本机库。