Android 系统源码项目加载预编好的so库

Android 系统源码项目加载预编好的so库

文章目录

  • Android 系统源码项目加载预编好的so库
    • 一、前言
    • 二、源码中加载so
      • 1、Android.mk加载so
        • 加载so的主要相关代码:
      • 2、Android.bp加载so
        • (1)Android.mk使用源码命令编译成Android.bp
        • (2)Android.bp
        • Android.bp 不用编译so并进行读取so解决方法:
    • 三、其他
      • 1、系统源码加载编译so小结
      • 2、Android.mk中可以执行 PRODUCT_COPY_FILES 吗?
      • 3、mk 添加编译androidx相关包报错解决
      • 4、Android.mk 在源码中执行执行转换成Android.bp

一、前言

Android 系统开发中会源代码有加载so库的情况,本文进行简单介绍。

Android Studio 项目加载so库,已经有介绍过:

https://blog.csdn.net/wenzhi20102321/article/details/137080360

Android Studio加载so和使用so还是比较方便的,环境OK的情况,几分钟就可以完成验证测试了。

但是如果要在系统源代码Java里面加载和使用so就比较麻烦了,

主要通过Android.mk或者Android.bp编译加载so,反正网上的代码写的mk/bp基本都是不行的。

本来以为只是介绍一下编译使用的Android.mk或者Android.bp就可以了,

但是事实有点出乎意料,总结下来发现收获了一些知识点;

所以这个很有必要进行总结一下。有兴趣的可以看看。

普通应用开发不一定用到这个知识,但是系统编译开发会用到这个知识,并且有的相关文件还不好解决。

本文最后还有一些源码编译apk相关知识的总结,还是比较有用的。可以点赞收藏。

二、源码中加载so

源码中加载so,首选是Android.mk,因为Android.bp 未完善,会有bug。

1、准备源码

这里准备的源码和Android Studio 加载so的源码是一模一样的,
只是在app同级目录下加一个Android.mk 或者Android.bp。

1、Android.mk加载so

LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)
LOCAL_PACKAGE_NAME := JniLoadsoLOCAL_MODULE_TAGS := optional
LOCAL_CERTIFICATE := platform
LOCAL_PRIVATE_PLATFORM_APIS := true
#生成到system/priv-app目录
LOCAL_PRIVILEGED_MODULE := trueLOCAL_DEX_PREOPT := falseLOCAL_MANIFEST_FILE := \app/src/main/AndroidManifest.xmlLOCAL_SRC_FILES := \$(call all-java-files-under,app/src/main/java/) \LOCAL_RESOURCE_DIR := \$(LOCAL_PATH)/app/src/main/resLOCAL_PREBUILT_JNI_LIBS:= \app/jni/arm64-v8a/libnative-lib.so
#这样加没用!!不知为啥
#LOCAL_SHARED_LIBRARIES := libnative-libLOCAL_STATIC_ANDROID_LIBRARIES := \androidx.recyclerview_recyclerview \com.google.android.material_materialLOCAL_STATIC_JAVA_LIBRARIES := \androidx.appcompat_appcompat \androidx-constraintlayout_constraintlayoutinclude $(BUILD_PACKAGE)include $(CLEAR_VARS)
LOCAL_MODULE := libnative-lib
LOCAL_SRC_FILES := app/jni/arm64-v8a/libnative-lib.so
include $(PREBUILT_SHARED_LIBRARY)

上面加了Androidx的包,需要在AndroidManifest.xml进行适配修改一下否则会编译报错。具体如何适配最后有说明;Android13或者Android14 源码编译会有这个问题。

这里的Android.mk 直接放在app同级目录下面就行,

我不喜欢放两个Android.mk的处理,实际上很多源码应用是这样处理的:
app同级目录下放一个声明链接的Android.mk,app/src/main/ 下面也放一个实际起作用的Android.mk;

