LoginSignup
80

More than 5 years have passed since last update.

Android Studio(Gradle)でapkファイルを作成する時にstorePassword/keyAlias/keyPasswordの指定方法をいくつか検証してみた。

Last updated at Posted at 2014-08-02

前提条件

今回対象とした環境

  • Android Studio v0.8.2
  • Gradle 1.12 (Android Studioに内包されているもの)
  • OS X Mavericks 10.9.4
  • 利用しているプロジェクトはAndroid Studioが生成したHello worldプロジェクト
  • ファイルの有無確認などのエラーハンドリングは全て省略
  • Gradleを実行する時のコマンドは全てgradlewがある階層で以下をタイプしています
./gradlew clean assembleRelease

Android StudioのGUI

一番基本的な方法としてGUIを利用する。

Build > Generate Signed APK... > Generate Signed APK Wizardを淡々とこなしていく。

新規でアプリを作成した場合、まずはこの方法でkeystoreファイルを作成する。

app/build.gradleに直接書き込む

ここからGradleを使ってみる。
まずは直接build.gradleに書き込む方法。

app/build.gradle
plugin: 'com.android.application'

android {
    compileSdkVersion 20
    buildToolsVersion "20.0.0"

    defaultConfig {
        applicationId "com.shiraji.myapplication"
        minSdkVersion 14
        targetSdkVersion 20
        versionCode 1
        versionName "1.0"
    }

    signingConfigs {
        release {
            storeFile file("${System.getenv('HOME')}/release.jks")
            storePassword "storePassword"
            keyAlias "keyAlias"
            keyPassword "keyPassword"
        }
    }

    buildTypes {
        release {
            runProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

            signingConfig signingConfigs.release
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
}

buildTypeのreleaseにsigningConfig signingConfigs.releaseを追加することを忘れない。
個人で開発しているのであれば、この方法が一番手っ取り早い。

gradle.propertiesから読み込む

gradle.propertiesはデフォルトのpropertyファイルです。このファイルに定義しておけば簡単に読み込むことが出来ます。

gradle.properties
KEY_ALIAS=keyAlias
KEY_PASSWORD=keyPassword
STORE_PASSWORD=storePassword
app/build.gradle
apply plugin: 'com.android.application'

android {
    compileSdkVersion 20
    buildToolsVersion "20.0.0"

    defaultConfig {
        applicationId "com.shiraji.myapplication"
        minSdkVersion 14
        targetSdkVersion 20
        versionCode 1
        versionName "1.0"
    }

    signingConfigs {
        release {
            storeFile file("${System.getenv('HOME')}/release.jks")
            storePassword STORE_PASSWORD
            keyAlias KEY_ALIAS
            keyPassword KEY_PASSWORD
        }
    }

    buildTypes {
        release {
            runProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

            signingConfig signingConfigs.release
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
}

gradle.propertiesのkeyをそのままbuild.gradleで使えるので、シンプルに書けます。

gradle.propertiesファイルを.gitignoreに入れ、このファイルを共有しないようにすれば、特定のPCからのみリリース作業が出来るようになります。
個人の開発であれば便利ですが、チーム開発であったり、複数人がリリース作業が出来る状態になるのであれば、gradle.propertiesファイルの扱いをどうするかを考える必要が出てきます。

環境変数から読み込む

環境変数に値を設定した結果

% env | egrep "key|Pass"
KEY_ALIAS=keyAlias
KEY_PASSWORD=keyPassword
STORE_PASSWORD=storePassword
app/build.gradle
apply plugin: 'com.android.application'

android {
    compileSdkVersion 20
    buildToolsVersion "20.0.0"

    defaultConfig {
        applicationId "com.shiraji.myapplication"
        minSdkVersion 14
        targetSdkVersion 20
        versionCode 1
        versionName "1.0"
    }

    signingConfigs {
        release {
            storeFile file("${System.getenv('HOME')}/release.jks")
            storePassword System.getenv('STORE_PASSWORD')
            keyAlias System.getenv('KEY_ALIAS')
            keyPassword System.getenv('KEY_PASSWORD')
        }
    }

    buildTypes {
        release {
            runProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

            signingConfig signingConfigs.release
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
}

signingConfigsのreleaseでSystem.getenv(String)で値を設定。

プロパティファイルから読み込む

$HOME/myapp.signconfig.gradle
storePassword=storePassword
keyAlias=keyAlias
keyPassword=keyPassword
app/build.gradle
apply plugin: 'com.android.application'

android {
    compileSdkVersion 20
    buildToolsVersion "20.0.0"

    defaultConfig {
        applicationId "com.shiraji.myapplication"
        minSdkVersion 14
        targetSdkVersion 20
        versionCode 1
        versionName "1.0"
    }

    signingConfigs {
        release {
            def signFile = file("${System.getenv('HOME')}/myapp.signconfig.gradle")
            def signingProps = new Properties()
            signingProps.load(new FileInputStream(signFile))

            storeFile file("${System.getenv('HOME')}/release.jks")
            storePassword signingProps['storePassword']
            keyAlias signingProps['keyAlias']
            keyPassword signingProps['keyPassword']
        }
    }

    buildTypes {
        release {
            runProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

            signingConfig signingConfigs.release
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
}

signingConfigsのreleaseで$HOME直下にあるプロパティファイルを参照し、それぞれのプロパティ値を設定。

コンソールから直接入力

app/build.gradle
apply plugin: 'com.android.application'

gradle.taskGraph.whenReady { taskGraph ->
    if(taskGraph.hasTask(':app:assembleRelease')) {
        def storePasswordValue = new String(System.console().readPassword("Enter store password: "))
        def keyAliasValue = new String(System.console().readLine("Enter key alias: "))
        def keyPasswordValue = new String(System.console().readPassword("Enter key password: "))

        android.signingConfigs.release.storePassword = storePasswordValue
        android.signingConfigs.release.keyAlias = keyAliasValue
        android.signingConfigs.release.keyPassword = keyPasswordValue
    }
}

android {
    compileSdkVersion 20
    buildToolsVersion "20.0.0"

    defaultConfig {
        applicationId "com.shiraji.myapplication"
        minSdkVersion 14
        targetSdkVersion 20
        versionCode 1
        versionName "1.0"
    }

    signingConfigs {
        release {
            storeFile file("${System.getenv('HOME')}/release.jks")
            storePassword ""
            keyAlias ""
            keyPassword ""
        }
    }

    buildTypes {
        release {
            runProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

            signingConfig signingConfigs.release
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
}

taskGraphを利用して、configurationフェーズ後に:app:assembleReleaseが存在していた場合のみコンソールでパスワードなどの入力を求めるようにしてあります。
signingConfingsでやってしまうと、別に:app:assembleReleaseではないタスクを実行したときもコンソールで入力を求めてしまうためです。

signingConfingsでstorePasswordなどに空文字を設定しているのは、これをしないと証明書つきのapkを作成してくれないためです。

キーチェーンを使う

キーチェーンに3種類の値を設定する。

app/build.gradle
apply plugin: 'com.android.application'

android {
    compileSdkVersion 20
    buildToolsVersion "20.0.0"

    defaultConfig {
        applicationId "com.shiraji.myapplication"
        minSdkVersion 14
        targetSdkVersion 20
        versionCode 1
        versionName "1.0"
    }

    signingConfigs {
        release {
            storeFile file("${System.getenv('HOME')}/release.jks")
            storePassword getPassword("shiraji", "storePassword")
            keyAlias getPassword("shiraji", "keyAlias")
            keyPassword getPassword("shiraji", "keyPassword")
        }
    }

    buildTypes {
        release {
            runProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

            signingConfig signingConfigs.release
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
}

String getPassword(String currentUser, String keyChain) {
    def stdout = new ByteArrayOutputStream()
    def stderr = new ByteArrayOutputStream()
    exec {
        commandLine 'security', '-q', 'find-generic-password', '-a', currentUser, '-gl', keyChain
        standardOutput = stdout
        errorOutput = stderr
        ignoreExitValue true
    }
    (stderr.toString().trim() =~ /password: "(.*)"/)[0][1]
}

getPassword(String, String)が重要で、execを利用してキーチェーンを叩く。
最初に許可をするかのポップアップが出るので、注意。

個人的な感想

ネタ的な方法も検証してみたけど、案外全て使えるのでは?と思った。
個人で開発しているなら、直接書き込むことをおすすめします。
チーム開発の場合、パスワードへのアクセス権限の有無があったりしますので、最適な方法を検証して下さい。上記の手法の組み合わせを行うといいと思います。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
80