【Android N兼容问题】Android N上系统预置应用调用so库失败问题的看法

本文解决AndroidN系统预置应用调用第三方库初始化失败问题,通过修改system/lib目录权限,使预置应用能正确加载SO库。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先引一篇博文,主要是根据这篇博文和一些其他的资料最终解决的问题

【Android N兼容问题】Android N上系统预置应用调用第三方库初始化失败

博文中该博主遇到的问题是内置应用调用百度地图的so库,结果报错

他的错误信息中有参考意义的主要是这一条

05-22 10:02:17.963 11659 11659 E linker  : library "/data/user/0/com.xxx.xxx.voc/lib/libgnustl_shared.so" ("/system/priv-app/xxx/lib/arm/libgnustl_shared.so") needed or dlopened by "/system/lib/libnativeloader.so" 
is not accessible for the namespace: [name="classloader-namespace", ld_library_paths="", default_library_paths="", permitted_paths="/data:/mnt/expand"]

以及

Caused by: java.lang.UnsatisfiedLinkError: dlopen failed: library "/data/user/0/com.xxx.xxx.voc/lib/libgnustl_shared.so" 

这里附上我的log,有参考意义的主要是这一条

A401-01 08:02:10.755  2883  2902 E AndroidRuntime: java.lang.UnsatisfiedLinkError: Error unpacking from JAR: Couldn't find SDK library in JAR.. Attempting to unpack from JAR because of previous error: dlopen failed: library "/system/lib/xxxx.so" needed or dlopened by "/system/lib/xxx.so" is not accessible for the namespace "classloader-namespace"

错误信息有一定出入,但其实问题是一样的

引用博文中给出的解决方案有两个

其一是将so库加到/bionic/linker/linker.cpp里的kLibraryGreyList列表中,或许是需要将绝对路径写上去或者是其他情况,我的改动没有作用,由于博主也说的并不明确,所以我决定放弃这种改法

其二是在/system/core/libnativeloader/native_loader.cpp中的static constexpr const char* kWhitelistedDirectories = "/data:/mnt/expand";的/data:/mnt/expand值后添加system/priv-app

在这一步我出现了问题,我和博主同样添加了system/priv-app但是我没有应有的效果,这时候回看我自己的log,发现差异的地方是,博主报错的so库位置是

/system/priv-app/xxx/lib/arm/xxx.so

而我的so库位置则是

/system/lib/xxx.so

所以我的修改不应该是system/priv-app而是system/lib

修改后就生效,可以正常调用so库了

总结

1,遇到这个问题,首先咱们需要注意的是上面log中的

UnsatisfiedLinkError 和 dlopen

这告诉了我们大概是调用so库失败造成的问题,然后我们需要注意的是错误信息中的so库地址,博主中的so库是位于priv-app中的一个和应用同名的文件夹中,我误以为是需要给priv-app中的该应用以权限调用so库,但其实这里的意思是告诉系统哪个位置的so库能够被动态链接

2,思路其实很简单,按照博主的思路走

安装和预装的区别其实和install和push的区别一样

前者:安装到data目录下,该目录下的so库被设置成可以被动态链接

后者:安装到system目录下,该目录没有被设置成可以被动态链接

于是出现的问题就是预装之后会报如上面log类似的错误,但是手动安装进去则不会

那么博主所做的其实只是看哪里设置了data目录可以被动态链接,然后在这个地方加上我们so库的地址,即system/lib或者是其他类似地址,所以回到总结1,我们需要注意自己so库的具体地址是哪里,添加对应地址才能完成修改

3,其实说心里话,这个问题最好解决的方式是在应用里修改调用so库的方式,方法已经满大街都是了,但是作为rom修改的话,我们可能没办法或者说比较难让应用方去做修改,所以只能让rom适配应用了......

转载于:https://www.cnblogs.com/Qunter/p/7485090.html

