1、系统签名
当项目开发需要使用系统级别权限或frame层某些api时,普通应用是无法使用的,需要在AndroidManifest中配置sharedUserId:
20180628193621701.png
android:sharedUserId="android.uid.system"
配置完 android:sharedUserId="android.uid.system" 之后,此时的 app 是无法成功安装到设备的,控制台会提示 INSTALL_FAILED_SHARED_USER_INCOMPATIBLE,这是因为此时 app 已经被识别为系统应用,但是其签名信息却不是系统签名,于是无法通过系统检验。进行系统签名需要准备好如下几个文件:
- platform.pk8:签名证书
- platform.x509.pem:签名证书
- signapk.jar:签名工具
注:我们是与Android系统厂商合作开发,以上文件为硬件厂商提供。
1.1 单独签名
将签名文件和签名工具、签名apk放置同一目录,定位到该目录,使用如下命令:
java -jar signapk.jar platform.x509.pem platform.pk8 unsign.apk signed.apk
signed.apk就是生成已经拥有系统签名的apk
1.2 生成平台platform.keystore文件
除了直接使用signapk.jar签名外,还可以将签名文件生成keystore文件,然后给apk进行签名。
1.2.1将pkcs8格式的私钥转化成pkcs12格式
openssl pkcs8 -in platform.pk8 -inform DER -outform PEM -out shared.priv.pem -nocrypt
1.2.2 将x509.pem公钥转换成pkcs12格式
openssl pkcs12 -export -in platform.x509.pem -inkey shared.priv.pem -out shared.pk12 -name test
这里会输入密码和确认密码,密码是android
1.2.3 生成platform.keystore
keytool -importkeystore -deststorepass android -destkeypass android -destkeystore test.jks -srckeystore shared.pk12 -srcstoretype PKCS12 -srcstorepass android -alias test
1.2.4 引入AndroidStudio
配置项目builde.gradle,在android区域下(与defaultConfig同级)添加配置:
signingConfigs {
release {
storeFile file("../test")
storePassword 'android'
keyAlias 'test'
keyPassword 'android'
}
debug {
storeFile file("../test")
storePassword 'android'
keyAlias 'test'
keyPassword 'android'
}
}
2 代码安装
使用场景:版本更新
2.1 安装方法
/*系统签名apk 使用pm安装*/
fun systemInstall(apkFile: File, finish: (() -> Unit)? = null) {
try {
if (apkFile.exists()) {
val cmd = "pm install -r " + apkFile.absolutePath
val runtime = Runtime.getRuntime()
val process = runtime.exec(cmd)
val errorInput = process.errorStream
val inputStream = process.inputStream
var bufferedReader = BufferedReader(InputStreamReader(inputStream))
var error = ""
var result = ""
var line = ""
while (bufferedReader.readLine().also { line = it } != null) {
result += line
}
bufferedReader = BufferedReader(InputStreamReader(errorInput))
while (bufferedReader.readLine().also { line = it } != null) {
error += line
}
Log.e("===>", result)
if (result == "Success") {
Log.e("===>", "install: Success")
} else {
Log.e("===>", "install: error$error")
}
finish?.invoke()
} else {
finish?.invoke()
}
} catch (e: IOException) {
e.printStackTrace()
finish?.invoke()
} catch (e: Exception) {
finish?.invoke()
}
}
2.2 注册广播,安装成功后自启
manifest文件下
<!-- 注册广播 安装包更新调起自启 -->
<receiver
android:name=".receiver.UpdateRestartReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REPLACED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
2.3 重启app
public class UpdateRestartReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_PACKAGE_REPLACED.equals(intent.getAction())) {
Uri data = intent.getData();
if (data != null && context.getPackageName().equals(data.getEncodedSchemeSpecificPart())) {
// 重新启动APP
Intent intentToStart = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
context.startActivity(intentToStart);
}
}
}
}
网友评论