加载so的主要相关代码:
LOCAL_PREBUILT_JNI_LIBS:= \app/jni/arm64-v8a/libnative-lib.so
#这样加没用!!不知为啥
#LOCAL_SHARED_LIBRARIES := libnative-libinclude $(CLEAR_VARS)
LOCAL_MODULE := libnative-lib
LOCAL_SRC_FILES := app/jni/arm64-v8a/libnative-lib.so
include $(PREBUILT_SHARED_LIBRARY)

上面和so相关就就LOCAL_PREBUILT_JNI_LIBS这一行代码,其他的编译命令和编译普通Java代码项目是一样的。

加入这个后,系统会在apk的同级目录下生成so文件。

后续有尝试去除 PREBUILT_SHARED_LIBRARY ,其实也是可以生成so在lib目录的。

所以主要作用的文件就是:

LOCAL_PREBUILT_JNI_LIBS:= \app/jni/arm64-v8a/libnative-lib.so

out目录生成后的so文件,如下图所示:

在这里插入图片描述

整编整个大包,烧录到系统,这个so就会在运行的Android设备apk的lib目录下。具体情况:

rk3588_t:/system/priv-app/JniLoadso #
rk3588_t:/system/priv-app/JniLoadso # ls
JniLoadso.apk  lib  oat
rk3588_t:/system/priv-app/JniLoadso # ls lib/arm64/
libnative-lib.so
rk3588_t:/system/priv-app/JniLoadso #

app应用运行后是可以正常读取到so库的。

2、Android.bp加载so

Android.bp 如何编写?

其实系统源码中有个android.go 文件是写了Android.mk和Android.bp所有对于属性的转换关系的。

但是并不是所有的标签都能转换。估计是实现了比较常用的大部分功能。

(1)Android.mk使用源码命令编译成Android.bp

源码中如何实现转换的,最后有链接,有兴趣的可以看看。

通过转换后获取到Android.bp:

