Android 应用添加系统签名权限介绍

一、前言


Android 应用添加系统签名就能获取到系统权限调用一些系统接口,

添加系统签名的方式主要包括:

在Android Studio中配置签名文件生成apk 和 在源码目录编译添加系统签名生成apk。

本文介绍的都是一些基础的签名知识,后续延伸介绍相关权限内容。有兴趣的可以进行了解。

二、Android 应用添加系统签名权限的几种方式介绍

1、在Android Studio添加系统签名文件

对应需要签名的module(默认是app)的build.gradle中添加如下代码:

android {compileSdkVersion 30buildToolsVersion "30.0.0"compileOptions {sourceCompatibility JavaVersion.VERSION_1_8targetCompatibility JavaVersion.VERSION_1_8}
。。。//证书信息在这里配置signingConfigs {main {storeFile file("./platform.jks") //签名文件路径,根目录storePassword "skg202302"keyAlias "skg"keyPassword "skg202302"}}buildTypes {release {minifyEnabled falsesigningConfig signingConfigs.main //添加这一行proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'}debug {minifyEnabled falsesigningConfig signingConfigs.main //添加这一行proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'}}}

只是添加了系统签名是不行的,还需要在AndroidManifest.xml中声明系统权限

AndroidManifest.xml 配置uid系统权限:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"coreApp="true"package="com.xxx.xxx"android:sharedUserId="android.uid.system">
2、源码编译apk添加系统签名

如果apk没有签名文件和为添加签名信息,那么添加uid.system后,该应用是无法安装到对应系统上的;

如果要安装可以在源码里面编译,生成的apk就会加入签名的信息的。

Android.mk
# 编译的目录,默认写法
include $(CLEAR_VARS)# 设置模块名
LOCAL_MODULE := mymodule# 设置预构建文件的源路径和目标路径
LOCAL_SRC_FILES := path/file.apk# 设置系统权限和目录
LOCAL_CERTIFICATE := platform
LOCAL_PRIVATE_PLATFORM_APIS := true
# 设置是否编译在 priv-app,如果没有指定目录默认为 system/priv-app
LOCAL_PRIVILEGED_MODULE := true include $(BUILD_PREBUILT)

Android.bp

android_app_import {name: "FileManager",apk: "FileManager.apk",//生成到priv-app目录下privileged: true,//使用系统签名certificate: "platform",
}
3、源码编译app代码添加系统签名
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)# 设置模块名为myapp
LOCAL_MODULE := myapp
# 添加需要编译的Java源文件
LOCAL_SRC_FILES := $(wildcard *.java)
# 添加需要编译的资源文件
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
# 设置输出APK的路径和名称
LOCAL_PACKAGE_NAME := myapp# 设置系统权限和目录
LOCAL_CERTIFICATE := platform
LOCAL_PRIVATE_PLATFORM_APIS := true
# 设置是否编译在 priv-app,如果没有指定目录默认为 system/app
LOCAL_PRIVILEGED_MODULE := true include $(BUILD_PACKAGE)

Android.bp

android_app {name: "myapp",srcs: ["path/to/your/app/src/**/*.java",],resource_dirs: ["path/to/your/app/res",],manifest: "path/to/your/app/AndroidManifest.xml",//加载类库static_libs: ["mylibrary",],//是否系统签名certificate: "platform",platform_apis: true,//是否生成到priv-app目录privileged: true,}

上面是代码的情况,编译apk获取系统签名的

Android13或者更新的源代码,大多都是使用Android.bp进行编译。

上面就是本文的主要内容,下面是一些相关内容知识。

三、缺少系统权限报错示例

这里以Settings设置属性为示例讲解。

Settings属性获取是不需要权限的,Settings属性设置是需要权限的,为啥会这样?

其实是因为代码里面定义的,具体是哪个类的哪行代码限制的?有兴趣的可以往下看看:

//Settings 获取属性值,不用权限和签名
int value = Settings.Global.getInt(getContentResolver(), Settings.Global.WIFI_ON, -1);//Settings 设置属性值,需要系统签名或者系统权限,否则会异常
boolean value = Settings.Global.putInt(getContentResolver(), Settings.Global.WIFI_ON, 1);//Wifi开关控制,需要系统签名或者系统权限,否则返回false,但是不会异常
WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
boolean value =  wifiManager.setWifiEnabled(true);
1、设置Settings属性报错

设置wifi开关状态报错:

 Caused by: java.lang.SecurityException: Permission denial: writing to settings requires:android.permission.WRITE_SECURE_SETTINGSat android.os.Parcel.createExceptionOrNull(Parcel.java:3011)at android.os.Parcel.createException(Parcel.java:2995)at android.os.Parcel.readException(Parcel.java:2978)at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:190)at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:142)at android.content.ContentProviderProxy.call(ContentProviderNative.java:732)at android.provider.Settings$NameValueCache.putStringForUser(Settings.java:3021)at android.provider.Settings$Global.putStringForUser(Settings.java:16753)at android.provider.Settings$Global.putString(Settings.java:16594)at android.provider.Settings$Global.putInt(Settings.java:16824)at com.demo.systemapp.MainActivity.setSettingsValue(MainActivity.java:29)at java.lang.reflect.Method.invoke(Native Method) 

