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

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

文章目录

  • Android 应用添加系统签名权限的几种方式实现介绍
    • 一、前言
    • 二、Android 应用添加系统签名权限的几种方式介绍
      • 1、在Android Studio添加系统签名文件
      • 2、源码编译apk添加系统签名
          • Android.mk
          • Android.bp
      • 3、源码编译app代码添加系统签名
          • Android.mk
          • Android.bp
    • 三、缺少系统权限报错示例
      • 1、设置Settings属性报错
      • 2、设置Wifi开关状态失败
      • 3、Settings属性设置为啥需要系统权限?
      • 4、设置Wifi开关状态为啥失败?
    • 四、其他
      • 1、系统权限介绍
        • (1)普通权限(normal)
        • (2)运行时权限(dangerous)
        • (3)签名权限(signature)
        • (4)特殊权限(privileged)
      • 2、如何查看一个应用的权限情况?
      • 3、系统权限级别总结
        • Android中不同应用权限级别从低到高总结场景
      • 4、Android APEX:系统新篇章的应用扁平化技术

一、前言

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

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

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

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

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

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

源码中生成 jks 签名文件:

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

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;}...
}

上面是Android13 中wifi开关状态返回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" />

上面的是 Android13 上比较新的权限定义,有兴趣的可以看看。

在线查看权限定义网址:

http://aospxref.com/android-13.0.0_r3/xref/frameworks/base/core/res/AndroidManifest.xml

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特殊权限

了解到不同的权限需求,应用要安装/编译在什么目录心里就有个底了。

4、Android APEX:系统新篇章的应用扁平化技术

Android13 和更新的版本编译,你会发现package/modules下面的代码模块都是编译到了目录: /system/apex/XXXPackage/XXX.apk

这里面的apk有些是系统签名应用,有些是普通应用,这个和具体的bp里面的编译规则相关。

APEX 的相关介绍:

https://blog.csdn.net/u011897062/article/details/133122565

https://blog.csdn.net/u010164190/article/details/122324409

这块知识看起来还是比较复杂。

对于普通应用开发者,和一般的系统应用开发者其实没啥研究价值。

可以简单的理解一下模块化的概念:比如把一个apk的某些模块编译成一个apk,这些模块可以接收广播处理事务或者启动服务处理事务等功能。

这个和应用开发中的模块化是同样的原理,只是源码中Android13 以前很少这样开发,后续更新的源码应该是会更多这样的模块。

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

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

相关文章

OJ_整数奇偶排序

题干 c实现 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<algorithm> using namespace std;//compare函数不交换返回true bool compare(int a, int b) {//1.a奇数&#xff0c;b偶数&#xff0c;不交换//2.a奇数&#xff0c;b奇数&#xff0c;a比b…

C语言实现跳表(附源码)

最近在刷一些链表的题目&#xff0c;在leetcode上有一道设计跳表的题目&#xff0c;也是通过查阅各种资料&#xff0c;自己实现出来&#xff0c;感觉这是种很神奇的数据结构。 一.简介 跳表与红黑树&#xff0c;AVL树等&#xff0c;都是一种有序集合&#xff0c;那既然是有序…

2023年09月CCF-GESP编程能力等级认证Python编程六级真题解析

Python等级认证GESP(1~6级)全部真题・点这里 一、单选题(共15题,共30分) 第1题 近年来,线上授课变得普遍,很多有助于改善教学效果的设备也逐渐流行,其中包括比较常用的手写板,那么它属于哪类设备?( ) A:输入 B:输出 C:控制 D:记录 答案:A 第2题 以下关于…

ffmpeg 输入文件,输入出udp-ts 指定pid

要使用FFmpeg将输入文件转换为UDP传输流&#xff08;TS&#xff09;并指定特定的PID&#xff0c;您可以使用以下命令&#xff1a; ffmpeg -i input_file -c:v libx264 -preset ultrafast -tune zerolatency -f mpegts -map 0:v:0 -map 0:a:0 -pid 0x12345678 udp://output_addr…

解决java,C#,php,python MD5加密不一致问题

