以下是重构后的内容:

一、前言

在 Android 系统中,添加系统签名可以获取到一些系统权限并调用一些系统接口。添加系统签名的方式主要有两类:一是使用 Android Studio 配置签名文件生成 APK;二是在源码目录编译并添加系统签名生成 APK。本文将介绍这两种方式,并后续延伸相关内容。如果对签名知识不熟悉,建议先进行学习。

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

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

源码中生成 jks 签名文件的方法如下:

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

在 Studio 中,针对需要签名的模块(默认是 app)的 build.gradle 文件中添加如下代码:

```groovy

android {

...

signingConfigs {

release {

storeFile file("your_keystore_path")

storePassword "your_keystore_password"

keyAlias "your_key_alias"

keyPassword "your_key_password"

}

}

buildTypes {

release {

signingConfig signingConfigs.release

...

}

}

}

```

请根据提供的内容完成内容重构,并保持段落结构:

```

android {

compileSdkVersion 30

buildToolsVersion "30.0.0"

compileOptions {

sourceCompatibility JavaVersion.VERSION_1_8

targetCompatibility JavaVersion.VERSION_1_8

}

signingConfigs {

main {

storeFile file("./platform.jks") //签名文件途径,根目录

storePassword "skg202302"

keyAlias "skg"

keyPassword "skg202302"

}

}

buildTypes {

release {

minifyEnabled false

signingConfig signingConfigs.main //添加那一止

proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"

}

debug {

minifyEnabled false

signingConfig signingConfigs.main //添加那一止

proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"

}

}

}

```

在某些情况下,如果Android应用程序包(APK)没有签名文件,或者需要为APK添加额外的签名信息,那么可以为其添加uid.system字段。然而,这样做可能会导致应用程序无法在对应的Android系统上正常运行。

为了解决这个问题,可以在源代码中进行编译。这样生成的APK将包含预先签名的信息。以下是重构后的内容:

1. 如果APK没有签名文件或需要添加额外的签名信息,可以考虑为其添加uid.system字段。但是,请注意这样做可能会导致应用程序无法在对应的Android系统上正常运行。

2. 为了确保APK能够在目标系统上正常运行,建议在源代码中进行编译。这样生成的APK将包含预先签名的信息,从而避免了在目标系统上出现问题的可能性。

总之,在处理没有签名文件或需要为APK添加额外签名信息的场景时,可以考虑为APK添加uid.system字段。但为了确保应用程序能够顺利运行,建议在源代码中进行编译并生成包含预签名信息的APK。

Android.mk 文件

## 编译目录设置

```makefile

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 文件

```dart

android_app_import {

name: "FileManager",

apk: "FileManager.apk", //生成到priv-app目录下

privileged: true, //运用系统签名

certificate: "platform",

}

```

## 源码编译app代码添加系统签名

```makefile

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 文件(已包含在上述内容中)

一、代码编译及系统签名

在Android13中,大部分更新的源代码都是通过使用Android.bp文件进行编译。以下是原文的次要内容,接下来是一些相关内容知识。

二、短少系统权限报错示例

以Settings设置属性为例进行讲解。Settings属性获取不需要权限,而Settings属性设置需要权限。为什么会这样呢?实际上是因为代码中定义的限制,具体是哪个类的哪行代码限制的?有兴趣的可以继续往下看:

```java

// 获取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);

```

三、设置Settings属性报错

当尝试设置wifi开关状态时出现报错:

```java

// 设置wifi开关状态报错

boolean value = wifiManager.setWifiEnabled(true);

```

Caused by: java.lang.SecurityException: Permission denial: writing to settings requires android.permission.WRITE_SECURE_SETTINGS at android.os.Parcel.createExceptionOrNull(Parcel.java:3011)

This exception occurs when the app attempts to write to the secure settings, but is denied permission due to security restrictions. Specifically, the app needs the android.permission.WRITE_SECURE_SETTINGS permission in order to write to the secure settings.

The exact location of this exception in the code is at android.provider.Settings$NameValueCache.putStringForUser(Settings.java:3021). Here's how it breaks down:

- The error starts with a SecurityException that indicates an attempted violation of security restrictions.

- The specific permission required for writing to secure settings is identified as android.permission.WRITE_SECURE_SETTINGS.