从报错日志看是缺少了权限:WRITE_SECURE_SETTINGS。这个权限是需要签名或者系统应用才能拥有的权限。

如果要规避应用崩溃,可以通过try {}catch捕获异常,避免崩溃。

2、设置Wifi开关状态失败

调用wifi开关接口日志:

2024-01-20 17:09:04.193 638-1052/system_process I/WifiService: setWifiEnabled packageName = com.demo.systemapp, enable = true
2024-01-20 17:09:04.195 638-1052/system_process I/WifiService: setWifiEnabled not allowed for uid=10084

上面的日志都是 WifiServiceImpl.java 里面的日志。

显示了是哪个应用,调用了wifi开关的什么状态,后续显示not allowed ,因为uid = 100084,相当于啥都没做。

这种情况没有报错,也不会崩溃,但是就是调用了没效果。

所以大概可以猜测出需要设置Settings属性或者调用Wifi开关状态的接口都是要系统权限或者系统签名。

3、Settings属性设置为啥需要系统权限


看看代码就知道了:

frameworks\base\core\java\android\provider\Settings.java

//Settings.XXX.Put属性需要权限的原因,代码这里定义了的。
@SystemApi
@RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
public static boolean putString(ContentResolver resolver,String name,String value,。。。){return putStringForUser(resolver, name, value, tag, makeDefault,resolver.getUserId(), DEFAULT_OVERRIDEABLE_BY_RESTORE);
}

代码这里已经声明了,必须要系统应用和 WRITE_SECURE_SETTINGS权限,

才能调用后续的put方法,所以未获取到权限就会抛出异常。

4、设置Wifi开关状态为啥失败?


根据下面代码的具体判断就可以看得出:

packages\modules\Wifi\service\java\com\android\server\wifi\WifiServiceImpl.java

//WifiManager.setWifiEnabled 失败原因,这里判断后返回了false
public synchronized boolean setWifiEnabled(String packageName, boolean enable) {//这里判断的是三方应用,主要是uid,三方应用不具有系统签名,所以返回false,不往下走if (isThirdParty && !isTargetSdkLessThanQ) {mLog.info("setWifiEnabled not allowed for uid=%").c(callingUid).flush();return false;}//这里判断是否是飞行模式并且是否不是系统应用(priv-app目录下的应用)//如果是飞行模式,并且不是priv-app目录的系统应用,返回false// If Airplane mode is enabled, only privileged apps are allowed to toggle Wifiif (mSettingsStore.isAirplaneModeOn() && !isPrivileged) {mLog.err("setWifiEnabled in Airplane mode: only Settings can toggle wifi").flush();return false;}//如果不是priv-app目录应用,并且热点开启的情况,返回false// If SoftAp is enabled, only privileged apps are allowed to toggle wifiif (!isPrivileged && mTetheredSoftApTracker.getState() == WIFI_AP_STATE_ENABLED) {mLog.err("setWifiEnabled with SoftAp enabled: only Settings can toggle wifi").flush();return false;}...
}

四、其他


1、系统权限介绍


framework 定义的所有 权限都是有定义包含 protectionLevel 等级的,主要权限等级有:普通,运行时,系统签名,特殊 。

