Android找不到so,实际上apk中有的

解决apk中有.so,实际运行时找不到的问题

排查方向:

  • ①、.so安装位置是否实际存在文件(context.getApplicationInfo().nativeLibraryDir
  • ②、当前ARM架构适配配置或者匹配(armeabi-v7a, arm64-v8a, x86_64, ...
  • ③、加载方式是否正确[System.loadLibrary("so_name_but_no_'lib'_prefix")/System.load("so_absolute_path")]
  • ④、Android版本(Android 31+),AGP版本(AGP 4.2.0+)参加下方配置 ↓↓↓
  • ⑤、android:extractNativeLibs=true是否配置(或者DSL选项useLegacyPackaging=true
  • ⑥、库文件没有访问权限
  1. Android .so存储位置
    可以通过如下方式获取so文件的加载位置
String so_path = context.getApplicationInfo().nativeLibraryDir; //查看加载 .so 的位置

举个栗子
系统应用:/system/lib/xxx[/vendor/lib (三方OEM厂商)] 或者 system/app/xxx/lib

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三方应用: data/app/[package-name]/lib
注意:package-name可能会是一串随机数字,可以通过如下adb命令行根据包名查看app的安装位置:
在这里插入图片描述
在这里插入图片描述
您可以通过如下代码查找.so文件所在的目录,参考自:

https://blog.csdn.net/wangbaochu/article/details/47805921

    /*** The function use to find so path for compatible android system* Android OS >= 2.3*/public static String findLibrary1(Context context, String libName) {String result = null;ClassLoader classLoader = (context.getClassLoader());if (classLoader != null) {try {Method findLibraryMethod = classLoader.getClass().getMethod("findLibrary", new Class<?>[] { String.class });   if (findLibraryMethod != null) {Object objPath = findLibraryMethod.invoke(classLoader, new Object[] { libName });if (objPath != null && objPath instanceof String) {result = (String) objPath;}}} catch (NoSuchMethodException e) {Log.e("findLibrary1", e.toString());} catch (IllegalAccessException e) {Log.e("findLibrary1", e.toString());} catch (IllegalArgumentException e) {Log.e("findLibrary1", e.toString());} catch (InvocationTargetException e) {Log.e("findLibrary1", e.toString());} catch (Exception e) {Log.e("findLibrary1", e.toString());}}return result;}/*** The function use to find so path for compatible android system* Android OS <= 2.2*/public static String findLibrary2(Context context, String libName) {String result = null;ClassLoader classLoader = (context.getClassLoader());if (classLoader != null) {try {Method findLibraryMethod = classLoader.getClass().getDeclaredMethod("findLibrary", new Class<?>[] { String.class });if (findLibraryMethod != null) {if (!findLibraryMethod.isAccessible()) {findLibraryMethod.setAccessible(true);}Object objPath = findLibraryMethod.invoke(classLoader, new Object[] { libName });if (objPath != null && objPath instanceof String) {result = (String) objPath;}}} catch (NoSuchMethodException e) {Log.e("findLibrary2", e.toString());} catch (IllegalAccessException e) {Log.e("findLibrary2", e.toString());} catch (IllegalArgumentException e) {Log.e("findLibrary2", e.toString());} catch (InvocationTargetException e) {Log.e("findLibrary2", e.toString());} catch (Exception e) {Log.e("findLibrary2", e.toString());}}return result;}
  1. 查看Android打包配置是否指定了对应ARM架构
android {// ... defaultConfig {// ...ndk {// 目前Android支持的ABIsabiFilters 'mips', 'mips64', 'x86', 'x86–64', 'arm64-v8a', 'armeabi', 'armeabi-v7a'}}
}

您可以通过如下代码获取当前设备支持的ABIs:

	/*** An ordered list of ABIs supported by this device** @return ABI*/public String[] getABIs() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {return Build.SUPPORTED_ABIS;} else {return new String[]{Build.CPU_ABI, Build.CPU_ABI2};}}

或者如下adb命令获取:
在这里插入图片描述
关于ABI架构引用如下文章:

https://www.jianshu.com/p/68b52659a5f6

1.在android4.4以下版本的安装过程中的,是先把所有so库全部寻找出来,然后优先列出cpu类型(通过ro.product.cpu.abi属性获得)目录下的so库,如果有其他的cpu类型下有跟手机cpu类型名称不一致的so库,则会将兼容cpu架构(通过ro.product.cpu.abi2属性获得)的另外的库也列出来。将列出来so库全部拷贝的系统指定目录,以供运行时加载。 即在android4.4以下版本,一个so库只要在 ro.product.cpu.abiro.product.cpu.abi2属性目录下至少存在一个就可以了。在android4.4以下的arm架构的设备 ro.product.cpu.abi的属性通常是armeabi-v7a, ro.product.cpu.abi2的属性值是armeabi,并且armeabi-v7a设备一定兼容armeabi。但不排除某些设备的ro.product.cpu.abi的属性为armeabi。

2.在android5.0及以上,由于增加了arm64的支持,app安装时的so库拷贝代码也修改了。修改成只拷贝一个最合适的目录下的so库到系统指定目录。 在arm架构下,64位cpu的优先级是arm64-v8a > armeabi-v7a > armeabi,32位cpu的优先级是armeabi-v7a > armeabi ,优先级可通过ro.product.cpu.abilist属性查看。由于android5.0是拷贝整体目录,所以在每一个目录下的,都必须要有完整的so,即所有app需要so库都要有。例如64位的cpu的设备上,
如果app目录里存在arm64-v8a子目录,则只拷贝该目录下的so库,其他目录的so,即使名称不一样,也不拷贝,如果arm64-v8a子目录的so库不全,则会报错。

  1. so加载方式不对
    目前有两种加载方式(以某个普通app下有个libtest.so文件为例):
    System.loadLibrary("so_name_but_no_'lib'_prefix") :会优先查找apk中的so目录,再查找系统目录,系统目录包括:/vendor/lib(64),/system/lib(64)
    System.load("so_absolute_path"): 直接加载制定路径下的so
System.loadLibrary("test");// libtest.so
String soRoot = context.getApplicationInfo().nativeLibraryDir;
System.load(soRoot + "/libtest.so");// libtest.so
  1. Google官方更新进行的调整和修改

https://developer.android.google.cn/guide/topics/manifest/application-element?hl=zh-cn

针对AGP >= 3.6.0需要在AndroidMainfest.xml清单文件中添加如下配置

<applicationandroid:extractNativeLibs="true"... >
</application>    

针对AGP >= 4.2.0需要在DSL中添加如下配置(上面配置过时)

android {packagingOptions {jniLibs {useLegacyPackaging true}}
}
  1. 库文件没有访问权限
    .so文件有权限限制(文件读写权限/系统访问权限限制),不允许访问,可通过如下命令查看对应文件的访问权限:

在这里插入图片描述
关于权限说明参考如下:

https://www.jianshu.com/p/ba0d31fc078a

drwxr-xr-x:应该分解为四部分
d rwx r-x r-x第一部分:d表示目录文件,-表示普通文件,l表示链接文件,p表示管道。
第二部分:root用户拥有的权限
第三部分:用户组拥有的权限
第四部分:其他用户拥有的权限r表示可读,w表示可写,x表示可执行,r-x表示可读可执行不可写查看文件权限方法:
ls -lO (大写的o) + 所在文件夹路径

举个栗子:
app需要引用系统的so库,当install形式的时候安装时,打开app需要使用/system/lib64目录下的so库时,提示不能访问。
原因分析:放到system/app下的app是可以找到的,但是普通的安装形式的app是没有权限访问的,所以需要需要声明公有so库才能使用

library "/system/lib64/libserialport.so" ("/system/lib64/libhqbindcs.so") needed or
dlopened by"/system/lib64/libhqbindcs.so" is not accessible for the namespace
"classloader-namespace"

解决方法:
修改system/core/rootdir/etc/public.libraries.txt
添加你要使用的的so到此问题件中。

cat public.libraries.txt 
....
libz.so
libhqbindcs.so

也可以直接不编译在板子上修改,对应目录/system/etc

https://wkingdom.github.io/2020/04/04/JNI%E6%97%A0%E6%B3%95%E8%AE%BF%E9%97%AEso%E6%8F%90%E7%A4%BAnot%20accessible/
https://www.jianshu.com/p/4be3d1dafbec

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/30291.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

机器学习课程复习——ANN

Q&#xff1a;ANN&#xff1f; 基本架构 由输入层、隐藏层、输出层等构建前馈/反馈传播 工作原理 先加权求和&#xff1a;每个神经元的输出是输入加权和的激活再送入激活函数&#xff1a;激活函数的存在使得其能够拟合各类非线性任务 联想&#xff1a;像adaboosting的加权求…

【CT】LeetCode手撕—手撕快排

目录 题目1-思路-快排1-1 快排的核心思想快速排序算法步骤优美的调整区间 1-2 ⭐快排的实现 2- 实现⭐912. 排序数组——题解思路 3- ACM 实现 题目 原题连接&#xff1a;912. 排序数组 1-思路-快排 1-1 快排的核心思想 选择一个基准 基准左侧的元素都小于该元素基准右侧的元…

旅游小程序(Uniapp+FastAdmin+ThinkPHP)

&#x1f30f;旅游系统小程序&#xff0c;开启智慧旅行新纪元&#xff01;&#x1f680; 一款基于UniappFastAdminThinkPHP开发的旅游系统&#xff0c;包含消费者端&#xff08;手机端&#xff09;、机构工作人员&#xff08;手机端&#xff09;、机构端&#xff08;PC&#x…

[Qt] Qt Creator中配置 Vs-Code 编码风格

新建vscode-onedark.xml文档 &#xff0c;将如下内容复制进去&#xff0c;并配置到Creator中&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <style-scheme version"1.0" name"One Dark"><style name"Tex…

判断单链表是否带环且返回节点

今天鄙人为大家带来的是一道简单的逻辑运算题。用用到了一个我们在链表中提及过的方法快慢法。这道题其实没啥考的实际意义。只是我们如果能了解这道题的解决方法的话。对我们后面梳理逻辑会有很大的帮助。 单链表的题目 我们可以看到上面的题目。就是让我们判断是否带环。也许…

14 学习PID--步进电机梯形加减速实现原理

步进电机加减速使用的场景有那些呢&#xff1f;为什么要使用加减速呢&#xff1f; 硬件驱动细分器与软件的细分参数或定时器分频参数设置不当时启动电机时&#xff0c;会遇见步进电机有啸叫声但是不会转动&#xff0c;这是因为软件产生脉冲的频率大于步进电机的启动频率&#x…

2023-2024“讯方杯”全国总决赛即将开赛,精彩一触即发!

讯方杯 2023-2024“讯方杯”全国大学生信息技术应用及创新大赛全国总决赛将于2024年6月21日一23日在广东东莞举行&#xff0c;旨在为全国高校大学生打造竞技和交流平台&#xff0c;提升学生的ICT知识水平和实践动手能力&#xff0c;助力学生迈向更高的竞赛舞台。 本次大赛由深…

《QT从基础到进阶·七十二》基于Qt开发的文件保险柜工具并支持文件各种加密和解密

1、概述 源码放在文章末尾 该项目实现了文件各种加密和解密的功能&#xff0c;能够有效的保障文件的安全&#xff0c;主要包含如下功能&#xff1a; 1、支持所有 AES 密钥长度&#xff1b; AES_128 AES_192 AES_256 2、支持ECB、CBC、CFB、OFB四种模式&#xff1b; 3、支持ZER…

MyBatis的配置文件,即:src->main->resources的配置

目录 1、properties 标签 1.1 mybatis-config.xml 1.2 db.properties 1.3 在SqlMapConfig.xml 中 引入数据库配置信息 2、typeAliases 标签 2.1 定义别名 2.2 使用别名 3、Mappers标签 作用&#xff1a;用来在核心配置文件中引入映射文件 引入方式&#xff0c;有以下…

AI 已经在污染互联网了。。赛博喂屎成为现实

大家好&#xff0c;我是程序员鱼皮。这两年 AI 发展势头迅猛&#xff0c;更好的性能、更低的成本、更优的效果&#xff0c;让 AI 这一曾经高高在上的技术也走入大众的视野&#xff0c;能够被我们大多数普通人轻松使用&#xff0c;无需理解复杂的技术和原理。 其中&#xff0c;…

爆赞!24年GitHub首本Python开发实战背记手册,标星果然百万名不虚传

Python (发音:[ paiθ(ə) n; (US) paiθɔn ] n. 蟒蛇&#xff0c;巨蛇 )&#xff0c;是一种面向对象的解释性的计算机程序设计语言&#xff0c;也是一种功能强大而完善的通用型语言&#xff0c;已经具有十多年的发展历史&#xff0c;成熟且稳定。Python 具有脚本语言中最丰富…

新火种AI|实属罕见!四大AI顶流同台,有哪些关键信息值得关注?

作者&#xff1a;小岩 编辑&#xff1a;彩云 在有着“AI春晚”之称的2024年智源大会上&#xff0c;非常难得的一幕出现了&#xff1a;当下国内的四大AI顶流公司——月之暗面&#xff0c;百川智能&#xff0c;智谱AI&#xff0c;面壁智能齐聚一堂&#xff0c;十分罕见的同台了…

天地图 uniapp使用笔记

官网地址&#xff1a;天地图API 效果&#xff1a; <template><view><!-- 显示地图的DOM节点 --><view id"container" class"content"></view><!-- END --><!-- 数据显示 --><h3>城市名称(IP属地)&#x…

Fisnar Liquid Control 操作维修手LC Pump Manual Twinmixer Maintenance 中文

Fisnar Liquid Control 操作维修手LC Pump Manual Twinmixer Maintenance 中文

Jquery 正则匹配字母、数字、-

Jquery 正则匹配字母、数字、- Jquery正则方式一Jquery正则方式二 本文主要讲述页面日常开发过程中需要校验输入参数时&#xff0c;采用正则校验的方式的使用方法&#xff0c;一共有两种形式&#xff0c;其中本文用到的正则公式主要是匹配字母、数字、中横线如下 Jquery正则方式…

DAY03 HTML

文章目录 一 表格1. 表格的语法2. 表格的可选标记3. 不规则的单元格&#xff08;合并单元格&#xff09;4. 表格的属性5. 表格的大小 二 列表1. 有序列表2. 无序列表3. 属性4. 列表的嵌套5. 定义列表【了解】 三 表单(重点)1. 表单的语法2. 表单的控件分类3. input元素4. selec…

智慧工地系统源码,支持项目级、公司级、集团级多级权限划分,支持PC端、手机端

智慧工地的核心是数字化&#xff0c;它通过传感器、监控设备、智能终端等技术手段&#xff0c;实现对工地各个环节的实时数据采集和传输&#xff0c;如环境温度、湿度、噪音等数据信息&#xff0c;将数据汇集到云端进行处理和分析&#xff0c;生成各种报表、图表和预警信息&…

Deflate内部实现(LZ77无损压缩算法)超详细图解算法版~

无损压缩算法 第一阶段&#xff1a;重复消除 — LZ77无损压缩算法算法介绍举例压缩算法思路图解压缩过程 第二阶段&#xff1a;位减少huffman位减少 概览 Gzip Deflate 编码&#xff08;LZ77哈夫曼&#xff09; Brotli LZ77哈夫曼二阶上下文建模 Deflate 分两个阶段压缩数据…

【Linux】Centos升级到国产操作系统OpenAnolis

一、前言 Anolis OS 7生态上和依赖管理上保持跟CentOS7.x兼容&#xff0c;一键式迁移脚本centos2anolis.py&#xff0c;实现CentOS7.x到Anolis OS 7的平滑迁移 使用迁移脚本前需要注意如下事项&#xff1a; 迁移涉及到软件包的重新安装&#xff0c;是不可逆过程&#xff0c;…

基于SpringBoot的社区医院管理服务系统

开头语&#xff1a;你好呀&#xff0c;我是计算机学姐码农小野&#xff01;如果有相关需求&#xff0c;可以私信联系我。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot框架 工具&#xff1a;Eclipse&#xff0c;Navicat&#xff0c;Maven…