- The exception is caused by attempting to write to the secure settings from within the com.demo.systemapp package and specifically within the setSettingsValue() method at MainActivity.java:29.

- The stack trace shows that this exception was caught and handled in some way, although further information on what was done is not provided in the question.

In summary, this exception indicates that a permissions issue has occurred while trying to write to the secure settings of an Android application. It is important to ensure that the necessary permissions have been granted to the app, or else it will not be able to access and modify certain system settings.

根据提供的信息,我们可以得到以下重构后的段落结构:

1. 从报错日志看,问题是缺少权限: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开关,以及尝试打开或关闭Wifi的状态。然后显示"not allowed",原因是uid = 10084,这意味着用户ID为10084的用户没有足够的权限执行此操作。虽然没有报错,也没有解体,但实际上没有成功执行该操作。

根据这些信息,我们可以推测出设置Settings属性或调用Wifi开关接口需要系统权限或系统签名。

3. 为什么Settings属性设置需要系统权限?

查看代码即可了解原因:

```java

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

```

从这段代码可以看出,要使用Settings.XXX.Put属性,必须具备系统使用和WRITE_SECURE_SETTINGS权限。

根据提供的内容,我们可以重构如下:

1. 威力挪用后续的put办法,如果未获得权限,就会抛出异常。

2. 设置Wifi开关形态失败的原因是什么?

通过查看下面的代码,我们可以得出详细判断:

```java

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

``

```java

// 判断WifiManagersetWifiEnabled失败后返回false的情况

public synchronized boolean setWifiEnabled(String packageName, boolean enable) {

// 判断是否为三方应用且目标SDK版本大于等于Q

if (isThirdParty && !isTargetSdkLessThanQ) {

mLog.info("setWifiEnabled not allowed for uid=" + callingUid).c(callingUid).flush();

return false;

}

// 判断是否处于飞翔模式且不是系统使用(priv-app目录下的使用)

if (mSettingsStore.isAirplaneModeOn() && !isPrivileged) {

mLog.err("setWifiEnabled in Airplane mode: only Settings can toggle wifi");

return false;

}

// 如果不是priv-app目录使用,并且热点开启的状况,返回false

if (!isPrivileged && mTetheredSoftApTracker.getState() == WIFI_AP_STATE_ENABLED) {

mLog.err("setWifiEnabled with SoftAp enabled: only Settings can toggle wifi");

return false;

}

// 其他情况,执行设置Wi-Fi的操作并返回结果

// ...

}

```

Android 13中wifi开关形态返回false的几种状况阐明。

一、wifi开关形态返回false的情况

1. 用户没有打开wifi开关;

2. 用户关闭了wifi开关后再次打开;

3. 系统检测到异常情况,如网络连接不稳定等,自动关闭wifi开关。

二、其余 1、系统权限引见 framework界说的所有权限都是有界说包括protectionLevel品级的,次要权限品级有:普通,运止时,系统签名,非凡 。(1)普通权限(normal)此类权限允许会见超出使用沙盒的数据和执止超出使用沙盒的收配。但那些数据和收配对用户隐私及对其余使用的收配带来的风险很是小。比如,上网权限,wifi 形态监听,蓝牙,获与靠山任务等候,粗略有一百多个。(2)运止时权限(dangerous)运止时权限也称为危险权限,此类权限授予使用对受限数据的格外会见权限,并允许使用执止对系统和其余使用具有更重大影响的受限收配。果此须要先正在使用中乞求运止时权限,而后威力会见受限数据或执止受限收配。当使用乞求运止时权限时,系统会显示运止时权限弹窗提示。比如,文件读写权限,日历读与和设置权限等候,总共不到一百个。(3)签名权限(signature)当使用声明了其余使用已界说的签名权限时,假如两个使用运用同一证书停行签名,系统会正在拆置时向前者授予该权限。否则,系统无奈向前者授予该权限。该权限只须要正在manifest中声明运用,同时使用和那类权限界说者领有一样的签名系统就会默许授予使用那类权限;系统授予那类权限后使用无需像运止时权限一样动态申请。比如,Android11新删的文件打点权限,对wifi、热点、Camera一些非凡收配权限比较多,粗略有五百多个。(4)非凡权限(privileged)非凡权限取特定的使用收配相对应。只要平台和本始方法制造商 (OEM) 可以界说非凡权限。另外,假如平台和 OEM 想要避免有人执止罪能出格壮大的收配(譬喻通过其余使用绘图),但凡会界说非凡权限。系统设置中的非凡使用会见权限页面包孕一组用户可切换的收配。此中的很多收配都以非凡权限的模式真现。每项非凡权限都有原人的真现细节。系统会为非凡权限分配“appop”护卫级别。比如原文的:允许使用步调正在所有用户之间停行交互、启动前台效劳、可通过overlay模式笼罩属性、使用主题变动监听等等,粗略有三百多个。正常状况下:非凡权限大局部取系统签名文件同时运用。

在 Android 系统中,权限声明通常位于 framework/base/core/res/AndroidManifest.xml 文件中。如果需要新增权限,可以在此文件中进行添加。需要注意的是,系统签名文件具有比普通应用使用的权限更高的权限。例如:对于 "android.permission.MANAGE_CAMERA" 权限,系统签名可以获得,而普通应用无法获得;对于 "android.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS" 权限,系统签名和普通应用都可以获得。

以上是 Android 13 中的一些较新的权限定义。感兴趣的读者可以查看相关资料。要查询某个应用的权限状态,可以使用以下命令:dumpsys package <包名>。这将显示该 APK 的信息,包括已授权的权限。

```