(1)普通权限(normal)
此类权限允许访问超出应用沙盒的数据和执行超出应用沙盒的操作。但这些数据和操作对用户隐私及对其他应用的操作带来的风险非常小。

比如,上网权限,wifi 状态监听,蓝牙,获取后台任务等待,大概有一百多个。

(2)运行时权限(dangerous)
运行时权限也称为危险权限,此类权限授予应用对受限数据的额外访问权限,并允许应用执行对系统和其他应用具有更严重影响的受限操作。因此需要先在应用中请求运行时权限,然后才能访问受限数据或执行受限操作。当应用请求运行时权限时,系统会显示运行时权限弹窗提示。

比如,文件读写权限,日历读取和设置权限等待,总共不到一百个。

(3)签名权限(signature)
当应用声明了其他应用已定义的签名权限时,如果两个应用使用同一证书进行签名,系统会在安装时向前者授予该权限。否则,系统无法向前者授予该权限。(注意:有些签名权限不适合第三方应用使用。)

该权限只需要在manifest中声明使用,同时应用和这类权限定义者拥有一样的签名系统就会默认授予应用这类权限;系统授予这类权限后应用无需像运行时权限一样动态申请。

比如,Android11 新增的文件管理权限,对wifi,热点,Camera一些特殊操作权限,比较多,大概有五百多个。

(4)特殊权限(privileged)
特殊权限与特定的应用操作相对应。只有平台和原始设备制造商 (OEM) 可以定义特殊权限。此外,如果平台和 OEM 想要防止有人执行功能特别强大的操作(例如通过其他应用绘图),通常会定义特殊权限。系统设置中的特殊应用访问权限页面包含一组用户可切换的操作。其中的许多操作都以特殊权限的形式实现。每项特殊权限都有自己的实现细节。系统会为特殊权限分配“appop”保护级别。

比如本文的: 允许应用程序在所有用户之间进行交互 权限,启动前台服务权限,可通过overlay形式覆盖属性权限,应用主题更改监听等等,大概有三百多个。

一般情况下:特殊权限大部分与系统签名文件同时使用。

我们常用的广播都定义在framework\base\core\res\AndroidManifest.xml里面,如果要新增可以在里面新增

值得注意的是,系统签名文件是比系统应用权限大的,比如:

    //MANAGE_CAMERA 权限,必须要系统签名才能获取到<permission android:name="android.permission.MANAGE_CAMERA"android:protectionLevel="signature" />//CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS 权限,系统签名或者priv-app应用都可以获取到<permission android:name="android.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS"android:protectionLevel="signature|privileged" />
2、如何查看一个应用的权限情况?

dumpsys package XXX包名,可以查看apk信息:

E:\Studio\project\test\SystemApp>adb shell
rk3588_t:/ $ ^C
130|rk3588_t:/ $ dumpsys package com.demo.systemappPackages:Package [com.demo.systemapp] (6e1e98c): //1、应用包名userId=10083 //uid,system.uid = 10000pkg=Package{1a148d5 com.demo.systemapp}codePath=/system/app/SystemAppDemo //2、apk路径resourcePath=/system/app/SystemAppDemotimeStamp=2024-01-20 11:45:31lastUpdateTime=2024-01-20 11:45:31requested permissions:  //3、AndroidManifest中声明的权限android.permission.WRITE_SECURE_SETTINGSandroid.permission.POST_NOTIFICATIONSUser 0: ceDataInode=9991 installed=true hidden=false suspended=false distractionFlags=0 stopped=false notLaunched=false enabled=0 instant=false virtual=falseinstallReason=0firstInstallTime=2024-01-20 11:45:31uninstallReason=0runtime permissions:  //4、获取到的权限,granted=true 才算获取到!android.permission.POST_NOTIFICATIONS: granted=false, flags=[ USER_SENSITIVE_WHEN_GRANTED|USER_SENSITIVE_WHEN_DENIED]rk3588_t:/ $
E:\Studio\project\test\SystemApp>

从dumpsys package XXX 命令的日志,可以看到包名应用对应的Uid信息,版本信息,apk安装位置,安装时间,AndroidManifest声明的权限,实际获取到的权限等等信息。

requested permissions 下面的权限是应用声明的权限,runtime permissions的权限是当前获取到的权限。

