Android中添加自定义Lib、SO 库,并解决UnsatisfiedLinkError 和library_public问题

在android N上使用 .so作为apk的第三方库的时候,会发生java.lang.UnsatisfiedLinkError

本项目中方案:

一,将SO库放在vendor/app/lib64目录下

二,增加SO库,预编译到out/vendor目录

增加Android.mk文件,如下:

######## automatic generated
LOCAL_PATH := $(call my-dir)

## xxx_Browser.apk
include $(CLEAR_VARS)
LOCAL_MODULE := xxx_Browser
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := app/$(LOCAL_MODULE).apk
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX :=  $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_CERTIFICATE := platform
#LOCAL_PRIVILEGED_MODULE := true
LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_APPS)
#LOCAL_REPLACE_PREBUILT_APK_INSTALLED := $(LOCAL_PATH)/app/$(LOCAL_MODULE).apk
include $(BUILD_PREBUILT)

include $(CLEAR_VARS)
LOCAL_MODULE        := libtensorflowlite_jnidd
LOCAL_MODULE_CLASS  := SHARED_LIBRARIES
LOCAL_MODULE_SUFFIX := .so
LOCAL_STRIP_MODULE  := false
LOCAL_MULTILIB      := 64
LOCAL_MODULE_OWNER  := qcom
LOCAL_MODULE_TAGS   := optional
LOCAL_SRC_FILES     := app/lib64/libtensorflowlite_jnidd.so
LOCAL_MODULE_PATH   := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_VENDOR)/lib64
LOCAL_PROPRIETARY_MODULE := true
include $(BUILD_PREBUILT)

而且还得增加:

同样需要修改device.mk,把需要打包的文件添加到变量PRODUCT_PACKAGES中:

PRODUCT_PACKAGES += \

或者 直接copy进out目录中:

可以修改device.mk中的PRODUCT_COPY_FILES

三,修改vendor/qcom/proprietrary/common/config/public.libraries.txt文件,公布出去,增加如下

libtensorflowlite_jnidd.so

Android N 版本有个新feature,就是普通应用不能直接引用系统的一些so库了,只能直接引用public.libraries.txt文件中过滤的so库

编译后查看out目录下vendor/etc/public.libraries.txt是否存在。

四,以上三步就修改完成,在调用SO库中出现Selinux问题,参考我另外一篇专门讲解Selinux权限问题

另外,如果要将libxxx.so加入到system/lib 或者system/lib64中

1,可以修改device.mk中的PRODUCT_COPY_FILES 直接在编译的时候copy进system/lib64

2,并且需要修改system/core/rootdir/etc/public.libraries.android.txt,增加该libxxx.so

这同样处理后,在开机时zygote初始化时preload lib时会找不到libxxx.so的问题,,(奇怪只有加到public.libraries.android.txt中的so,zygote需preload ?)

经过分析:因缺少32bit so,导致开始zygote 32bit preload crash,解决方法:

同时预置32位和64位so文件至system/lib和system/lib64中,解决

另外一个方法,将系统修改为只支持64位,修改该文件:core_64_bit.mk,去掉32位的支持,也将导致不支持32位apk

