apk系統(tǒng)簽名記錄

1、系統(tǒng)簽名

當(dāng)項(xiàng)目開(kāi)發(fā)需要使用系統(tǒng)級(jí)別權(quán)限或frame層某些api時(shí),普通應(yīng)用是無(wú)法使用的,需要在AndroidManifest中配置sharedUserId:


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

配置完 android:sharedUserId="android.uid.system" 之后,此時(shí)的 app 是無(wú)法成功安裝到設(shè)備的,控制臺(tái)會(huì)提示 INSTALL_FAILED_SHARED_USER_INCOMPATIBLE,這是因?yàn)榇藭r(shí) app 已經(jīng)被識(shí)別為系統(tǒng)應(yīng)用,但是其簽名信息卻不是系統(tǒng)簽名,于是無(wú)法通過(guò)系統(tǒng)檢驗(yàn)。進(jìn)行系統(tǒng)簽名需要準(zhǔn)備好如下幾個(gè)文件:

  • platform.pk8:簽名證書(shū)
  • platform.x509.pem:簽名證書(shū)
  • signapk.jar:簽名工具
    注:我們是與Android系統(tǒng)廠商合作開(kāi)發(fā),以上文件為硬件廠商提供。

1.1 單獨(dú)簽名

將簽名文件和簽名工具、簽名apk放置同一目錄,定位到該目錄,使用如下命令:

java -jar signapk.jar platform.x509.pem platform.pk8 unsign.apk signed.apk

signed.apk就是生成已經(jīng)擁有系統(tǒng)簽名的apk

1.2 生成平臺(tái)platform.keystore文件

除了直接使用signapk.jar簽名外,還可以將簽名文件生成keystore文件,然后給apk進(jìn)行簽名。

1.2.1將pkcs8格式的私鑰轉(zhuǎn)化成pkcs12格式

openssl pkcs8 -in platform.pk8 -inform DER -outform PEM -out shared.priv.pem -nocrypt

1.2.2 將x509.pem公鑰轉(zhuǎn)換成pkcs12格式

openssl pkcs12 -export -in platform.x509.pem -inkey shared.priv.pem -out shared.pk12 -name test

這里會(huì)輸入密碼和確認(rèn)密碼,密碼是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

配置項(xiàng)目builde.gradle,在android區(qū)域下(與defaultConfig同級(jí))添加配置:

signingConfigs {
    release {
        storeFile file("../test")
        storePassword 'android'
        keyAlias 'test'
        keyPassword 'android'
    }
    debug {
        storeFile file("../test")
        storePassword 'android'
        keyAlias 'test'
        keyPassword 'android'
    }
}

2 代碼安裝

使用場(chǎng)景:版本更新

2.1 安裝方法

/*系統(tǒng)簽名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 注冊(cè)廣播,安裝成功后自啟

manifest文件下

 <!-- 注冊(cè)廣播 安裝包更新調(diào)起自啟 -->
<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())) {
                // 重新啟動(dòng)APP
                Intent intentToStart = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
                context.startActivity(intentToStart);
            }
        }
 
 
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容