如何在Android代码中使用.so文件来调用本地方法

4

我有一个包含本地方法的libmath.so文件,需要在我的安卓代码中调用这些本地方法。我创建了一个示例安卓应用程序,并将libmath.so文件添加到libs/armeabi文件夹中,然后运行“右键单击鼠标” -> Android工具 -> 添加本地支持。现在,在应用程序的jni文件夹中创建了以下文件及其内容。

Android.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE    := libmath
LOCAL_SRC_FILES := libmath.cpp
include $(BUILD_SHARED_LIBRARY)

libmath.cpp

#include <jni.h>

当我将项目运行为Android应用程序时,控制台显示如下:
17:58:41 **** Build of configuration Default for project math ****
"F:\\Vinay\\Softwares\\android-ndk-r10d\\ndk-build.cmd" all 
[armeabi] Compile++ thumb: math <= libmath.cpp
[armeabi] StaticLibrary  : libstdc++.a
[armeabi] SharedLibrary  : libmath.so
[armeabi] Install        : libmath.so => libs/armeabi/libmath.so
17:58:53 Build Finished (took 11s.695ms)

以下是我加载库的代码:

public class MathJni {
static {
    System.loadLibrary("math");
}
public native String calc(String paramString);

}

public static final MathJni math = new MathJni();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        String s= math.calc("help");

    }

当我在模拟器上运行安卓应用程序后,启动应用程序时出现以下错误。

02-06 07:38:36.900: D/dalvikvm(831): Trying to load lib /data/app-lib/com.example.math-2/libmath.so 0xb3cd0848
02-06 07:38:36.900: D/dalvikvm(831): Added shared lib /data/app-lib/com.example.math-2/libmath.so 0xb3cd0848
02-06 07:38:36.910: D/dalvikvm(831): No JNI_OnLoad found in /data/app-lib/com.example.math-2/libmath.so 0xb3cd0848, skipping init
02-06 07:38:37.540: W/dalvikvm(831): No implementation found for native Lcom/example/math/MathJni;.calc:(Ljava/lang/String;)Ljava/lang/String;
02-06 07:38:37.540: D/AndroidRuntime(831): Shutting down VM
02-06 07:38:37.550: W/dalvikvm(831): threadid=1: thread exiting with uncaught exception (group=0xb3a20ba8)
02-06 07:38:37.570: E/AndroidRuntime(831): FATAL EXCEPTION: main
02-06 07:38:37.570: E/AndroidRuntime(831): Process: com.example.math, PID: 831
02-06 07:38:37.570: E/AndroidRuntime(831): java.lang.UnsatisfiedLinkError: Native method not found: com.example.math.MathJni.calc:(Ljava/lang/String;)Ljava/lang/String;
02-06 07:38:37.570: E/AndroidRuntime(831):  at com.example.math.MathJni.calc(Native Method)
02-06 07:38:37.570: E/AndroidRuntime(831):  at com.example.math.MainActivity.onCreate(MainActivity.java:16)

可能出现此错误的原因是什么?

1
安卓编码?自从什么时候本地代码不是安卓代码了? - Deduplicator
1
你还没有展示你的C++代码。 - Michael
迈克尔是非常正确的。尽管缺乏信息,我仍然猜测您在MathJni类中没有一个接受java.lang.String实例作为参数的calc方法... - Géza Török
我没有任何C++代码。当我将.so添加到Android项目并运行“Android工具->添加本地支持”时,.cpp文件被生成,并且这就是我在此处附加的内容。 - Vinay
抱歉,我忘记在MathJni类中添加public native String calc(String paramString);行。现在我已经添加了它。 - Vinay
1个回答

3
如果你没有编写过C++代码,只是使用Java直接预构建的.so文件,那么你不必使用NDK。
只需将.so文件放入项目中,在eclipse项目下放置在libs/<abi>下,在gradle项目下放置在jniLibs/<abi>下。
这里你所做的是创建了一个名为libmath的NDK模块,其内容几乎为空。当你构建项目时,NDK会生成一个新的libmath.so文件,其中没有来自初始库的任何内容。因此,请删除所有jni文件和文件夹,将以前的.so文件复制回libs/<abi>,然后再次运行项目。
如果遇到其他问题,请验证你的libmath.so是否实现了jstring com_example_math_MathJni_calc(JNIEnv* env, jobject* obj),或者检查你应该在Java端声明什么才能使用你的库,使用正确的包名和签名(如果有随附于你的.so文件的文档,它应该说明这一点)。

谢谢,我会尝试这个。 - Vinay
当我按照所述尝试时,在启动应用程序时logcat中会出现以下错误。02-06 10:34:02.840: E/AndroidRuntime(1259): java.lang.UnsatisfiedLinkError: Couldn't load math from loader dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.math-1.apk"],nativeLibraryDirectories=[/data/app-lib/com.math-1, /system/lib]]]: findLibrary returned null - Vinay
你还在使用System.loadLibrary()吗? 根据你的错误提示,我认为你已经切换到了System.load()。 你应该从logcat中获取更多的调试信息,而不是只看到“findLibrary returned null”。此外,检查一下你的.so文件是否已正确集成到apk包中,方法是将其作为zip文件打开,并验证它们是否在“lib/<abi>”目录内。 - ph0b
非常感谢您的评论。 - Vinay

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接