Android - 自动系统签名
# 一、系统签名
以下是两类应用开发场景:
- 普通应用开发:使用公司自定义
keystore
进行签名,如:微信、支付宝 - 系统应用开发:使用 AOSP 系统签名或厂商自定义
keystore
进行签名,如:设置、录音
系统应用开发相对于普通应用开发拥有更高的权限,可以使用一些系统级别的 API,比如:
- 静默安装(
android.permission.INSTALL_PACKAGES
) - 屏幕抓取(
SurfaceControl#createDisplay
) - 设备音频抓取(
AudioSource.REMOTE_SUBMIX
) - 应用外悬浮窗
- ...
系统应用开发只适用于以下几类开发者:
- Android 系统定制开发者(自主拥有系统签名)
- Android 系统厂商合作开发者(能拿到厂商的自定义系统签名)
温馨提示:如果你不属于以上类别,那么你要清楚,没有系统签名一切都是空谈。
# 1、配置
系统应用开发需要在清单文件根节点指定 sharedUserId
:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:sharedUserId="android.uid.system">
...
</manifest>
# 2、签名
配置完 android:sharedUserId="android.uid.system"
之后,此时的 app 是无法成功安装到设备的,控制台会提示 INSTALL_FAILED_SHARED_USER_INCOMPATIBLE
,这是因为此时 app 已经被识别为系统应用,但是其签名信息却不是系统签名,于是无法通过系统检验。进行系统签名需要准备好如下几个文件:
- platform.pk8:签名证书
- platform.x509.pem:签名证书
- signapk.jar:签名工具
如果你的设备是纯纯的原生系统(AOSP),那么可以在以下网址中找到这几个签名文件:
- https://github.com/aosp-mirror/platform_build/tree/master/target/product/security (opens new window)
- https://github.com/techexpertize/SignApk (opens new window)
- https://github.com/maks/aosp-signapk (opens new window)
注:如果是
Android 系统厂商合作开发
这种场景(自定义过系统签名),那么以上文件应该让合作厂商提供。
签名文件准备好之后,就可以通过以下命令对 app-unsigned.apk
进行系统签名了:
java -jar signapk.jar platform.x509.pem platform.pk8 app-unsigned.apk signed.apk
命令执行之后,生成出来的 signed.apk
文件就已经是经过系统签名的了。
# 3、安装
执行 adb install signed.apk
命令后,发现这次就可以正常安装了。通过 adb install
这种方式,就跟我们平时普通应用开发一样,apk 会被安装到 /data/app/
目录下,但是因为指定了 android:sharedUserId="android.uid.system"
,所以,这时的 app 会被认为是系统应用,可以使用系统权限。
注:除了
android.uid.system
以外,sharedUserId
还可以指定其他值,详情说明可通过以下文章了解:https://www.cnblogs.com/scarecrow-blog/p/4876628.html (opens new window)
另外,如果你是 Android 系统定制开发者,你也可以将该 apk 文件放置到 /system/app
或 /system/priv-app
目录下,之后 系统烧录 或 OTA 升级时就会自动携带上该系统应用。
# 二、自动签名
经过上面的几个步骤后,我们确定能将自己开发好的系统应用成功安装到设备上,但是,你会发现签名环节太麻烦了,每次都要手动对 apk 进行签名,非常不利于开发和调试。当然,我们可以通过编写 gradle 脚本,在项目每次编译完成时,执行自动签名任务,但是这种方式并不是最优解,还有一种更简单的方式。
# 1、生成系统签名文件
我们知道,Android 项目中可以在 build.gradle
文件的 signingConfigs
域中配置我们的自定义签名文件(*.jks
),在配置好 buildTypes
之后,每次编译时 gradle 都会自动对 apk 进行签名,那这个签名文件(*.jks
)能不能是系统签名文件呢?答案是可以的。keytool-importkeypair
这个工具可以将系统签名信息(*.pk8
、*.pem
)导入到现有签名文件中(*.jks
),以下是它的仓库地址:
将仓库中的 keytool-importkeypair
文件下载下来,然后执行以下命令:
# 语法:
# keytool-importkeypair [-k keystore] [-p storepass] -pk8 pk8 -cert cert -alias key_alias
# 示例:
keytool-importkeypair -k platform.jks -p 123456 -pk8 platform.pk8 -cert platform.x509.pem -alias platform
注:上面示例中
platform.jks
是我自己创建的签名文件(不知道怎么创建签名文件的请自行 ChatGPT~),请根据你自己项目的实际情况,修改keystore、storepass、key_alias
等参数。
有一点需要特别注意,keytool-importkeypair
是 shell 脚本,在 Unix 系统下可以直接运行,但是在 Windows 系统下(cmd 或 PowerShell)是无法直接运行的,这时可以借助 Git Bash
来执行该命令。
注:如果你的
Git Bash
出现乱码,可以在右键->Options->Text,将Locale
设置为zh_CN
,Character set
设置为GBK
即可。如果还是乱码,那么改成UTF8
等其他字符集逐个试试吧~。
执行命令后,原本的 platform.jks
文件会被覆盖成拥有系统签名信息的签名文件了。
# 2、配置系统签名文件
接下来就跟普通应用开发一样,在 app 工程的 build.gradle
文件中配置一下签名就好了:
android {
...
signingConfigs {
platform {
storeFile file('../config/signing/platform.jks')
storePassword "123456"
keyAlias "platform"
keyPassword "123456"
}
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.platform
}
debug {
initWith(buildTypes.release)
debuggable true
minifyEnabled false
}
}
...
}
注:
initWith(otherBuildType)
可以让当前buildType
(debug)复制其他buildType
(release)的配置,减少相同配置的代码量。虽然这很方便,但是一定要注意,如果是 debug 构建类型,一定要指定其debuggable
为 true(因为 release 的debuggable
默认为 false),否则你的工程可能会无法进入 debug 模式。
至此,我们就可以像普通应用开发那样,愉快的开发系统应用了。
- 01
- Flutter - 危!3.24版本苹果审核被拒!11-13
- 02
- Flutter - 轻松搞定炫酷视差(Parallax)效果09-21
- 03
- Flutter - 轻松实现PageView卡片偏移效果09-08