android_app {name: "JniLoadso",certificate: "platform",platform_apis: true,//生成到system/priv-app目录privileged: true,dex_preopt: {enabled: false,},manifest: "app/src/main/AndroidManifest.xml",srcs: ["app/src/main/java//**/*.java"],resource_dirs: ["app/src/main/res"],// ANDROIDMK TRANSLATION ERROR: unsupported assignment to LOCAL_PREBUILT_JNI_LIBS// LOCAL_PREBUILT_JNI_LIBS := app/jni/arm64-v8a/libnative-lib.so//这样加没用!!不知为啥//LOCAL_SHARED_LIBRARIES := libnative-libstatic_libs: ["androidx.recyclerview_recyclerview","com.google.android.material_material","androidx.appcompat_appcompat","androidx-constraintlayout_constraintlayout",],}// ANDROIDMK TRANSLATION ERROR: unsupported include
// include $(PREBUILT_SHARED_LIBRARY)

虽然生成了Android.bp但是最后提示有ERROR,并且LOCAL_PREBUILT_JNI_LIBS指令是无法转换的。

所以Android使用源码命令转换Android.mk,在一些特殊的模块处理上是有问题的,比如so加载就有问题。

并且在mk和bp转换的关系源码android.go中也是未找到 LOCAL_PREBUILT_JNI_LIBS 的转换关系;

所以这个是目前Android14 也无法解决的问题;使用Android.bp就是无法编译加载so。

但是上面的Android.bp 是可以正常编译出apk的,只是编译出的out目录apk中未生成lib目录。

所以Android.bp 没法编译加载so项目吗,其实不是。

因为在源码中这样编译so项目是没问题的。但是要多做一些操作。往后看看吧。

(2)Android.bp

有用部分的源码:

android_app {name: "JniLoadso",platform_apis: true,certificate: "platform",optimize: {proguard_flags_files: ["app/src/main/proguard.flags"],},privileged: true,static_libs: ["androidx.appcompat_appcompat","androidx-constraintlayout_constraintlayout","androidx.annotation_annotation","com.google.android.material_material","androidx-constraintlayout_constraintlayout","androidx.recyclerview_recyclerview",],manifest: "app/src/main/AndroidManifest.xml",srcs: ["app/src/main/java/**/*.java",],resource_dirs: ["app/src/main/res"],}

这样编译后运行的设备中未包含 JniLoadso 应用需要的so,那么点击运行应用肯定会报错的,怎么解决?

Android.bp 不用编译so并进行读取so解决方法:
1、Android 系统编译源码应用可以读取系统so;
如果apk应用是64位的(目前99%应用都是64位的),那么系统可以读取到system/lib64下面的so;
2、如果是限制单个应用使用,可以通过脚本把so放到运行环境的apk的lib/arm64/目录下;
3、apk优先是读取自己目录下的lib,如果没有就读取系统下的 system/lib64的so
这是亲自测试验证过的,两个地方只有一个地方有就可以正常读取到。

其实如何读取不用我们管,系统会实现;

具体要管的就是系统运行环境有没有放入so文件,有就可以读取到,没有就会报错。

系统编译的app应用代码中只要定义了加载so

    static {System.loadLibrary("native-lib");}

那如果运行环境中如果存在so就没有问题。

原因和思路找到了,源码里面怎么写这个脚本呢?

1、复制文件到system/lib64PRODUCT_COPY_FILES += device/copyfile/libnative-lib.so:$(TARGET_COPY_OUT_SYSTEM)/lib64/libnative-lib.so//PRODUCT_COPY_FILES 目录是以release目录为基准的;
//copyfile 这个文件夹是自己添加的,自定义的,可以根据自己情况设置。2、复制文件到某个apk的目录下:
PRODUCT_COPY_FILES += device/copyfile/libnative-lib.so:$(TARGET_COPY_OUT_SYSTEM)/priv-app/JniLoadso/lib/arm64/libnative-lib.so

PRODUCT_COPY_FILES 指令,相信很多搞过系统源码都是知道的,这个就是复制文件的;

在device下的某个mk文件都有这个指令,在device目录其中一个起作用的写入上面的指令就可以。

正常情况下,写了上面指令,系统源码编译后就会在out目录下生成so文件,

比如写了第一条指令,就会在out/target/XXX…/system/lib64 看到 libnative-lib.so 文件。

三、其他

1、系统源码加载编译so小结

(1) Android.mk 中可以使用 LOCAL_PREBUILT_JNI_LIBS指令复制so到编译的XXXapk/lib/arm64/目录下;
(2) Android.bp 没有指令复制so到编译的apk目录下;
(3) Android 系统编译源码应用可以读取系统so和apk目录下的lib/arm64/的so文件
(4) 如果是使用Android.bp编译so项目,
必须要写脚本命令复制so到system/lib64 或者复制到apk的ib/arm64/
(5) 如果是使用Android.mk编译so项目,
即可使用LOCAL_PREBUILT_JNI_LIBS指令复制so,也可以在另外的mk文件使用脚本复制so文件到system/lib64 或者复制到apk的ib/arm64/
(6) 如果是单个应用使用的so,使用复制脚本命令把so文件复制到到apk的ib/arm64/就可以;如果是多个应用使用到的so,使用复制脚本命令把so文件复制到到system/lib64/比较好。

其实那些编译apk的指令都是差不多的,很多网上搜索到不可用的指令,参考系统源码其他apk编译的就可以;

最重要的是学习到了系统中编译源码apk 会读取 apk的ib/arm64/或者system/lib64 下面的so;

加载so一定是以so文件名称作为唯一标识的,如果so文件名称不对是读取不到的;

Java代码中读取so:

    static {System.loadLibrary("native-lib");}

那么so的名称一定要设置成 libnative-lib.so(native-lib.so是不行的),也就是说前面加lib,后面加.so,就是so文件的命名。

2、Android.mk中可以执行 PRODUCT_COPY_FILES 吗?

很多人可能没试过,不确定有没有作用。

我之前也么试过,今天特意试了一下,确实不行。

Android.mk中可以执行 PRODUCT_COPY_FILES 会报错:

FAILED: 
In file included from build/make/core/prebuilt.mk:53:
packages/SkgApps/JniLoadso/Android.mk:36: error: cannot assign to readonly variable: PRODUCT_COPY_FILES

其实想一下就知道了,Android.mk里面应该是执行有限的指令和标签的;

在android.go里面确实是没有这个 PRODUCT_COPY_FILES 指令的。

3、mk 添加编译androidx相关包报错解决

AndroidManifest.xml.fixed 的分析处理:

https://blog.csdn.net/wenzhi20102321/article/details/138334484

4、Android.mk 在源码中执行执行转换成Android.bp

Android.mk和Android.bp的区别和转换详解:

https://blog.csdn.net/wenzhi20102321/article/details/135704801

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

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

相关文章

【C++】STL容器详解【下】

目录 一、list容器 1.1 list基本概念 1.2 lsit构造函数 1.3 list数据元素插入和删除操作 1.4 list大小操作 1.5 list赋值操作 1.6 list数据的存取 1.7 list反转排序 二、set/multiset容器 2.1 set/multiset基本概念 2.2 set构造函数 2.3 set赋值操作 2.4 set大小操…

Hash Table、HashMap、HashSet学习

文章目录 前言Hash Table(散列表)基本概念散列函数散列冲突(哈希碰撞)拉链法红黑树时间复杂度分析 HashMap基础方法使用基本的增删改查其他的方法 实现原理 HashSet基础操作去重原理 前言 本文用于介绍关于Hash Table、HashMap、…

【qt】多线程实现倒计时

1.界面设计 设置右边的intvalue从10开始倒计时 2.新建Thread类 新建Thread类,使其继承QThread类,多态重写run函数,相当于线程执行函数 3.重写run函数 重写run函数,让另一个进程每隔1s发出一个信号,主线程使用conne…

uniapp 全屏日历,动态无限加载

不好用请移至评论区揍我 原创代码,请勿转载,谢谢! 注:本人仅在微信小程序测试过,未在其他app/h5尝试过,按理说应该是可以的,代码没有引用任何第三方组件 日历中每个日期下方的空白部分均可自定义,写在代码中的<view class="item">我是内容</view>…

Prometheus 服务监控

目录 Prometheus 是什么 Prometheus 的特点 Prometheus 的组件 Prometheus 的指标 Prometheus 的使用场景 Prometheus 的安装 方式一&#xff1a;压缩包方式安装 方式二&#xff1a;Docker 方式安装 Prometheus 的 Web UI 面板介绍 Prometheus 目录结构介绍 Prometh…

简单的Linux Ftp服务搭建

简单的Linux FTP服务搭建 1.需求 公司有一个esb文件传输代理&#xff0c;其中我们程序有文件传输功能&#xff0c;需要将本地文件传输到esb文件代理服务器上&#xff0c;传输成功之后发送http请求&#xff0c;告知esb将固定文件进行传输到对应外围其他服务的文件目录中&#…

unity GridLayoutGroup真正的居中

GridLayoutGroup默认的居中效果: 不是真正的居中 加上代码: namespace UnityEngine.UI {/// <summary>/// GridLayoutGroup拓展&#xff0c;使支持自定义内容/// </summary>internal class GridLayoutGroupEx : GridLayoutGroup{/// <summary>/// 启用居中/…

香橙派转换模型以及在开发板上部署

新手小白记录一下自己使用香橙派模型转换以及在开发板上运行的过程&#xff0c;防止后面忘记。 使用的开发板&#xff1a;Orange Pi 5 Plus&#xff08;rk3588&#xff09; 官方的一些资料在&#xff08;主要参考用户手册&#xff09;&#xff1a;Orange Pi - Orangepihttp:/…

【视频讲解】Python贝叶斯卷积神经网络分类胸部X光图像数据集实例

全文链接&#xff1a;https://tecdat.cn/?p37604 分析师&#xff1a;Yuanchun Niu 在人工智能的诸多领域中&#xff0c;分类技术扮演着核心角色&#xff0c;其应用广泛而深远。无论是在金融风险评估、医疗诊断、安全监控还是日常的交互式服务中&#xff0c;有效的分类算法都是…

科研绘图系列:R语言富集散点图(enrichment scatter plot)

介绍 富集通路散点图(Enrichment Pathway Scatter Plot)是一种数据可视化工具,用于展示基因集富集分析(Gene Set Enrichment Analysis, GSEA)的结果。 横坐标是对应基因名称,纵坐标是通路名称,图中的点表示该基因在某个通路下的qvalue,可以简单理解为不同环境下的贡献…

【全网最全】2024年数学建模国赛A题30页完整建模文档+17页成品论文+保奖matla代码+可视化图表等(后续会更新)

您的点赞收藏是我继续更新的最大动力&#xff01; 一定要点击如下的卡片那是获取资料的入口&#xff01; 【全网最全】2024年数学建模国赛A题30页完整建模文档17页成品论文保奖matla代码可视化图表等&#xff08;后续会更新&#xff09;「首先来看看目前已有的资料&#xff0…

【ACM独立出版|EI快检索-高录用|IEEE Fellow支持】2024年数字经济与计算机科学国际学术会议(DECS2024)

【ACM独立出版&#xff5c;EI快检索-高录用&#xff5c;IEEE Fellow支持】 2024年数字经济与计算机科学国际学术会议&#xff08;DECS2024&#xff09; *ACM独立出版&#xff0c;快检索&#xff0c;高录用 *见刊后1个月左右完成EI&Scopus检索 *国内211大学、世界QS名校…

系统架构师-ERP+集成

ERP 集成平台end&#xff1a;就懒得画新的页

MyBatis-MappedStatement什么时候生成?QueryWrapper如何做到动态生成了SQL?

通过XML配置的MappedStatement 这部分MappedStatement主要是由MybatisXMLMapperBuilder进行解析&#xff0c;核心逻辑如下&#xff1a; 通过注解配置的MappedStatement 核心逻辑就在这个里面了&#xff1a; 继承BaseMapper的MappedStatement 我们看看这个类&#xff0c;里…

Java项目——苍穹外卖(一)

Entity、DTO、VO Entity&#xff08;实体&#xff09; Entity 是表示数据库表的对象&#xff0c;通常对应数据库中的一行数据。它通常包含与数据库表对应的字段&#xff0c;并可能包含一些业务逻辑。 DTO&#xff08;数据传输对象&#xff09; 作用&#xff1a;DTO 是用于在…

【小沐学OpenGL】Ubuntu环境下glfw的安装和使用

文章目录 1、简介1.1 OpenGL简介1.2 glfw简介 2、安装glfw2.1 直接命令二进制安装2.2 源码安装 3、测试glfw3.1 测试1&#xff0c;glfwglew3.2 测试2&#xff0c;glfwglad3.3 测试3 结语 1、简介 1.1 OpenGL简介 OpenGL作为图形界的工业标准&#xff0c;其仅仅定义了一组2D和…

Vivado编译报错黑盒子问题

1 问题描述 “Black Box Instances: Cell **** of type ** has undefined contents and is considered a back box. The contents of this cell must be defined for opt_design to complete successfully.” 检查工程代码提示的模块&#xff0c;该模块为纯手写的Veril…

注册安全分析报告:熊猫频道

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞…

【论文阅读】CiteTracker: Correlating Image and Text for Visual Tracking

paper&#xff1a;[2308.11322] CiteTracker: Correlating Image and Text for Visual Tracking (arxiv.org) code&#xff1a;NorahGreen/CiteTracker: [ICCV23] CiteTracker: Correlating Image and Text for Visual Tracking (github.com) 简介 现有的视觉跟踪方法通常以…

前端:HTML、CSS、JS、Vue

1 前端 内容概要 了解前端三件套(HTML、CSS、JS)在前端所起的作用掌握HTML标签的功能&#xff0c;掌握重要标签(a标签&#xff0c;form标签)了解CSS了解JS的基础语法掌握Vue的基础语法重点掌握Vue项目怎么启动项目掌握前后端分离是什么。前端做什么事情&#xff0c;后端做什么…