<think>好的,我现在需要解决用户关于Android JNI开发中如何调用System/lib64目录下问题,用户已经拥有头文件。我需要逐步理清思路,确保回答正确且符合Android开发规范。 首先,用户的问题涉及调用系统,而系统通常位于/system/lib64(针对64位)或/system/lib(32位)。这些目录下的是系统预装的,普通应用无法直接访问,因为它们需要系统权限或者特定的签名。所以,我需要考虑如何让应用有权限加载这些。 接下来,用户已经生成了头文件,这意味着他们已经通过javah或类似工具生成了JNI所需的头文件,可能已经有了本地方法的声明。接下来的步骤应该是如何正确链接加载这些系统。 首先,动态加载系统通常使用System.loadLibrary,但系统可能已经被其他组件加载过,所以需要确认是否需要显式加载。不过,系统libc、libm等通常不需要显式加载,因为它们已经被系统加载。但如果是自定义的系统,可能需要通过System.loadLibrary来加载,但普通应用可能没有权限。 这时候需要考虑权限问题。普通应用无法直接访问/system/lib64下的,除非设备已经root,或者应用被签名成系统应用。因此,用户可能需要确认他们的应用是否有足够的权限。如果没有,可能需要寻找其他方法,比如将打包到APK中,或者通过NDK编译时链接系统。 接下来,如果用户确实有权限访问这些系统,那么他们需要在JNI代码中包含正确的头文件,在编译时链接这些。例如,在Android.mk或CMakeLists.txt中添加对应的依赖。比如,使用LOCAL_LDLIBS或target_link_libraries来链接这些。 另外,需要注意的名称是否正确。例如,如果名为libexample.so,那么在加载时应使用System.loadLibrary("example"),但如果是系统,可能需要使用全路径,但System.loadLibrary不支持全路径,只能加载应用本地或系统已知路径的。所以,如果系统不在默认的链接路径中,可能需要使用dlopen等函数动态加载,但这也需要权限。 此外,用户可能需要处理ABI兼容性问题,确保他们的应用编译时针对正确的ABI(如arm64-v8a),与系统的ABI匹配。否则可能会导致运行时错误。 还可能涉及到JNI函数的正确注册,确保本地方法能够正确映射到对应的C/C++函数,尤其是在使用静态注册或动态注册时需要注意方法签名的一致性。 总结下来,步骤可能包括: 1. 确认权限:应用是否有权限访问系统,是否需要系统签名或root。 2. 正确配置构建脚本(如CMake或ndk-build)来链接系统。 3. 在JNI代码中包含头文件正确实现本地方法。 4. 处理ABI兼容性加载的方式。 需要提醒用户,如果无法获取系统权限,可能需要寻找替代方案,例如将所需打包到APK中,或者通过其他IPC机制与系统服务通信,而不是直接调用系统。</think>在Android JNI开发中调用`/system/lib64`目录下的系统需遵循以下步骤: --- ### **一、前置条件检查** 1. **权限限制** - `/system/lib64`下的为系统级,普通应用**无权限直接调用** - 需满足以下条件之一: - 应用拥有`android:sharedUserId="android.uid.system"`(需系统签名) - 设备已Root,通过`System.load()`强制加载 2. **ABI匹配** 确保应用编译时目标ABI(如`arm64-v8a`)与系统的架构一致 --- ### **二、JNI配置步骤** #### 1. **声明Native方法** ```java public class NativeWrapper { // 声明与系统对应的native方法 public static native void systemLibraryMethod(); } ``` #### 2. **加载系统** ```java static { try { // 方式1:系统签名环境下直接加载 System.loadLibrary("system_lib_name"); // 去掉lib前缀.so后缀 // 方式2:Root设备强制加载(需处理异常) // System.load("/system/lib64/libsystem_lib_name.so"); } catch (UnsatisfiedLinkError e) { e.printStackTrace(); } } ``` --- ### **三、NDK编译配置** #### 1. **CMakeLists.txt配置** ```cmake add_library(your_jni_lib SHARED your_jni_source.cpp) # 链接系统 target_link_libraries(your_jni_lib log system_lib_name) # 直接使用系统名称 ``` #### 2. **处理头文件依赖** - 将已有头文件放入`app/src/main/cpp/include` - 配置头文件搜索路径: ```cmake include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/include) ``` --- ### **四、JNI实现逻辑** ```cpp #include <jni.h> #include "system_lib_header.h" // 用户提供的系统头文件 extern "C" JNIEXPORT void JNICALL Java_com_example_NativeWrapper_systemLibraryMethod(JNIEnv *env, jclass clazz) { // 调用系统函数 system_library_function(); } ``` --- ### **五、常见问题处理** 1. **UnsatisfiedLinkError** - 检查名称拼写是否正确 - 验证是否存在:`adb shell ls /system/lib64 | grep libname` 2. **权限问题** - 非系统应用建议改用NDK编译静态链接,或通过Binder与系统服务交互 3. **API兼容性** - 系统可能依赖特定Android版本,需在`AndroidManifest.xml`中设置`minSdkVersion` --- ### **六、替代方案建议** 若无法获取系统权限,可考虑: 1. 将所需**重新编译**后打包到APK的`jniLibs`目录 2. 通过`AIDL`或`HIDL`与系统服务通信 --- 通过以上步骤,结合权限编译配置,即可实现对系统的调用。请根据实际环境调整安全策略。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值