在正常开发一个Android软件项目时,我们需要生成一个签名文件。具体实现方式可以参考:项目签名。但当我们开发一个系统级的app时,如果apk已经集成到系统中,再想重新安装新包测试时,可能会遇到安装不上的问题,提示签名不一致。这是因为系统在整体编译时需要整体进行系统签名。而当我们把新的apk往系统安装时,就会提示签名不一致,因为当前编译好的apk是应用签名,终端上的app是系统签名,二者不匹配,所以不能覆盖安装。
为了解决这个问题,我们需要将编译好的apk进行系统签名才可以安装。以下是总结的系统签名方法:
1. 前提准备
- build/target/product/security文件夹
- testkey:普通签名APK,默认情况下使用。
- platform:该APK完成一些系统的核心功能。经过对系统中存在的文件夹的访问测试,这种方式编译出来的APK所在进程的UID为system。
- shared:该APK需要和home/contacts进程共享数据。
- media:该APK是media/download系统中的一环。
- .pk8代表私钥,.x509.pem公钥,它们都是成对出现;
- testkey是作为android编译的时候默认的签名key,如果系统中的apk的Android.mk中没有设置LOCAL_CERTIFICATE的值,就默认使用testkey。
- android:sharedUserId=“android.uid.system”
2. 生成系统的keystore文件
根据上述前提准备,我们可以按照以下步骤生成系统的keystore文件:
1. 首先确保你已经有了签名工具(如jarsigner)和相应的证书(如testkey.pk8)。
2. 将证书导入到Android Studio中。在Android Studio的菜单栏中,选择“File” > “Project Structure”。在弹出的窗口中,选择“Modules” > “Signing Certs”。点击右侧的“+”按钮,选择证书文件(如testkey.pk8),并为其设置密码。点击“OK”保存设置。
3. 在项目的build.gradle文件中,添加签名配置。在android闭包内添加以下代码:
```groovy
android {
...
signingConfigs {
release {
storeFile file("path/to/your/keystore") // 这里填写你的keystore文件路径
storePassword "your_keystore_password" // 这里填写你的keystore密码
keyAlias "your_key_alias" // 这里填写你的key别名
keyPassword "your_key_password" // 这里填写你的key密码
}
}
...
}
```
4. 在项目的build.gradle文件中的application闭包内添加以下代码:
```groovy
android {
...
lintOptions {
checkReleaseBuilds false
}
...
}
```
5. 最后,同步Gradle并重新构建项目。新生成的apk将具有系统签名。
如果之前没有生成platform.pem文件,可以执行以下命令来生成:
```shell
openssl pkcs8 -inform DER -nocrypt -in platform.pk8 -out platform.pem
```
接下来,生成platform.p12文件,设置对应的密码和alias名(app签名使用到),可以使用以下命令:
```shell
openssl pkcs12 -export -in platform.x509.pem -out platform.p12 -inkey platform.pem -password pass:密码 -name 名称
```
要生成platform.jks(app使用的签名文件),可以使用keytool工具。首先启动keytool:
```shell
keytool -importkeystore -deststorepass 密码 -destkeystore ./platform.keystore -srckeystore ./platform.p12 -srcstoretype PKCS12 -srcstorepass 密码
```
然后,在build.gradle文件中配置signingConfigs,如下所示:
```groovy
signingConfigs {
release {
storeFile file('../platfrom.keystore')
storePassword '密码'
keyAlias '别名'
keyPassword '密码'
}
}
```