当前位置: 首页 > news >正文

Android 源码集成可卸载 APP

android系统包含三类APP: 1、可自由卸载APP安装在 /data/app目录下。 2、系统APP放在 /system/app目录。 3、特权APP放在 /system/priv-app目录。

系统编译后,打包前, /data分区不起作用,因此系统打包前,可以先将APP全部拷贝到 /system分区的 /system/usr/app目录下。

1、拷贝APP暂存到 /system/usr/app 目录

 在 /build/target/product/base_product.mk中添加如下命令, 会将 /apps/apps目录下的所有文件拷贝到 /system/usr/app ,将 shell脚本拷贝到 /system/bin目录

# 拷贝APP
PRODUCT_COPY_FILES += $(call find-copy-subdir-files,*,/data1/rom/android/lineageOS2/apps/apps,/system/usr/app)
# 拷贝shell
PRODUCT_COPY_FILES += $(call find-copy-subdir-files,*,/data1/rom/android/lineageOS2/apps/shell,/system/bin)

2、绕过拷贝 .apk文件时校验

 注释 /build/core/Makefile 如下 apk拷贝报错代码

define check-product-copy-files
$(if $(filter %.apk, $(1)),$(error \Prebuilt apk found in PRODUCT_COPY_FILES: $(1), use BUILD_PREBUILT instead!))
endef

3、系统启动执行init.rc脚本时,拷贝APP到 /data分区

在 init.rc文件中定义如下service , 并在 on boot 事件中 执行 preinstall

service preinstall /system/bin/preinstall.shclass mainuser rootgroup rootoneshoton bootxxxxxxxxxx.....start preinstall

4、shell 脚本文件如下 

#!/system/bin/shCUSTOMIZED_APK=/system/usr/app
DATA_APK=/data/appecho "CUSTOMIZED_APK=${CUSTOMIZED_APK}"
#获取是否已经预安装过标记位
PREINSTALL_RESULT=`getprop persist.sys.preinstall.value`
echo "PREINSTALL_RESULT=${PREINSTALL_RESULT}"
apk_files=""
#判断标记位是否为空,为空则没有预装过。然后将所有apk均copy到data/app下面。if [ -z "${PREINSTALL_RESULT}" ]; thencd ${CUSTOMIZED_APK}apk_files=$(ls *.apk )echo "apks files = ${apk_files}"for apkfile in $apk_filesdoecho " apkfiles = ${apkfile} "cp -vf ${CUSTOMIZED_APK}/${apkfile} ${DATA_APK}/${apkfile}echo "start copy "chmod 777 ${DATA_APK}/${apkfile}done#设置标记位
setprop persist.sys.preinstall.value 1# 拷贝 设备改机文件
cp /system/etc/device.json /data/system/device.json
chmod 666 /data/system/device.json
# 拷贝adb公钥
cp /system/etc/adb_keys /data/system/adb_keys
chown -R shell:shell /data/system/adb_keys
chmod 666 /data/system/adb_keyscd ../..fi

5、添加selinux权限

file_contexts文件: system/sepolicy/private/file_contexts 添加下面一行:

/system/bin/preinstall.sh  u:object_r:preinstall_exec:s0

同目录新建文件 preinstall.te 内容如下:

type preinstall, domain;
type preinstall_exec, exec_type, file_type;init_daemon_domain(preinstall)
#全部默认允许
permissive preinstall;

修改 init.te 允许读取并执行 preinstall:

#默认全部允许
allow init preinstall_exec:file {read open getattr execute};

android 11 系统 在 system/sepolicy/prebuilts/api/30.0/private 目录同步修改

TODO

最后一次拉取的android11源码 将 apk拷贝到 /data/app目录后开机没有扫描安装,原因待分析

FIXED : 

在 PackageManagerService. assertPackageIsValid 方法中 ,如下代码段:

