Android13 系统源码适配安装可卸载的三方apk应用
Android13 系统源码适配安装可卸载的三方apk应用
文章目录
- Android13 系统源码适配安装可卸载的三方apk应用
- 一、前言
- 二、Android 系统运行后默认安装三方apk实现
- 1、Android 系统默认安装三方apk实现主要思路
- 2、Android 系统默认安装三方apk具体实现
- (1)准备好需要安装的三方apk应用
- (2)编写一个installapk.sh脚本
- (3)执行PRODUCT_COPY_FILES指令
- (4)在某个init.XXX.rc中执行 installapk.sh脚本,即可安装三方应用
- 3、报错解决
- (1)PRODUCT_COPY_FILES 命令复制文件是apk会报错
- (2)复制的apk文件命名包含特殊字符或者中文或报错
- (3)**SELinux**权限报错
- 三、其他
- 1、Android 系统运行后默认安装三方apk实现总结
- 2、在Android源码中配置第三方应用相对麻烦的大概原因
- 3、如果把三方apk直接push 到 /data/app/XXX/目录 会默认安装吗?
- 4、一个遗留的问题:init脚本未启动成功
一、前言
本文主要介绍 手机的三方应用比如游戏,微博等应用,在源码中如何默认配置到手机中的。
Android手机中的系统应用是无法手动卸载的,但是这些三方应用安装后是可以手动卸载的。
源码编译中配置系统应用是比较简单的,只要在apk文件并且再Android.mk或者Android.bp中进行配置即可。
但是如果要默认配置三方应用确实有点麻烦,网上很多文章讲得都比乱,
大部分只是贴了相关代码,基本没有介绍完整流程和分享解决配置过程还有一些编译报错。
本文是一篇介绍Android 系统源码适配安装可卸载的三方apk知识,比较全面的,基于实际操作的,有很大参考价值的,并且对相关内容进行了介绍的文章。
为啥三方应用配置要比系统应用麻烦那么多?本文最后有简单介绍。
如果把三方apk直接push 到 /data/app/XXX/这个三方应用安装的目录,三方应用会默认安装吗?同样最后介绍。
二、Android 系统运行后默认安装三方apk实现
这是本文的核心内容,如果编译过源码,修改过.mk文件、init.rc文件、shell脚本XXX.sh ,
那么下面的内容是不难的,如果没有接触过也可以看着理解。
1、Android 系统默认安装三方apk实现主要思路
整体思路:
(1)准备好需要安装的三方apk应用
(2)编写一个installapk.sh脚本
(3)在某个.mk文件执行PRODUCT_COPY_FILES指令把apk文件和installapk.sh脚本文件复制到运行环境的某个目录
(4)在某个init.XXX.rc中执行 installapk.sh脚本,即可安装三方应用展开了说一下:
installapk.sh文件的代码主要就是变量文件执行了 pm install XXX.apk,不会写也没关系直接复制过来用就行XX.mk文件执行PRODUCT_COPY_FILES指令的使用修改一下具体源码的目录即可init.XXX.rc是根据自己系统代码的情况,选择一个常用的init.XXX.rc,在里面执行启动installapk.sh脚本即可,启动脚本的代码也是比较简单,只要几行固定的代码,一看就能学会理解上面内容,并且按照顺序一步一步来,最后就能实现系统默认安装三方apk功能。
网上很多文章只是贴了一下代码,未介绍具体思路和先后过程所以会比较乱。
2、Android 系统默认安装三方apk具体实现
(1)准备好需要安装的三方apk应用
比如把所有三方apk,放在源码/vendor/preinstallapk目录。
源码这里的apk目录其实无所谓,只要在.mk文件里面填写正确就可以了。
(2)编写一个installapk.sh脚本
代码如下:
#!/vendor/bin/sh
#给vendor目录读写和remount权限,有些系统不用,可以具体情况编写
/system/bin/mount -o rw,remount /vendor#读取是否设置的prop属性
installprop=`getprop persist.mydebug.preinstall`#定向日志到文件,不然看不到
echo "installapk.sh start " >> /sdcard/Download/installapkLog.txtecho "installapk installprop persist.mydebug.preinstall = $installprop" >> /sdcard/Download/installapkLog.txtif [ "$my_property" = "true" ];thenecho "installapk return!" >> /sdcard/Download/installapkLog.txtreturn
else echo "installapk start" >> /sdcard/Download/installapkLog.txt
fi#遍历vendor/preinstallapk 里面的所以apk
for file in /vendor/preinstallapk/*
do
if [ -f "$file" ]
thenecho "installapk apk = $file" >> /sdcard/Download/installapkLog.txtpm install -r $file
fi
done#最后,复制一份apk到sdcard进行备份,如果项目不需要就不用cpmkdir sdcard/Download/operatormkdir sdcard/Download/operator/appcp /vendor/preinstallapk/* sdcard/Download/operator/app/#设置prop表示,表示已经安装过apk了setprop persist.mydebug.install true# 根据需求决定是否删除三方apkrm -rf /vendor/preinstallapk/*echo "installapk end" >> /sdcard/Download/installapkLog.txt
上面的代码主要逻辑:
1、给vendor 读写和remount权限,有些系统不用有些要,可以具体情况编写
2、获取prop属性,查看是否已经安装过,判断安装过就不再安装
3、未安装的情况,遍历目录所有apk文件进行“pm install -r XXX”安装
4、安装完后复制一个apk到sdcard目录,并且删除vendor目录的三方应用
5、记录prop属性,设置应用已经安装其中一些细节:
全过程使用定向日志输出到本地文件,如果不想被用户看到,可以输出到vendor分区/vendor/preinstallapk/目前是手机运行环境中存在apk的目录,具体体现可以在后面的.mk中体现上面所有的目录都是手机设备真实可以cd到的目录,.sh文件就是安卓设备中可执行的shell脚步获取属性的错误写法:
my_property=$(getprop persist.mydebug.preinstall)
正确写法:
propstring=`getprop persist.mydebug.preinstall`
如果想要脚本简单一些,去掉prop属性的判断,去掉复制文件,去掉定向日志生成。
精简后的 installapk.sh代码如下:
/system/bin/mount -o rw,remount /vendor
for file in /vendor/preinstallapk/*
do
if [ -f "$file" ]
thenpm install -r $file
fi
done
rm -rf /vendor/preinstallapk/*
把写好的 installapk.sh放到源码的 /vendor/scripts/ 目录下,这个目录也是可以更加自己的项目情况修改的。
(3)执行PRODUCT_COPY_FILES指令
找到一个执行 PRODUCT_COPY_FILES 执行的XXX.mk文件,在里面多加下面两行代码。
PRODUCT_COPY_FILES += \$(call find-copy-subdir-files,*,vendor/preinstallapk,$(TARGET_COPY_OUT_VENDOR)/preinstallapk)PRODUCT_COPY_FILES += \$(call find-copy-subdir-files,*,vendor/scripts,$(TARGET_COPY_OUT_VENDOR)/bin)
代码编译运行后,就会在 根目录的 vendor 下面的 preinstallapk 和 bin 文件夹看到 apk文件和 installapk.sh文件。
这里也不一定要copy到vendor 目录,根据项目情况复制到 system 目录也可以的。
(4)在某个init.XXX.rc中执行 installapk.sh脚本,即可安装三方应用
找到一个会执行的 init.XXX.rc 文件,大概加入如下代码:
# init 刚启动的时
on boot# installapk 监听服务,执行sh脚本
service installapk /vendor/bin/installapk.shdisabledoneshotseclabel u:r:shell:s0on property:sys.boot_completed=1start installapk
系统/device/init 目录下 很多init.XXX.rc 都可以正常运行,如果不知道找哪个,直接加在 init.rc 文件也可以。
也可以在Java代码中启动设置prop属性,也是可以启动脚本的:
SystemProperties.set("ctl.start","installapk");
可以在xxx.sh脚本中添加属性判断或者设置,在代码中判断属性后执行脚本也是ok 的。
3、报错解决
(1)PRODUCT_COPY_FILES 命令复制文件是apk会报错
这个是编译报错,也是必须要要解决的报错,报错日志:
FAILED:
In file included from build/make/core/main.mk:1448:
build/make/core/Makefile:72: error: Prebuilt apk found in PRODUCT_COPY_FILES: device/preinstallapk/SystemAppDemo.apk:vendor/preinstallapk/SystemAppDemo.apk, use BUILD_PREBUILT instead!.
日志提示,PRODUCT_COPY_FILES 复制的文件是apk,请用 BUILD_PREBUILT指令进行安装;
BUILD_PREBUILT 指令就是Android.mk 里面的编译类型,据我所了解,Android.mk和Android.bp编译的apk都是不可以卸载的apk!百度搜索也没有相关介绍。
所以还是要解决这个编译问题。其实解决也不难,去除它的检测机制的几行代码就行,解决方法:
注释掉build/core/Makefile文件中检测apk代码 ,#号就是注释
#define check-product-copy-files
#$(if $(filter-out $(TARGET_COPY_OUT_SYSTEM_OTHER)/%,$(2)), \
# $(if $(filter %.apk, $(2)),$(error \
# Prebuilt apk found in PRODUCT_COPY_FILES: $(1), use BUILD_PREBUILT instead!))) \...//中间这些代码可以不管#endef //最后记得注释这行,不然代码编译不通过!
(2)复制的apk文件命名包含特殊字符或者中文或报错
File "/build/tools/releasetools/edify_generator.py", line 213, in SetPermissionsself.script.append('set_perm(%d, %d, 0%o, "%s");' % (uid, gid, mode, fn))
TypeError: %d format: a number is required, not NoneType
可能是你的apk名字中包含非法字符,如中文,“-”,等.。
apk名称包含下划线是不会报错的。
(3)SELinux权限报错
自己测试的系统是配置关闭了selinux 的,所以没有selinux问题,即使有提示错误也是不用去管的。
别人写三方apk配置流程(包含了selinux修改):
https://blog.csdn.net/vviccc/article/details/114920873
selinux修改每个系统方案的代码路径都会有差异,根据自己的情况即可。
查看SELinux权限 情况:
console:/ # getenforce
Permissive
console:/ # 三种模式的说明:
enforcing:强制模式,SELinux 正在运行中,已经在限制 domain/type。permissive:宽容模式:SELinux 正在运行中,但仅发出警告信息,并不会实际限制 domain/type 的存取
(permissive模式可以用在测试环境中供调试规则时使用)。disabled:关闭,SELinux 不再运行。
selinux 设置:
https://blog.csdn.net/u010404909/article/details/125411501
可以手动关闭 SELinux ,确实是不是SELinux权限导致的异常。
Android权限 - avc权限问题修改:
https://blog.csdn.net/hanhan1016/article/details/105929535/
三、其他
1、Android 系统运行后默认安装三方apk实现总结
(1)准备好apk,放到某个源码目录
(2)准备好installapk.sh,放到某个源码目录
(3)在某个mk文件,把apk和sh脚本文件复制到运行环境的某个目录
(4)修改某个init.XXX.rc,编写service,监听启动sh脚本
如果是有root和remount权限的系统,可以不用编译源码直接测试效果,具体实现:
(1)把apk 和 xxx.sh放到某个目录
(2)在init.rc 中添加 service 的相关代码,并且设置启动xxx.sh的启动条件
(3)重启后即可自动安装三方应用,或者sh xxxx/xxx.sh 校验sh脚本是否正常安装三方应用,或者设置prop属性启动init中的service
总统代码量其实就是写一个sh脚本和在init.rc中添加一些启动sh的代码。
2、在Android源码中配置第三方应用相对麻烦的大概原因
在Android源码中配置第三方应用相对系统应用麻烦的原因主要有以下几点:
1. 权限限制:Android系统对于系统应用和第三方应用有不同的权限限制。
系统应用通常具有更高的权限和特权,可以访问更多的系统资源和功能。
而第三方应用受到更多的限制,需要经过严格的权限管理和安全审查。2. 系统签名:系统应用通常需要使用特定的系统签名来进行身份验证。
这些签名是由设备制造商或系统开发者提供的,用于确保系统应用的安全性和可信度。
第三方应用无法使用系统签名,因此在源码中配置时需要进行额外的验证和授权。3. 安全性考虑:Android系统为了保护用户和系统的安全,对第三方应用的操作进行了限制。
源码中的配置文件和代码可能需要经过安全审查和验证,以确保不会产生潜在的安全风险。4. 多样性和兼容性:Android系统在不同的设备和版本之间存在着差异。
不同设备的硬件和功能可能有所不同,因此需要根据具体设备进行适配和配置。
而第三方应用在不同设备上的兼容性也需要额外的处理和测试。
综上所述,由于安全性、权限限制、系统签名等因素的考虑,
Android源码中配置第三方应用相对于系统应用来说确实更加麻烦和复杂。
这也体现了Android系统对于用户数据和系统安全的重视。
3、如果把三方apk直接push 到 /data/app/XXX/目录 会默认安装吗?
答案是:不会,下面是一些分析。
在Android设备上,三方APK手动安装后的目录是/data/app/XXX包名/ 。
在这个目录下,每个应用程序都有一个以包名命名的子目录,其中包含了安装后的APK文件和其他应用程序数据。
但是需要注意的是,/data目录是系统保护的目录,普通用户无法直接访问。
只有具有root权限的用户才能查看和修改这个目录下的文件。
测试直接把apk文件放到,data/app/XXX/目录,Android系统重启会把XXX目录自动删除
为啥?具体原因是:
在Android系统中,将APK文件推送到`/data/app`目录是不会自动安装应用程序的。
该目录是用于存储已安装的应用程序的数据和缓存文件,而不是用于直接安装应用程序。当你将APK文件推送到`/data/app`目录时,系统不会将其自动解析和安装为应用程序。
因此,当你重新启动设备时,系统会清除`/data/app`目录中的数据和文件,
这就是为什么推送到该目录的APK文件在重启后会消失的原因。
4、一个遗留的问题:init脚本未启动成功
两套代码都是Android13 的代码,具体修改也是一样的,一份ok,一份不ok。
一份源码环境中 init.XXX.rc 的 sh 脚本启动成功;
另一份其他方案的源码环境中 init.XXX.rc 的 sh 脚本未启动成功,通过代码或者设置属性也是无法启动sh脚本。
01-31 18:36:49.251 1 1 I init : starting service 'installapk'...
01-31 18:36:52.919 1 1 I init : Service 'installapk' (pid 3129) exited with status 0 oneshot service took 3.662000 seconds in background
这里看到init 的 Service exited with status 0,正常情况都是 Service XXX exited with status 1 的。
尝试直接sh XXX/XXX.sh 脚本都是可以正常执行安装应用的。
所以出现问题的地方可能是init.rc或者具体实现ini.rc的c代码相关。
这个问题看了几天暂时未看出原因,待年后继续分析。
已经放假,祝所有人新年快乐。
相关文章:
Android13 系统源码适配安装可卸载的三方apk应用
Android13 系统源码适配安装可卸载的三方apk应用 文章目录 Android13 系统源码适配安装可卸载的三方apk应用一、前言二、Android 系统运行后默认安装三方apk实现1、Android 系统默认安装三方apk实现主要思路2、Android 系统默认安装三方apk具体实现(1)准…...
flutter使用qr_code_scanner扫描二维码
qr_code_scanner仓库地址:qr_code_scanner | Flutter Package 需要添加android和ios的相机权限和本地相册权限: android中添加权限: 在android\app\build.gradle中修改:minSdkVersion 20 并且在android/app/src/main/AndroidManifest.xml中…...
黑马Java——集合进阶(List、Set、泛型、树)
一、集合的体系结构 1、单列集合(Collection) 二、Collection集合 1、Collection常见方法 1.1代码实现: import java.util.ArrayList; import java.util.Collection;public class A01_CollectionDemo1 {public static void main(String[] a…...
TS项目实战二:网页计算器
使用ts实现网页计算器工具,实现计算器相关功能,使用tsify进行项目编译,引入Browserify实现web界面中直接使用模块加载服务。 源码下载:点击下载 讲解视频 TS实战项目四:计算器项目创建 TS实战项目五:B…...
MySQL的ACID、死锁、MVCC问题
1 ACID ACID代表原子性(atomicity)、一致性(consistency)、隔离性(isolation)和持久性(durability)。一个确保数据安全的事务处理系统,必须满足这些密切相关的标准。 原…...
Docker 可视化工具
1、Portainer 概念介绍 Portainer是一款轻量级的应用,它提供了图形化界面,用于方便地管理Docker环境,包括单机环境和集群环境。 Portainer分为开源社区版(CE版)和商用版(BE版/EE版)。 Porta…...
【C++】友元:友元函数与友元类
一、友元 友元(friend)是C中的一种特殊关系,用于在类之间共享访问权限。通过将一个函数或类声明为另一个类的友元,我们可以允许友元访问声明类的非公有成员。 二、友元函数 问题:现在尝试去重载operator<<&am…...
linux之wsl2安装远程桌面
0. 安装后的效果 1. wsl中打开terminal并安装库 sudo apt-get purge xrdp sudo apt install -y xrdp sudo apt install -y xfce4 sudo apt install -y xfce4-goodies 2.优化显示 sudo sed -i s/max_bpp32/#max_bpp32\nmax_bpp128/g /etc/xrdp/xrdp.ini sudo sed -i s/xserverbp…...
如何以管理员身份删除node_modules文件
今天拉项目,然后需要安装依赖,但是一直报错,如下: 去搜这个问题会让把node_modules文件先删掉 再去安装依赖。我在删除的过程中会说请以管理员身份来删除。 那么windows如何以管理员身份删除node_modules文件呢? wi…...
【Linux】环境基础开发工具的使用之gdb详解(三)
前言:上一篇文章中我们讲解了Linux下的gcc与g的使用,今天我们将进一步的学习gdb与makefile来帮我们更好的理解与使用基础开发工具。 💖 博主CSDN主页:卫卫卫的个人主页 💞 👉 专栏分类:Linux的深度刨析 👈 …...
SpringBoot源码解读与原理分析(二十四)IOC容器的刷新(五)
文章目录 7.11 初始化所有剩下的单实例bean对象7.11.1 beanFactory.preInstantiateSingletons7.11.2 getBean7.11.2.1 别名的解析处理7.11.2.2 判断是否已注册过7.11.2.3 创建前的检查7.11.2.4 标记准备创建的bean对象7.11.2.5 合并BeanDefinition7.11.2.6 bean对象的创建7.11.…...
最大子数组和
一、题目 给你一个整数数组nums,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。子数组 是数组中的一个连续部分。 示例 1: 输入:nums [-2,1,-3,4,-1,2,1,-5,4] 输出&#…...
Node.js版本管理工具之_Volta
Node.js包管理工具之_Volta 文章目录 Node.js包管理工具之_Volta1. 官网1. 官网介绍2. 特点1. 快( Fast)2. 可靠(Reliable)3. 普遍( Universal) 2. 下载与安装1. 下载2. 安装3. 查看 3. 使用1. 查看已安装的工具包2. 安装指定的node版本3.切换项目中使用的版本 1. 官网 1. 官网…...
Redis 命令大全
文章目录 启动与连接Key(键)相关命令String(字符串)Hash(哈希)List(列表)Set(集合)Sorted Set(有序集合)其他常见命令HyperLogLog&…...
再这么烂下去,离糊就不远了。别让才华被埋没。
♥ 为方便您进行讨论和分享,同时也为能带给您不一样的参与感。请您在阅读本文之前,点击一下“关注”,非常感谢您的支持! 文 |猴哥聊娱乐 编 辑|徐 婷 校 对|侯欢庭 近日,胡歌凭借电视剧《繁花》荣登《环球银幕》二月…...
Unity BuffSystem buff系统
Unity BuffSystem buff系统 一、介绍二、buff系统架构三、架构讲解四、框架使用buff数据Json数据以及工具ShowTypeBuffTypeMountTypeBuffOverlapBuffShutDownTypeBuffCalculateType时间和层数这里也不过多说明了如何给生物添加buff 五、总结 一、介绍 现在基本做游戏都会需要些…...
Android rom定制 修改system分区的容量大小
1、写在前面 系统ROM定制化,预置app太多,会导致系统rom很大,原生系统system分区已经不够用了,要加大系统systemui分区 2.修改system分区的容量大小的核心类 device/mediatekprojects/$project/BoardConfig.mk build/make/core/Makefile3、修改system 分区的容量大小的核…...
速盾:服务器接入免备案CDN节点的好处有哪些
本文将探讨服务器接入免备案CDN节点的好处,包括提高网站的访问速度、增加网站的稳定性和可靠性、降低带宽成本等方面的优势。同时,还将提供一些相关问题的解答,帮助读者更好地了解这一技术。 随着互联网的迅猛发展,网站的访问速度…...
Redisson看门狗机制
一、背景 网上redis分布式锁的工具方法,大都满足互斥、防止死锁的特性,有些工具方法会满足可重入特性。如果只满足上述3种特性会有哪些隐患呢?redis分布式锁无法自动续期,比如,一个锁设置了1分钟超时释放,…...
【Java数据结构】双向 不带头 非循环 链表实现(模拟实现LinkedList类)
LinkedList底层实际上是双向、不带头结点、非循环的链表 链表的分类有八种,常用的有两种:一是单向、不带头结点、非循环的(基本上网上的题型都是这种);二是双向、不带头结点、非循环(LinkedList的底层实现…...
国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...
push [特殊字符] present
push 🆚 present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中,push 和 present 是两种不同的视图控制器切换方式,它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...
深入理解Optional:处理空指针异常
1. 使用Optional处理可能为空的集合 在Java开发中,集合判空是一个常见但容易出错的场景。传统方式虽然可行,但存在一些潜在问题: // 传统判空方式 if (!CollectionUtils.isEmpty(userInfoList)) {for (UserInfo userInfo : userInfoList) {…...
Kafka主题运维全指南:从基础配置到故障处理
#作者:张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1:主题删除失败。常见错误2:__consumer_offsets占用太多的磁盘。 主题日常管理 …...
DAY 26 函数专题1
函数定义与参数知识点回顾:1. 函数的定义2. 变量作用域:局部变量和全局变量3. 函数的参数类型:位置参数、默认参数、不定参数4. 传递参数的手段:关键词参数5 题目1:计算圆的面积 任务: 编写一…...
鸿蒙HarmonyOS 5军旗小游戏实现指南
1. 项目概述 本军旗小游戏基于鸿蒙HarmonyOS 5开发,采用DevEco Studio实现,包含完整的游戏逻辑和UI界面。 2. 项目结构 /src/main/java/com/example/militarychess/├── MainAbilitySlice.java // 主界面├── GameView.java // 游戏核…...