E:Studio\projecttest\SystemApp> adb shell rk3588_t:/ $

^C

130|rk3588_t:/ $ dumpsys package com.demo.systemapp

Packages:

Package [com.demo.systemapp] (6e1e98c): //1、使用包名

userId=10083 //uid,system.uid = 10000 pkg=Package{1a148d5 com.demo.systemapp} codePath=/system/app/SystemAppDemo //2、apk途径

resourcePath=/system/app/SystemAppDemo timeStamp=2024-01-20 11:45:31 lastUpdateTime=2024-01-20 11:45:31 requested permissions: //3、AndroidManifest中声明的权限

android.permission.WRITE_SECURE_SETTINGS android.permission.POST_NOTIFICATIONS User 0: ceDataInode=9991 installed=true hidden=false suspended=false distractionFlags=0 stopped=false notLaunched=false enabled=0 instant=false virtual=false installReason=0 firstInstallTime=2024-01-20 11:45:31 uninstallReason=0 runtime 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下的权限是使用在AndroidManifest中声明的权限,而runtime permissions下的权限是当前实际获得的权限。值得注意的是,即使是系统使用的权限或系统签名使用的权限,也需要在AndroidManifest中进行声明。

在使用权限级别时,需要按照从低到高的顺序进行总结。具体包括以下场景:

1. 普通使用:只用到了普通权限,例如上网权限等。

2. system/app:系统使用,用于限制无法手动卸载的应用,对系统权限没有要求的场景,或者挪用系统API。

3. system/priv-app:系统使用(未设置uid.system),无法手动卸载,可以挪用部分系统API。

4. 系统签名使用普通安装方式,可以挪用系统相关API,同时也可以被手动卸载,可以添加privileged特权权限。

5. system/priv-app:系统使用(设置uid.system),无法手动卸载,可以挪用全部系统API,可以添加privileged特权权限。

理解不同的权限需求后,开发者在进行打包或编译时就可以知道要放置在什么目录下。

此外,还有一点关于Android APEX的内容需要了解。在Android 13及更新版本的编译过程中,你会发现package/modules下面的代码模块都被编译到了目录:/system/apex/XXXPackage/XXX.apk。这些apk有些是系统签名使用的,有些是普通使用的,具体的编译规则与详细的bp文件有关。

APEX的相关内容可以通过以下链接进行学习:

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

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

需要注意的是,这些知识对于普通使用开发者和正常系统的开发人员来说,可能并没有太大的研究价值。但是了解模块化的概念仍然具有一定的意义,比如将一个apk的某些模块编译成一个apk,以便这些模块能够接收广播、管理事务或启动服务等功能。

在开发过程中,模块化是其核心原则之一。这与使用已开发好的模块有着相同的基本原理,只是在源代码中,Android 13 之前的版本很少采用这种方式进行开发。然而,随着后续版本的更新,我们可以看到更多的模块化设计出现在源代码中。