值得注意的是即使是系统应用或者系统签名应用也是要在 AndroidManifest 中声明需要的权限。

3、系统权限级别总结


Android中不同应用权限级别从低到高总结场景

(1)普通应用。只用到了普通权限,比如上网权限等等。
(2)system/app 系统应用,用来可以限制无法手动卸载,对系统权限没有要求的情况,无法调用系统api
(3)system/priv-app 系统应用(未设置uid.system),无法手动卸载,可以调用部分系统api
(4)系统签名应用普通安装的方式,可以调用系统相关api,同时也可以被手动卸载,可以添加privileged特殊权限
(5)system/priv-app 系统应用(设置uid.system),无法手动卸载,可以调用全部系统api,可以添加privileged特殊权限

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

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

相关文章

Spring 上下文对象

1. Spring 上下文对象概述 Spring 上下文对象&#xff08;ApplicationContext&#xff09;是 Spring 框架的核心接口之一&#xff0c;它扩展了 BeanFactory 接口&#xff0c;提供了更多企业级应用所需的功能。ApplicationContext 不仅可以管理 Bean 的生命周期和配置&#xff0…

Kafka-副本分配策略

一、上下文 《Kafka-创建topic源码》我们大致分析了topic创建的流程&#xff0c;为了保持它的完整性和清晰度。细节并没有展开分析。下面我们就来分析下副本的分配策略以及副本中的leader角色的确定逻辑。当有了副本分配策略&#xff0c;才会得到分区对应的broker&#xff0c;…

Move语言中的代币合约:设计和实现指南

系列文章目录 Task1&#xff1a;hello move&#x1f6aa; Task2&#xff1a;move coin&#x1f6aa; Task3&#xff1a;move nft&#x1f6aa; 更多精彩内容&#xff0c;敬请期待&#xff01;✌️ 文章目录 系列文章目录前言什么是 Sui 链&#xff1f;什么是 Move 编程语言&a…

精酿啤酒厂建设攻略——关键步骤与注意点

建设一家精酿啤酒厂&#xff0c;每一步都至关重要。在这里&#xff0c;小编将为您精心梳理建设精酿啤酒厂的详细步骤和关键注意点&#xff0c;助您在啤酒市场的蓝海中乘风破浪。从投资预算的精确规划&#xff0c;到市场渠道的精心布局&#xff0c;从产品特色的精准定位&#xf…

什么是UGFC?模块电脑(核心板)规范标准简介四

1. 概念 UGFC是Unified Gold Finger Core Board的缩写&#xff08;意指&#xff1a;统一接口定义金手指核心板&#xff09;&#xff0c;为武汉万象奥科电子有限公司基于企业标准定义的一种针对嵌入式、低功耗、通用型的小型计算机模块标准&#xff0c;采用204Pin金手指连接器…

数据科学与SQL:组距分组分析 | 区间分布问题

目录 0 问题描述 1 数据准备 2 问题分析 3 小结 0 问题描述 绝对值分布分析也可以理解为组距分组分析。对于某个指标而言&#xff0c;一个记录对应的指标值的绝对值&#xff0c;肯定落在所有指标值的绝对值的最小值和最大值构成的区间内&#xff0c;根据一定的算法&#x…

量子感知机

神经网络类似于人类大脑&#xff0c;是模拟生物神经网络进行信息处理的一种数学模型。它能解决分类、回归等问题&#xff0c;是机器学习的重要组成部分。量子神经网络是将量子理论与神经网络相结合而产生的一种新型计算模式。1995年美国路易斯安那州立大学KAK教授首次提出了量子…

mysql in查询大数据量业务无法避免情境下优化

在 MySQL 中&#xff0c;IN 查询操作广泛用于从数据库中检索符合条件的多条记录&#xff0c;但当涉及到大数据量的 IN 查询时&#xff0c;性能可能会显著下降。特别是当 IN 子句中的元素数量非常大时&#xff0c;MySQL 需要对每个元素进行匹配&#xff0c;这会导致查询变得非常…

大语言模型---ReLU函数的计算过程及其函数介绍

文章目录 1. 概要2. ReLU定义 1. 概要 **ReLU 作用&#xff1a;**主要用于为神经网络引入非线性能力&#xff0c;作用是将输入中的整数保留原值&#xff0c;负数置为 0。 从而在层与层之间引入非线性&#xff0c;使神经网络能够拟合复杂的非线性关系。 **ReLU使用场景&#xf…

