Android中使用System.load加载指定路径.so库失败的排查求助
看起来你遇到的核心问题确实是SELinux的权限限制——虽然文件权限显示正常,但SELinux的上下文规则才是这里的拦路虎。下面是几个按推荐程度排序的可行解决方向:
优先方案:将SO库放到应用默认Native库目录,用
System.loadLibrary()加载
Android为每个应用预设了专门存放Native库的目录:/data/data/your.package.name/lib/(64位设备对应lib64子目录),这个目录的SELinux策略默认允许应用直接读取。你只需要把mylibrary.so移到这个目录下,然后用System.loadLibrary("mylibrary");(注意不需要加.so后缀)加载即可,系统会自动处理路径和权限逻辑,这也是官方推荐的标准做法,能彻底规避SELinux限制。检查并修正SO文件的SELinux上下文
如果一定要把SO放在自定义路径(不推荐),可以通过root权限的adb shell先检查文件的SELinux上下文:ls -Z /data/data/my.package.name/mylibrary.so正常的应用私有文件上下文应该类似
u:object_r:app_data_file:s0:cXX,cYY(其中cXX,cYY是应用对应的SELinux seccomp级别)。如果你的文件上下文异常(比如是u:object_r:sdcard_file:s0这类),可以用chcon命令修改:chcon u:object_r:app_data_file:s0:cXX,cYY /data/data/my.package.name/mylibrary.so这里的
cXX,cYY可以从你应用目录下其他正常文件的上下文里复制(执行ls -Z /data/data/my.package.name/查看即可)。修改完成后再尝试加载,应该能绕过SELinux的读取拦截。临时关闭SELinux(仅用于调试,生产环境绝对禁止)
如果你只是想快速确认问题根源是否为SELinux,可以临时将SELinux切换为宽容模式:su setenforce 0重启应用测试,如果加载成功,就坐实了SEPolicy的限制问题。但这个方法仅限调试使用,生产环境绝对不能这么做,会严重破坏系统安全性。
补充说明:Android Nougat+限制的是加载系统分区的非公开库,你自己的私有库不在此限制范围内,所以核心问题还是路径选择和SELinux上下文配置。
内容的提问来源于stack exchange,提问作者Luca D'Amico

