我在Android应用中使用共享库libToon-c.so。
通过Android虚拟设备(AVD)运行此应用时,共享库已加载并正在运行,没有任何问题。
但是,当尝试将库加载到手机(Google Pixel)上时,会显示以下错误
E/linker: "/data/app/com.example.androidsharedlibscratch-a6Mv8edOnQ2q6HbbixecrQ==/lib/arm64/libToon-c.so": ignoring DT_PREINIT_ARRAY in shared library! E/haredlibscratc: No implementation found for long com.example.androidsharedlibscratch.Toon.createToon() (tried Java_com_example_androidsharedlibscratch_Toon_createToon and Java_com_example_androidsharedlibscratch_Toon_createToon__) D/AndroidRuntime: Shutting down VM E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.androidsharedlibscratch, PID: 18368
java.lang.UnsatisfiedLinkError: No implementation found for long com.example.androidsharedlibscratch.Toon.createToon() (tried Java_com_example_androidsharedlibscratch_Toon_createToon and Java_com_example_androidsharedlibscratch_Toon_createToon__)
at com.example.androidsharedlibscratch.Toon.createToon(Native Method)
at com.example.androidsharedlibscratch.Toon.<init>(Toon.java:44)
at com.example.androidsharedlibscratch.MainActivity.onCreate(MainActivity.java:41)
at android.app.Activity.performCreate(Activity.java:7144)
at android.app.Activity.performCreate(Activity.java:7135)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2931)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3086)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1816)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6718)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
toonJni.h包含以下函数定义
JNIEXPORT jlong JNICALL Java_com_example_androidsharedlibscratch_Toon_createToon
(JNIEnv *, jobject);
对应的toonJni.cpp文件包含以下函数实现:
JNIEXPORT jlong JNICALL Java_com_example_androidsharedlibscratch_Toon_createToon(JNIEnv *env, jobject obj) {
...
return (reinterpret_cast<jlong>(toon));
}
此共享库已使用以下独立工具链针对Android进行了编译:
为了将库包含在项目中,已按照以下方式将.so文件放入jniLibs文件夹中:
以下代码已添加到build.gradle中,以包含jni文件:
sourceSets {
main {
jniLibs.srcDirs 'src/main/jniLibs'
}
}
toonJni.h包含extern c {...}指令
toonJni.h文件是使用以下javac命令生成的
javac -h . Toon.java
apk已被构建,提取并验证为包含libToon-c.so文件
还使用了以下命令来验证libToon-c.so是否在设备(Google Pixel)的app文件夹中
adb shell dumpsys package packages | grep androidsharedlibscratch
adb ls /data/app/com.example.androidsharedlibscratch-foqHDywOpE_dDPgTCtTttw==/lib/arm64
以下是命令和名称修改检查的结果:
android-ndk-r21/build/toolchain/bin/aarch64-linux-android-nm android_studio_scratch/AndroidSharedLibScratch/app/src/main/jniLibs/arm64-v8a/libToon-c.so
000000000000d570 T Java_com_example_androidsharedlibscratch_Toon_createToon
按照指定的@Botje在.cpp和.h文件(如下)中添加了以下JNI_OnLoad。成功加载的toonLib未显示在android studio logcat中(日志级别设置为详细)。
toonJni.h中的定义:
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved);
toonJni.cpp中的实现:
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv* env;
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
return JNI_ERR;
}
__android_log_print(ANDROID_LOG_INFO, "toonlib", "toonlib loaded successfully");
return JNI_VERSION_1_6;
}