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代码相关。
这个问题看了几天暂时未看出原因,待年后继续分析。

已经放假,祝所有人新年快乐。

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

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

相关文章

chartGPT网站

在人工智能日益发展的今天,大语言模型成为了我们生活与工作中不可或缺的一部分。它们能够帮助我们处理文本、回答问题、生成创意内容,甚至协助编程和数据分析。然而,由于网络环境的复杂性,找到一个既稳定又快速的大语言模型网站并…

C++ 中template 模版

C模板&#xff08;Templates&#xff09;主要是编写泛型代码&#xff0c;在编译时为不同数据类型生成相应的函数或类实例&#xff0c;主要有函数模板&#xff0c;类模板 函数模板 #include <iostream> #include <string>using namespace std;template<typenam…

OLAP技术的发展及趋势简述

这里写自定义目录标题 历史发展基于电子表格的数据分析基于传统数据库的数据分析基于大数据的数据分析 当下的现状OLAP技术的分类MOLAPROLAPHOLAP 主流的OLAP引擎新技术的普及内存向量计算列式数据存储及交换增量查询多源融合计算下推物化视图 发展趋势智能化分析多源融合和自动…

C Primer Plus(第六版)15.9 编程练习 第3题

#include <stdio.h> void getbit(int num); int main() { getbit(127); return 0; } void getbit(int num) { int result; int sum0; int mask1; result num; while(result!0) { if((result & mask) 1) sum; result >> 1; } printf("%d打开的位有%d个…

【学习笔记】树上差分总结(点差分/边差分)

一.树上差分的基本概念 1.树上差分的定义 树上差分&#xff0c;顾名思义&#xff0c;意思就是在树上做差分。 至于什么是差分呢&#xff1f;如果不会的同学&#xff0c;可以先看看我的这篇博客:一维,二维差分の详解&#xff08;简单易懂&#xff09;_一维差分-CSDN博客 2.树…

智能小程序框架——模块化语法参考(ESModule 语法、CommonJS 语法)

小程序的逻辑代码使用 JavaScript 语法进行编写。可以将一些公共的代码抽离成为一个单独的 js 文件&#xff0c;作为一个模块&#xff0c;以实现逻辑共享复用。主要有 ESModule 和 CommonJS 两种形式。一个项目内应保持使用一种语法形式&#xff0c;否则可能出现导入异常的情况…

SpringBoot中使用Spring自带线程池ThreadPoolTaskExecutor与Java8CompletableFuture实现异步任务示例

场景 关于线程池的使用&#xff1a; Java中ExecutorService线程池的使用(Runnable和Callable多线程实现)&#xff1a; Java中ExecutorService线程池的使用(Runnable和Callable多线程实现)_executorservice executorservice executors.newfix-CSDN博客 Java中创建线程的方式…

springboot(ssm考试信息报名系统 在线考试报名系统Java系统

springboot(ssm考试信息报名系统 在线考试报名系统Java系统 开发语言&#xff1a;Java 框架&#xff1a;springboot&#xff08;可改ssm&#xff09; vue JDK版本&#xff1a;JDK1.8&#xff08;或11&#xff09; 服务器&#xff1a;tomcat 数据库&#xff1a;mysql 5.7&a…

React+echarts实现排名+自动滚动+X轴自定义titleTop

1、效果 2、环境准备 1、react18 2、antd 4 3、代码实现 原理&#xff1a;自动滚动通过创建定时器动态更新echar的dataZoom属性startValue、endValue&#xff0c;自定义tooltip通过监听echar的鼠标移入移出事件&#xff0c;判断tooltTip元素的显隐以及位置。 /*** 收集完成…

【Java EE】----Spring框架创建和使用

1.Spring框架创建 创建一个maven项目 添加Spring框架支持 <dependencies> 上下文<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.3.RELEASE</version></depende…

【网站项目】038汽车养护管理系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

java -jar启动SpringBoot项目时配置文件加载位置与优先级

服务部署启动时,我们经常需要指定配置文件启动. 一般有四种,优先级如下 spring.config.location > spring.profiles.active > spring.config.additional-location > 默认的 application.yml 1.spring.config.location 外部配置文件优先级最高 一般配置文件在服务…

PS之外的平面设计利器:7款高效软件帮你轻松搞定

平面图设计的痕迹体现在日常生活的方方面面&#xff0c;如路边传单、杂志、产品包装袋或手机开屏海报等&#xff0c;平面设计软件层出不穷。Photoshop是大多数平面图设计初学者的入门软件&#xff0c;但随着设计师需求的不断提高&#xff0c;平面图设计软件Photoshop逐渐显示出…

SpringBoot:自动配置报告

自动配置报告demo&#xff1a;点击查看 LearnSpringBoot03AutoConfig 点击查看更多的SpringBoot教程 一、application.properties代码 #开启springboot debug模式 #自动配置报告 #Positive matches: 自动配置类启用了&#xff08;自动配置类匹配上了&#xff09;&#xff0c…

【动态规划】【图论】【C++算法】1928规定时间内到达终点的最小花费

作者推荐 【动态规划】【状态压缩】【2次选择】【广度搜索】1494. 并行课程 II 本文涉及知识点 动态规划汇总 LeetCode1928. 规定时间内到达终点的最小花费 一个国家有 n 个城市&#xff0c;城市编号为 0 到 n - 1 &#xff0c;题目保证 所有城市 都由双向道路 连接在一起…

【python】绘制春节烟花

一、Pygame库春节烟花示例 下面是一个使用Pygame实现的简单春节烟花效果的示例代码。请注意&#xff0c;运行下面的代码之前&#xff0c;请确保计算机上已经安装了Pygame库。 import pygame import random import math from pygame.locals import *# 初始化pygame pygame.ini…

Spring Boot配置文件优先级

1、bat文件启动java程序 java -Dmmmqqq -Dfile.encodingUTF-8 -jar ruoyi-admin.jar --mmmiii --llllll 2、配置类型 程序参数Program arguments : --mmmiii 单个属性值&#xff0c;可以从String[] args读取到&#xff0c;放在jar包命令后面 VM参数VM options :一般以-D …

如何让 Pages 文字分为两栏或更多栏?

通常一份文件都是由上往下仅有「一栏」而已&#xff0c;但在某些情况的排版&#xff0c;我们需要两栏甚至三栏的设计&#xff0c;在Pages 要如何做到呢&#xff1f;来看看吧。 将 Pages 文件改为双栏式设计 点一下「格式」>「布局」&#xff0c;就可以看到预设的「直栏」数…

C++:哈希表的哈希桶(模拟实现)

在这里不赘述哈希表的相关性质有兴趣的参考线性探测&#xff0c;这里直接贴代码 template<class T>struct HashNode{T _data;HashNode<T>* _next;HashNode(const T& data):_data(data), _next(nullptr){}};template<class K, class T, class KOFV>class …

SpringMVC-请求

一、引子 我们在上一篇SpringMVC-响应中提到了如何给客户端返回响应&#xff0c;那么本节来介绍一下如何承接客户端的响应。 二、接收参数 &#xff08;1&#xff09;使用RequestParam注解&#xff1a; RequestMapping(value "/example", method RequestMethod…