<think>好的,用户的问题是关于Android JNI开发如何依赖/system/lib64目录下的so,并且已经有了头文件。我需要先理清楚这个问题的关键点。 首先,用户想使用系统预装的so,这些位于/system/lib64下。在Android中,系统通常需要特定的权限或者系统签名才能访问,普通应用可能无法直接调用。所以需要确认用户的应用是否有系统权限或者是否是系统应用。 接下来,用户已经有头文件,说明他们已经知道需要调用的函数接口。这一步没问题,但需要确保头文件的正确性,比如函数声明和符号名称是否匹配。 然后是如何在Android项目中配置依赖。通常,使用JNI时会通过CMake或ndk-build来链接外部。这里的关键点是指定的路径和名称,但由于是系统,可能需要不同的处理方式。 系统可能已经被包含在NDK的查找路径中,比如liblog.so等。但如果是自定义的系统,可能需要手动指定路径。不过,/system/lib64是系统目录,普通应用可能没有权限访问,所以链接时可能会失败,或者运行时出现权限问题。 另外,需要注意Android版本的变化。在Android 7.0及以上,系统限制了直接使用系统,除非应用系统应用,或者具有相应的权限。所以用户可能需要将应用作为系统应用签名,或者找到其他方法。 可能的步骤包括: 1. 在CMakeLists.txt中添加的链接,使用全路径或者名称。 2. 在Java代码中加载,使用System.loadLibrary或者直接指定路径。 3. 处理权限问题,确保应用有权限访问系统。 但这里可能需要更具体的配置。比如,使用CMake时,可以通过添加target_link_libraries来链接系统,但由于这些系统目录,可能需要设置特定的标志或者路径。 另一个考虑是,如果so是NDK的一部分,可能已经存在别名,比如通过find_library来查找。但如果是第三方系统,可能需要直接引用名字,比如-lname。 用户可能遇到的问题包括链接失败,或者运行时找不到,或者权限被拒绝。需要提醒用户注意这些点,并检查应用的权限和签名。 总结来说,步骤应该是: 1. 确认应用权限,是否为系统应用。 2. 配置CMake或ndk-build以链接系统。 3. 在Java中加载。 4. 处理可能出现的权限和兼容性问题。</think>在Android JNI开发中依赖`/system/lib64`目录下的系统,需按以下步骤操作: --- ### 一、前置条件验证 1. **系统权限要求** `/system/lib64`目录需**系统应用**或**拥有root权限**才能访问,普通应用需添加系统签名: ```xml <!-- AndroidManifest.xml中添加系统权限 --> <uses-permission android:name="android.permission.ACCESS_SYSTEM_LIBRARIES"/> ``` 2. **ABI兼容性** 确保目标的CPU架构(如`arm64-v8a`)与应用配置一致。 --- ### 二、JNI配置步骤 #### 1. CMakeLists.txt配置(推荐) ```cmake cmake_minimum_required(VERSION 3.4.1) # 声明系统路径 set(SYSTEM_LIB_DIR /system/lib64) # 链接系统(假设名为libfoo.so) add_library(foo SHARED IMPORTED) set_target_properties(foo PROPERTIES IMPORTED_LOCATION "${SYSTEM_LIB_DIR}/libfoo.so") # 关联到你的JNI target_link_libraries(your_jni_lib foo) ``` #### 2. Android.mk配置(旧项目适用) ```makefile LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := your_jni_lib LOCAL_SRC_FILES := your_code.cpp # 直接链接系统 LOCAL_LDLIBS += -L/system/lib64 -lfoo include $(BUILD_SHARED_LIBRARY) ``` --- ### 三、Java层加载 ```java // 先加载系统依赖 static { try { System.loadLibrary("foo"); // 自动搜索/system/lib64 } catch (UnsatisfiedLinkError e) { // 备选方案:通过绝对路径加载(需root) // Runtime.getRuntime().load("/system/lib64/libfoo.so"); } } // 加载你的JNI System.loadLibrary("your_jni_lib"); ``` --- ### 四、常见问题处理 1. **链接失败** - 检查文件名是否正确(如`libfoo.so`对应`-lfoo`) - 使用`nm -D libfoo.so`验证符号是否存在 2. **运行时权限问题** ```logcat java.lang.UnsatisfiedLinkError: dlopen failed: library "libfoo.so" not found ``` - 确认设备`/system/lib64`下实际存在 - 系统应用需添加`android:sharedUserId="android.uid.system"` 3. **API级别限制** 高版本Android可能限制非系统应用访问系统目录,需通过`vendor`分区或预置系统应用解决。 --- ### 五、替代方案(若无系统权限) 1. **将复制到应用私有目录** ```bash adb pull /system/lib64/libfoo.so app/src/main/jniLibs/arm64-v8a/ ``` 2. **动态加载(需root)** ```java Runtime.getRuntime().exec("su -c cp /system/lib64/libfoo.so /data/data/your.package/"); ``` --- **最终建议**:优先与设备厂商合作,将预置到`/vendor/lib64`并通过标准NDK方式链接。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值