use*_*225 80 android android-ndk
我想使用来自另一个 Android项目的现有本机库,所以我只是将NDK构建库(libcalculate.so)复制到我的新Android项目中.在我的新Android项目中,我创建了一个文件夹libs/armeabi/并将libcalculate.so放在那里.有没有 JNI /文件夹.我的测试设备有ARM架构.
在我的java代码中,我通过以下方式加载库:
static{
System.loadLibrary("calculate");
}
Run Code Online (Sandbox Code Playgroud)
当我运行我的新Android项目时,我收到错误:
java.lang.UnsatisfiedLinkError: ...
nativeLibraryDirectories=[/vendor/lib, /system/lib]]] couldn't find "libcalculate.so"
Run Code Online (Sandbox Code Playgroud)
所以,正如错误所说,复制的本机库不在/ verdor/lib或/ system/lib中,如何在我的情况下解决这个问题?
(我解压缩了apk包,在lib /下有libcalculate.so)
==== UPDATE =====
我还尝试在项目根目录下创建一个jni /文件夹,并在jni /下添加一个Android.mk文件.Android.mk的内容是:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libcalculate
LOCAL_SRC_FILES := libcalculate.so
include $(PREBUILT_SHARED_LIBRARY)
Run Code Online (Sandbox Code Playgroud)
然后,在项目根目录下,我执行了ndk-build.之后,armeabi /和armeabi-v7a /目录由ndk-build生成(文件夹中有libcalculate.so).
然后我运行我的maven成功构建项目.在最终的apk包中,有:
lib/armeabi/libcalculate.so
lib/armeabi-v7a/libcalculate.so
Run Code Online (Sandbox Code Playgroud)
但是当我运行我的应用程序时,同样的错误抛出:
java.lang.UnsatisfiedLinkError: ...
nativeLibraryDirectories=[/vendor/lib, /system/lib]]] couldn't find "libcalculate.so"
Run Code Online (Sandbox Code Playgroud)
ph0*_*h0b 156
为了根本原因(也许可以在同一时间解决您的问题),您可以执行以下操作:
删除jni文件夹和所有.mk文件.如果你没有编译任何东西,你不需要这些也不需要NDK.
复制你的libcalculate.so文件<project>/libs/(armeabi|armeabi-v7a|x86|...).当使用Android Studio时,它是<project>/app/src/main/jniLibs/(armeabi|armeabi-v7a|x86|...),但我看到你正在使用eclipse.
构建你的APK并将其作为zip文件打开,检查你的libcalculate.so文件是否在lib /(armeabi | armeabi-v7a | x86 | ...)中.
删除并安装您的应用程序
运行dumpsys包软件包| grep yourpackagename以获取应用程序的nativeLibraryPath或legacyNativeLibraryDir.
在你拥有的nativeLibraryPath或legacyNativeLibraryDir/armeabi上运行ls,检查你的libcalculate.so是否确实存在.
如果它在那里,检查它是否没有从你原来的libcalculate.so文件中改变:它是针对正确的架构编译的,它是否包含预期的符号,是否有任何遗漏的依赖项.您可以使用readelf分析libcalculate.so.
为了检查步骤5-7,您可以使用我的应用程序而不是命令行和readelf:Native Libs Monitor
PS:很容易对默认情况下放置或生成.so文件的位置感到困惑,这里有一个摘要:
eclipse项目中的libs/CPU_ABI
Android Studio项目中的jniLibs/CPU_ABI
AAR中的jni/CPU_ABI
最终APK内的lib/CPU_ABI
在<5.0设备上的应用程序的nativeLibraryPath内部,以及在= = 5.0设备上的应用程序的legacyNativeLibraryDir/CPU_ARCH内部.
其中CPU_ABI是以下任何一个:armeabi,armeabi-v7a,arm64-v8a,x86,x86_64,mips,mips64.取决于您所针对的架构和已编译的库.
还要注意的lib未混合CPU_ABI目录之间:你所需要的全套你使用的是什么的,一个lib是内部 armeabi文件夹将不被一个安装armeabi-V7A设备,如果有内部的任何库armeabi来自APK的-v7a文件夹.
小智 18
在gradle中,将所有文件夹复制到 libs/
jniLibs.srcDirs = ['libs']
Run Code Online (Sandbox Code Playgroud)
添加上述行来sourceSets在build.gradle文件中工作.没有其他任何工作.
Daw*_*ozd 12
在我的情况下,我必须通过gradle排除编译源并设置libs路径
android {
...
sourceSets {
...
main.jni.srcDirs = []
main.jniLibs.srcDirs = ['libs']
}
....
Run Code Online (Sandbox Code Playgroud)
作为参考,我收到了此错误消息,解决方案是当您指定库时,您会错过前面的“lib”和末尾的“.so”。
所以,如果你有一个文件 libmyfablib.so,你需要调用:
System.loadLibrary("myfablib"); // this loads the file 'libmyfablib.so'
Run Code Online (Sandbox Code Playgroud)
查看了apk,安装/卸载并尝试了各种复杂的解决方案后,我看不到摆在我面前的简单问题!
这是 Android 8 更新。
在早期版本的 Android 中,对于 LoadLibrary 本机共享库(例如,用于通过 JNI 访问),我将本机代码硬连线以遍历 lib 文件夹的一系列潜在目录路径,基于各种 apk 安装/升级算法:
/data/data/<PackageName>/lib
/data/app-lib/<PackageName>-1/lib
/data/app-lib/<PackageName>-2/lib
/data/app/<PackageName>-1/lib
/data/app/<PackageName>-2/lib
Run Code Online (Sandbox Code Playgroud)
这种方法很鸡肋,不适用于 Android 8;从https://developer.android.com/about/versions/oreo/android-8.0-changes.html 你会看到,作为他们“安全”更改的一部分,你现在需要使用 sourceDir:
“你不能再假设 APK 位于名称以 -1 或 -2 结尾的目录中。应用程序应该使用 sourceDir 来获取目录,而不是直接依赖目录格式。”
更正, sourceDir 不是查找本机共享库的方法;使用类似的东西。测试 Android 4.4.4 --> 8.0
// Return Full path to the directory where native JNI libraries are stored.
private static String getNativeLibraryDir(Context context) {
ApplicationInfo appInfo = context.getApplicationInfo();
return appInfo.nativeLibraryDir;
}
Run Code Online (Sandbox Code Playgroud)
出现此错误的原因是您的应用与您链接的本机库之间的ABI不匹配.换句话说,您的应用和您.so的目标是针对不同的ABI.
如果您使用最新的Android Studio模板创建应用,则可能会针对您的应用,arm64-v8a但您的.so目标可能armeabi-v7a就是.
有两种方法可以解决这个问题:
.so构建的旧ABI .选择2很脏,但我想你可能更感兴趣:
改变你的应用程序 build.gradle
android {
defaultConfig {
...
ndk {
abiFilters 'armeabi-v7a'
}
}
}
Run Code Online (Sandbox Code Playgroud)
尝试在包含部分后调用您的库PREBUILT_SHARED_LIBRARY:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libcalculate
LOCAL_SRC_FILES := <PATH>/libcalculate.so
include $(PREBUILT_SHARED_LIBRARY)
#...
LOCAL_SHARED_LIBRARIES += libcalculate
Run Code Online (Sandbox Code Playgroud)
更新:
如果您将在 Java 中使用此库,则需要将其编译为共享库
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libcalculate
LOCAL_SRC_FILES := <PATH>/libcalculate.so
include $(BUILD_SHARED_LIBRARY)
Run Code Online (Sandbox Code Playgroud)
并且您需要将库部署到/vendor/lib目录中。
| 归档时间: |
|
| 查看次数: |
106067 次 |
| 最近记录: |