// If we're only installing presumed-existing packages, require that the
// scanned APK is both already known and at the path previously established
// for it.  Previously unknown packages we pick up normally, but if we have an
// a priori expectation about this package's install presence, enforce it.
// With a singular exception for new system packages. When an OTA contains
// a new system package, we allow the codepath to change from a system location
// to the user-installed location. If we don't allow this change, any newer,
// user-installed version of the application will be ignored.
if ((scanFlags & SCAN_REQUIRE_KNOWN) != 0) {if (mExpectingBetter.containsKey(pkg.getPackageName())) {logCriticalInfo(Log.WARN,"Relax SCAN_REQUIRE_KNOWN requirement for package "+ pkg.getPackageName());} else {PackageSetting known = mSettings.getPackageLPr(pkg.getPackageName());if (known != null) {if (DEBUG_PACKAGE_SCANNING) {Log.d(TAG, "Examining " + pkg.getCodePath()+ " and requiring known paths " + known.codePathString+ " & " + known.resourcePathString);}if (!pkg.getCodePath().equals(known.codePathString)|| !pkg.getCodePath().equals(known.resourcePathString)) {throw new PackageManagerException(INSTALL_FAILED_PACKAGE_CHANGED,"Application package " + pkg.getPackageName()+ " found at " + pkg.getCodePath()+ " but expected at " + known.codePathString+ "; ignoring.");}} else {// throw new PackageManagerException(INSTALL_FAILED_INVALID_INSTALL_LOCATION,//         "Application package " + pkg.getPackageName()//         + " not found; ignoring.");}}
}

注释掉  INSTALL_FAILED_INVALID_INSTALL_LOCATION 异常。

同时,修改selinux权限: untrusted_app_all 增加 execute 权限:

#允许app读取/data/system目录文件 允许app 执行 data/app-libm目录下的可执行文件
allow untrusted_app_all system_data_file:file { open read execute};

相关文章:

Android 源码集成可卸载 APP

android系统包含三类APP: 1、可自由卸载APP安装在 /data/app目录下。 2、系统APP放在 /system/app目录。 3、特权APP放在 /system/priv-app目录。 系统编译后,打包前, /data分区不起作用,因此系统打包前,可以先将APP全部拷贝到 /…...

cJSON-轻量级解析模块、字符串的神——编织STM32C8T6与阿里云信息传递的纽带

编写方向:本人就不泛泛的编写一篇什么一文学会cJSON了,没什么突出点,也就我水水字数,你们看来看去也不懂,本人是从上阿里云传信息接触的cJSON的,我就此写一篇针对性的文章,希望对大家有用&#…...

【Git】Clone

当git clone失败时,出现 RPC failed; curl 92 HTTP/2 stream 0 was not closed cleanly: CANCEL (err 8) 错误,可能由于网络连接不稳定或仓库太大导致的。 可以尝试以下几种方法来解决这个问题: 增加 Git 的缓冲区大小: git confi…...

web开发 之 HTML、CSS、JavaScript、以及JavaScript的高级框架Vue(学习版2)

一、前言 接下来就是来解决这些问题 二、 Ajax 1.ajax javscript是网页三剑客之一&#xff0c;空用来控制网页的行为的 xml是一种标记语言&#xff0c;是用来存储数据的 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-…...

【课程学习】信号检测与估计II

b站 文章目录 1-概述 1-概述 线性、正交、平稳、高斯 研究线性模型&#xff0c;采用正交化方法&#xff0c;假设信号平稳&#xff0c;考虑信号的统计特性是高斯的。 本学期考虑&#xff0c;非线性、非正交、非平稳、非高斯。 阵列处理 1980-1990 MUSIC 稀疏性 2006-2012 LASS 时…...

【深度学习|PyTorch】基于 PyTorch 搭建 U-Net 深度学习语义分割模型——附代码及其解释!

【深度学习|PyTorch】基于 PyTorch 搭建 U-Net 深度学习语义分割模型——附代码及其解释&#xff01; 【深度学习|PyTorch】基于 PyTorch 搭建 U-Net 深度学习语义分割模型——附代码及其解释&#xff01; 论文地址&#xff1a; https://arxiv.org/abs/1505.04597 代码地址&a…...

DPDK基础入门(十):虚拟化

I/O虚拟化 全虚拟化&#xff1a;宿主机截获客户机对I/O设备的访问请求&#xff0c;然后通过软件模拟真实的硬件。这种方式对客户机而言非常透明&#xff0c;无需考虑底层硬件的情况&#xff0c;不需要修改操作系统。 半虚拟化&#xff1a;通过前端驱动/后端驱动模拟实现I/O虚拟…...

OpenCV_图像旋转超详细讲解

图像转置 transpose(src, dst); transpose()可以实现像素下标的x和y轴坐标进行对调&#xff1a;dst(i,j)src(j,i)&#xff0c;接口形式 transpose(InputArray src, // 输入图像OutputArray dst, // 输出 ) 图像翻转 flip(src, dst, 1); flip()函数可以实现对图像的水平翻转…...

关于 OceanBase 4.x 中被truncate的 table 不再支持进回收站的原因

近期&#xff0c;OceanBase的问答社区中收到了不少用户的询问&#xff0c;关于OceanBase 3.x版本支持被truncate的table进入回收站的功能&#xff0c;为何在升级到4.x版本后不再支持了&#xff1f;为了解答大家的疑惑&#xff0c;我们将通过这篇文章来浅析 OceanBase在4.x版本中…...

Numpy索引详解(数值索引,列表索引,布尔索引)

数值索引 数值索引类似列表索引操作使用[]&#xff0c;参数为下标&#xff0c;[0,len-1),高维数组的索引使用多个[]连用分别代表一维索引&#xff0c;二维索引... import numpy as np import torchnp.random.seed(1) data1 np.arange(5) data2 np.arange(15).reshape(3,5) …...

大数据新视界 --大数据大厂之MongoDB与大数据:灵活文档数据库的应用场景

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…...

三年 Sparker 都不一定知道的算子内幕

一、如何在 mapPartitions 中释放资源 mapPartitions是一种对每个分区进行操作的转换操作&#xff0c;于常用的map操作类似&#xff0c;但它处理的是整个分区而不是单个元素。mapPartitions的应用场景适合处理需要在每个分区内批量处理数据的场景&#xff0c;通常用于优化性能…...

PG表空间

目录标题 PG表空间PostgreSQL表空间的最佳实践是什么&#xff1f;如何在PostgreSQL中创建和管理自定义表空间&#xff1f;PostgreSQL表空间对数据库性能的具体影响有哪些&#xff1f;在PostgreSQL中&#xff0c;如何迁移数据到不同的表空间以优化存储布局&#xff1f;PostgreSQ…...

谷粒商城のElasticsearch

文章目录 前言一、前置知识1、Elasticsearch 的结构2、倒排索引 (Inverted Index)2.1、 索引阶段2.2、查询阶段 二、环境准备1、安装Es2、安装Kibana3、安装 ik 分词器 三、项目整合1、引入依赖2、整合业务2.1、创建索引、文档、构建查询语句2.2、整合业务代码 后记 前言 本篇介…...

排队免单模式小程序开发

开发一个排队免单模式的小程序涉及多个方面&#xff0c;包括需求分析、界面设计、后端开发、数据库设计以及测试上线等。下面我将详细介绍每个步骤的概要&#xff1a; 1.需求分析 明确目标&#xff1a;首先确定小程序的核心功能&#xff0c;即排队免单模式的具体实现方式。例如…...

从OracleCloudWorld和财报看Oracle的转变

2024年9月9-12日Oracle Cloud World在美国拉斯维加斯盛大开幕 押注AI和云 Oracle 创始人Larry Ellison做了对Oracle战略和未来愿景的主旨演讲&#xff0c;在演讲中Larry将AI技术和云战略推到了前所未有的高度&#xff0c;从新的Oracle 23c改名到Oracle23ai&#xff0c;到Oracl…...

搭建 PHP

快速搭建 PHP 环境指南 PHP 是一种广泛用于 Web 开发的后端脚本语言&#xff0c;因其灵活性和易用性而受到开发者的青睐。无论是开发个人项目还是企业级应用&#xff0c;PHP 环境的搭建都是一个不可忽视的基础步骤。本指南将带您快速学习如何在不同平台上搭建 PHP 环境&#x…...

kubernetes技术详解,带你深入了解k8s

目录 一、Kubernetes简介 1.1 容器编排应用 1.2 Kubernetes简介 1.3 k8s的设计架构 1.3.1 k8s各个组件的用途 1.3.2 k8s各组件之间的调用关系 1.3.3 k8s的常用名词概念 1.3.4 k8s的分层结构 二、k8s集群环境搭建 2.1 k8s中容器的管理方式 2.2 k8s环境部署 2.2.1 禁用…...

Gateway学习笔记

目录 介绍&#xff1a; 核心概念 依赖 路由 断言 基本的断言工厂 自定义断言 过滤器 路由过滤器 过滤器工厂 自定义路由过滤器 全局过滤器 其他 过滤器执行顺序 前置后置&#xff08;&#xff1f;&#xff09; 跨域问题 yaml 解决 配置类解决 介绍&#x…...

创造增强叙事的互动:Allison Crank的沉浸式体验设计理念

在沉浸式技术日新月异的今天,如何通过用户交互增强叙事,而非分散注意力,成为了设计师们共同面临的挑战。作为用户体验设计师和研究员,Allison Crank以其独特的视角和丰富的经验,为我们揭示了这一领域的核心原则与实践方法。 叙事与互动的和谐共生 Allison Crank强调,互…...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 &#xff08;1&#xff09;连接查询&#xff08;JOIN&#xff09; 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

基于服务器使用 apt 安装、配置 Nginx

&#x1f9fe; 一、查看可安装的 Nginx 版本 首先&#xff0c;你可以运行以下命令查看可用版本&#xff1a; apt-cache madison nginx-core输出示例&#xff1a; nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

面向无人机海岸带生态系统监测的语义分割基准数据集

描述&#xff1a;海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而&#xff0c;目前该领域仍面临一个挑战&#xff0c;即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...

uniapp 开发ios, xcode 提交app store connect 和 testflight内测

uniapp 中配置 配置manifest 文档&#xff1a;manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号&#xff1a;4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)

前言&#xff1a; 双亲委派机制对于面试这块来说非常重要&#xff0c;在实际开发中也是经常遇见需要打破双亲委派的需求&#xff0c;今天我们一起来探索一下什么是双亲委派机制&#xff0c;在此之前我们先介绍一下类的加载器。 目录 ​编辑 前言&#xff1a; 类加载器 1. …...

给网站添加live2d看板娘

给网站添加live2d看板娘 参考文献&#xff1a; stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下&#xff0c;文章也主…...