apk系统签名记录

2023-07-31  本文已影响0人  smallestt

1、系统签名

当项目开发需要使用系统级别权限或frame层某些api时,普通应用是无法使用的,需要在AndroidManifest中配置sharedUserId:


20180628193621701.png
android:sharedUserId="android.uid.system"

配置完 android:sharedUserId="android.uid.system" 之后,此时的 app 是无法成功安装到设备的,控制台会提示 INSTALL_FAILED_SHARED_USER_INCOMPATIBLE,这是因为此时 app 已经被识别为系统应用,但是其签名信息却不是系统签名,于是无法通过系统检验。进行系统签名需要准备好如下几个文件:

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);
            }
        }
 
 
    }
}
上一篇下一篇

猜你喜欢

热点阅读