AndroidStdioで署名付きreleaseビルド時・インストール時の署名エラーを解決する
結論
以下手順でAndroid Studioでも署名付きビルドイメージを使うことができました。
- 署名などのシークレットを定義するファイルを作成する
- 定義したファイルをbuild.gradle.ktsでよみこむ
- 読み込んだ値を使い、署名を設定する
詳しくは以下に書いていきます。
はじめに
android studioでアプリをreleaseビルドしてエミュレーターにインストールしようとしたところエラーになってしまった。
The application could not be installed: INSTALL_PARSE_FAILED_NO_CERTIFICATES APK signature verification failed. List of apks: [0] '/Users/xxxxxxxx/hoge/app/build/intermediates/extracted_apks/release/extractApksFromBundleForRelease/base-en.apk' [1] '/Users/xxxxxxxx/hoge/app/build/intermediates/extracted_apks/release/extractApksFromBundleForRelease/base-arm64_v8a.apk' [2] '/Users/xxxxxxxx/hoge/app/build/intermediates/extracted_apks/release/extractApksFromBundleForRelease/base-xxhdpi.apk' [3] '/Users/xxxxxxxx/hoge/app/build/intermediates/extracted_apks/release/extractApksFromBundleForRelease/base-master.apk'
NO_CERTIFICATES
とあるので、署名に問題があるのは明らかです。
記載しない事
- 署名の作り方
- 署名付きビルドのやり方
環境
$ ./gradlew --version
------------------------------------------------------------
Gradle 8.11.1
------------------------------------------------------------
Build time: 2024-11-20 16:56:46 UTC
Revision: 481cb05a490e0ef9f8620f7873b83bd8a72e7c39
Kotlin: 2.0.20
Groovy: 3.0.22
Ant: Apache Ant(TM) version 1.10.14 compiled on August 16 2023
Launcher JVM: 17.0.12 (JetBrains s.r.o. 17.0.12+1-b1207.37)
Daemon JVM: /Users/xxxxxxxx/Library/Java/JavaVirtualMachines/jbr-17.0.12/Contents/Home (no JDK specified, using current Java home)
OS: Mac OS X 15.4.1 aarch64
今ある情報
ビルドしたapiをバラして署名を更新している。
apkをコマンドラインで署名付きにして使うという感じの情報が多い。
でももっと楽したい!
対策
署名情報をAndroid Studio で設定することができるので、設定後にビルドすればインストールできる。
AndroidStudioで署名情報を設定する方法
後述のgit管理の問題で本方法は実際には使えないが、署名の動作確認するに当たり使うことがあるかも。
Project Structureを開く
Signing Configsを設定する
これでbuild.gradle.ktsに設定がされる。
慣れればbuild.gradle.ktsに直接設定をすればいいだけ。
とりあえずこれでビルドはできるようになる。
ただ、git管理する必要があるbuild.gradle.kts
にシークレットが記載されてしまうのは困る。
またgradle.properties
もgit管理対象なのでこちらにも書けない。
署名情報をgit管理しない方法
署名情報をプロジェクトルートにあるlocal.propertiesに記載する
android studioで自動生成されるファイルで最初にsdk.dirが記載されている。
ここにシークレットを追記する。
シークレットのイメージ
内容はシークレット作成時に自分で指定したもの。
sdk.dir=/Users/xxxxxxxx/Library/Android/sdk
signing.keyAlias = キーエイリアス
signing.storeFile = /Users/xxxxxxxx/anrdoid-upload-key/キーストア.jks
signing.storePassword = キーストアパスワード
signing.keyPassword = キーパスワード
シークレットをbuild.gradle.ktsに反映する
以下の設定を記載します。
loadProperties関数でlocal.propertiesを読み込んで、signingConfigsでそれぞれ設定しています。
// Kotlinの拡張関数を使用してプロパティファイルを読み込む
fun loadProperties(filename: String): Map<String, String> {
val properties = mutableMapOf<String, String>()
val file = rootProject.file(filename)
if (file.exists()) {
file.reader().use { reader ->
reader.buffered().forEachLine { line ->
if (!line.startsWith("#") && line.contains("=")) {
val (key, value) = line.split("=", limit = 2)
properties[key.trim()] = value.trim()
}
}
}
}
return properties
}
android {
// 署名情報をreleaseビルドに追加
signingConfigs {
create("release") {
val localProperties = loadProperties("local.properties")
storeFile = localProperties["signing.storeFile"]?.toString()?.let { file(it) }
storePassword = localProperties["signing.storePassword"]?.toString()
keyAlias = localProperties["signing.keyAlias"]?.toString()
keyPassword = localProperties["signing.keyPassword"]?.toString()
}
}
// 署名情報をログに出力
tasks.register("printSigningInfo") {
doLast {
println("Release signing config:")
println("storeFile: ${android.signingConfigs.getByName("release").storeFile}")
println("storePassword: ${android.signingConfigs.getByName("release").storePassword}")
println("keyAlias: ${android.signingConfigs.getByName("release").keyAlias}")
println("keyPassword: ${android.signingConfigs.getByName("release").keyPassword}")
}
}
// ビルドタイプに署名設定を追加
buildTypes {
getByName("release") {
isMinifyEnabled = true
proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
signingConfig = signingConfigs.getByName("release")
}
}
// ...other settings
なお、署名情報が正しいかどうかの確認のためにprintSigningInfo
を追加してみました。
以下のように使用できます。
設定ができていない場合はnullになります。
$ ./gradlew printSigningInfo --no-configuration-cache
> Configure project :app
w: file:///Users/xxxx/hoge/app/build.gradle.kts:115:5: 'packagingOptions(Packaging.() -> Unit): Unit' is deprecated. Renamed to packaging
> Task :app:printSigningInfo
Release signing config:
storeFile: ストアファイル.jks"
storePassword: "ストアパスワード"
keyAlias: "キーエイリアス"
keyPassword: "キーパスワード"
BUILD SUCCESSFUL in 1s
1 actionable task: 1 executed
以上です!
Discussion