JAVA写法 public static String md5Base64(final String str, final String key) throws Exception {if ((null == str) || "".equals(str)) {return "";}MessageDigest messagedigest;messagedigest = MessageDigest.getInstance("MD5");Strin…

Prompt Engneering(提示词工程)

大模型的目标是理解和生成人类语言。给定一些词语&#xff0c;语言模型可以预测下一个词语可能是什么&#xff0c;或者给定的一些词语生层对应内容。 那么如何引导它们产生期望的输出&#xff0c;或者说如何提问&#xff0c;就成为了一个关键的问题。这就引入了一个重要的概念…

QStandardItemModel与QTableView里如何设置复选框居中

笔者为这个问题思索了不少时间&#xff0c;这个问题就是c qt里创建了一个QStandardItemModel设置了表格的表头&#xff0c;往表格填充数据时&#xff0c;数据的复选框左对齐&#xff0c;想要设置复选框居中对齐&#xff0c;不知道如何处理&#xff0c;这里给出代码与运行效果&a…

用Python画一条祥龙,祝您新年龙腾万里

用Python画一条祥龙&#xff0c;祝您新年龙腾万里 龙年到了&#xff0c;祝大家新年龙行龘龘&#xff0c;龙腾万里&#xff01; 从2021年开始&#xff0c;我每年都用Python画一幅当年生肖的图。 用Python标准库turtle画一头金牛&#xff0c;祝您新年牛气冲天&#xff01; 用P…

vscode 括号 python函数括号补全

解决方法 在setting.json中添加 “python.analysis.completeFunctionParens”: true 打开设置&#xff1b; 点击图中按钮打开setting.json文件 添加 “python.analysis.completeFunctionParens”: true

apipost 简单的性能压测总结

1、简单的使用机型牌评估 1&#xff09;jdk默认256M给100用&#xff0c;推荐给1000人同时用JVM 堆栈建议2G~4G&#xff08;目前定了机型4核8G内存 2T磁盘做radio0存储&#xff09;&#xff1b; 2&#xff09;数据库配置文件写了占了2G内存&#xff08;my.cnf文件&#xff09…

Python算法100例-1.3 牛顿迭代法求方程根

完整源代码项目地址&#xff0c;关注博主私信’源代码’后可获取 1&#xff0e;问题描述 编写用牛顿迭代法求方程根的函数。方程为 a x 3 b x 2 c x d 0 ax^3bx^2cxd0 ax3bx2cxd0&#xff0c;系数a、b、c、d由主函数输入&#xff0c;求x在1附近的一个实根。求出根后&…

详解SkyWalking前端监控的性能指标

SkyWalking 从8.2.0版本开始支持对前端浏览器端的性能进行监控&#xff0c;不仅可以像以前一样监控浏览器发送给后端服务的与请求&#xff0c;还能看到前端的渲染速度、错误日志等信息——这些信息是获取最终用户体验的最有效指标。实现的方式是引入skywalking-client-js库&…

C语言——字符串大小写互换

前言&#xff1a; 在C语言中&#xff0c;大小写字母相互转换是一个常见的操作。本文将详细介绍C语言中实现大小写字母相互转换的各种方法&#xff0c;并附上代码示例。 目录 一、使用tolower()和toupper()函数 二、使用位操作 三、使用字符串操作函数 一、使用tolower()和t…

STL篇三:list

文章目录 前言1.list的介绍和使用1.1 list的介绍1.2 list的使用1.3 list的迭代器的失效 2.list的模拟实现2.1 结点的封装2.2 迭代器的封装2.2.1 正向迭代器2.2.2 反向迭代器 2.3 list功能的实现2.3.1 迭代器的实例化及begin()、end() 2.3.2 构造函数2.3.3 赋值运算符重载2.3.4 …

YGG 为 Axie Infinity: Origins 发布超级任务游戏内训练器,深化对 Ronin 的支持

自 2023 年以来&#xff0c;Ronin 已成为增长最快的游戏区块链。由于 Axie Infinity 和 Pixels 等游戏的持续成功&#xff0c;日活跃用户数量至少增长了 10 倍。在过去的一年里&#xff0c;有超过 120 万个新地址加入&#xff0c;并且&#xff0c;这个数字还在持续增长。 ​Ron…

科技助力快乐养老,山东恒康养老服务中心与清雷科技达成合作

谈到养老服务&#xff0c;大家或许会有一些刻板印象。 如果说一个落落大方、笑容温柔的90后女孩是一家养老院的院长&#xff0c;很多人都会感到诧异。但就是这位来自山东省龙口市恒康养老服务中心的90后院长韩雨&#xff0c;实现了百分百入住率、百分百好评的养老服务奇迹。 韩…

关于虚拟货币内容发布规则的调整通知

为提升内容质量&#xff0c;遏制错误虚假有害内容传播蔓延&#xff0c;营造清朗网络空间&#xff0c;CSDN根据《国家发展改革委等部门关于整治虚拟货币“挖矿”活动的通知》及国家相关法律法规&#xff0c;针对虚拟货币相关内容制定以下细则&#xff0c;依据最新规则&#xff0…

北斗卫星在物联网时代的应用探索

北斗卫星在物联网时代的应用探索 在当今数字化时代&#xff0c;物联网的应用已经深入到人们的生活中的方方面面&#xff0c;让我们的生活更加智能便捷。而北斗卫星系统作为我国自主研发的卫星导航系统&#xff0c;正为物联网的发展提供了强有力的支撑和保障。本文将全面介绍北…

【软件设计师笔记】深入探究操作系统

【软件设计师笔记】计算机系统基础知识考点(传送门) &#x1f496; 【软件设计师笔记】程序语言设计考点(传送门) &#x1f496; &#x1f413; 操作系统的作用 1.通过资源管理提高计算机系统的效率 2.改善人机界面向用户提供友好的工作环境 &#x1f413; 操作系统的特征 …

nodejs 事件循环

浏览器的事件循环比较熟悉了&#xff0c;也来了解下 node 的。 参考来源&#xff1a; https://nodejs.org/en/guides/event-loop-timers-and-nexttick/ https://juejin.cn/post/6844903999506923528 事件循环分为 6 个阶段&#xff0c;图中每个框都是一个阶段&#xff0c;每个阶…