SPSS统计学:连续均匀分布

概念 连续均匀分布是指在某个连续区间上&#xff0c;随机变量取值的概率密度函数是常数的分布。假设连续均匀分布的区间为[a,b]&#xff0c;其中a是区间的下界&#xff0c;b是区间的上界。 方差的推导 连续均匀分布的方差计算中出现数字12&#xff0c;是因为在推导过程中&…

时间请求参数、响应

&#xff08;7&#xff09;时间请求参数 1.默认格式转换 控制器 RequestMapping("/commonDate") ResponseBody public String commonDate(Date date){System.out.println("默认格式时间参数 date > "date);return "{module : commonDate}"; }…

JAVA八股与代码实践----接口与抽象类的区别和用法

接口和抽象类的区别 关键字abstractinterface 实例化不能直接实例化不能直接实例化 方法可以有抽象和具体方法只能有抽象方法&#xff08;Java 8 支持默认方法&#xff09; 变量可以有普通变量只能有常量 (public static final) 继承单继承多继承 构造函数可以定义不允许…

python学习记录18

1 函数的定义 python中的函数指使用某个定义好的名字指代一段完整的代码&#xff0c;在使用名字时可以直接调用整个代码&#xff0c;这个名字叫做函数名。利用函数可以达到编写一次即可多次调用的操作&#xff0c;从而减少代码量。 函数分为内置函数与自定义函数。内置函数例…

设计模式:4、命令模式(双重委托)

目录 0、定义 1、命令模式包括四种角色 2、命令模式的UML类图 3、代码示例 0、定义 将一个请求封装为一个对象&#xff0c;从而使用户可用不同的请求对客户进行参数化&#xff1b;对请求排队或记录请求日志&#xff0c;以及支持可撤销的操作。 1、命令模式包括四种角色 接…

WPF动画

在 WPF&#xff08;Windows Presentation Foundation&#xff09;中&#xff0c;主要有两种类型的动画&#xff1a;属性动画&#xff08;Property Animation&#xff09;和关键帧动画&#xff08;Key - Frame Animation&#xff09;。属性动画用于简单地从一个起始值平滑地过渡…

VSCode汉化教程【简洁易懂】

我们安装完成后默认是英文界面。 找到插件选项卡&#xff0c;搜索“Chinese”&#xff0c;找到简体&#xff08;更具你的需要&#xff09;&#xff08;Microsoft提供&#xff09;Install。 安装完成后选择Change Language and Restart。

海洋通信船舶组网工业4G路由器应用

船舶是浩瀚海洋中探索与贸易的载体&#xff0c;更是船员们生活与工作的家园。为了在广阔的水域中搭建起稳定、高效的网络桥梁&#xff0c;工业4G路由器以卓越的通信组网能力&#xff0c;为船舶组网提供网络支持。 工业4G路由器以其强大的信号发射能力&#xff0c;确保船舶内部…

深入浅出分布式缓存:原理与应用

文章目录 概述缓存分片算法1. Hash算法2. 一致性Hash算法3. 应用场景Redis集群方案1. Redis 集群方案原理2. Redis 集群方案的优势3. Java 代码示例:Redis 集群数据定位Redis 集群中的节点通信机制:Gossip 协议Redis 集群的节点通信:Gossip 协议Redis 集群的节点通信流程Red…

麒麟部署一套NFS服务器,用于创建网络文件系统

一、服务端共享目录 在本例中,kyserver01(172.16.200.10)作为客户端,创建一个目录/testdir并挂载共享目录;kyserver02(172.16.200.11)作为服务端,创建一个共享目录/test,设置为读写权限,要求客户端使用root登录时映射为nobody用户、非root登录时保持不变。 服务端启…

美国AWS EC2 ubuntu 使用密码登陆

1。使用页面登录ec2 2.切换root用户 sudo -i 3.为root用户或者其它用户配置密码 passwd user passwd root 4.修改下面文件的配置vi /etc/ssh/sshd_config PermitRootLogin和PasswordAuthentication 修改为yes 第五步&#xff1a;进入/etc/ssh/sshd_config.d目录&#xff0c;…