キーストアのパスワードとキーのパスワードがプロジェクトのbuild.gradle
ファイルに保存されないように署名プロセスを設定しようとしています。
現在、build.gradle
には次のものがあります。
Android {
...
signingConfigs {
release {
storeFile file("my.keystore")
storePassword "store_password"
keyAlias "my_key_alias"
keyPassword "key_password"
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}
それは完全に正常に動作しますが、私はしてはいけません私のリポジトリにstorePassword
とkeyPassword
の値を入れます。 storeFile
とkeyAlias
のどちらもそこに置かないことを希望します。
build.gradle
を変更して、何らかの外部ソース(私のコンピューターにのみ存在するファイルなど)からパスワードを取得する方法はありますか?
そしてもちろん、変更されたbuild.gradle
は他のコンピューターでも使用できるはずです(コンピューターがパスワードにアクセスできない場合でも)。
Android StudioおよびMac OS X Mavericsを使用している場合は、それが問題になります。
Groovyの素晴らしい点は、Javaコードを自由に混在させることができ、Java.util.Properties
を使用してキー/値ファイルを読み取るのが非常に簡単なことです。おそらく、慣用的なGroovyを使用するさらに簡単な方法がありますが、Javaはまだ非常に単純です。
keystore.properties
ファイルを作成します(この例では、プロジェクトのルートディレクトリにsettings.gradle
の隣にありますが、好きな場所に置くことができます。
storePassword=...
keyPassword=...
keyAlias=...
storeFile=...
これをbuild.gradle
に追加します:
allprojects {
afterEvaluate { project ->
def propsFile = rootProject.file('keystore.properties')
def configName = 'release'
if (propsFile.exists() && Android.signingConfigs.hasProperty(configName)) {
def props = new Properties()
props.load(new FileInputStream(propsFile))
Android.signingConfigs[configName].storeFile = file(props['storeFile'])
Android.signingConfigs[configName].storePassword = props['storePassword']
Android.signingConfigs[configName].keyAlias = props['keyAlias']
Android.signingConfigs[configName].keyPassword = props['keyPassword']
}
}
}
あるいは、自動生成されたgradleコードにより類似した方法でScott Bartaの答えを適用したい場合、プロジェクトのルートフォルダーにkeystore.properties
ファイルを作成できます。
storePassword=my.keystore
keyPassword=key_password
keyAlias=my_key_alias
storeFile=store_file
gradleコードを次のように変更します。
// Load keystore
def keystorePropertiesFile = rootProject.file("keystore.properties");
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
...
Android{
...
signingConfigs {
release {
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
}
}
...
}
このプロパティファイルをモジュールのルートに保存できます。その場合は、rootProject
を省略し、このコードを変更して、異なるキーストアとキーエイリアスのプロパティセットをいくつか持つこともできます。
最も簡単な方法は、~/.gradle/gradle.properties
ファイルを作成することです。
Android_STORE_PASSWORD=hunter2
Android_KEY_PASSWORD=hunter2
build.gradle
ファイルは次のようになります。
Android {
signingConfigs {
release {
storeFile file('yourfile.keystore')
storePassword Android_STORE_PASSWORD
keyAlias 'youralias'
keyPassword Android_KEY_PASSWORD
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}
いくつかのリンクを読んだ後:
http://blog.macromates.com/2006/keychain-access-from-Shell/http://www.thoughtworks.com/es/insights/blog/signing-open -source-Android-apps-without-disclosing-passwords
Mac OSXを使用しているため、キーチェーンアクセスを使用してパスワードを保存できます。
それからあなたのgradleスクリプトで:
/* Get password from Mac OSX Keychain */
def 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
}
//noinspection GroovyAssignabilityCheck
(stderr.toString().trim() =~ /password: '(.*)'/)[0][1]
}
次のように使用します:
getPassword(currentUser、 "Android_Store_Password")
/* Plugins */
apply plugin: 'com.Android.application'
/* Variables */
ext.currentUser = System.getenv("USER")
ext.userHome = System.getProperty("user.home")
ext.keystorePath = 'KEY_STORE_PATH'
/* Signing Configs */
Android {
signingConfigs {
release {
storeFile file(userHome + keystorePath + project.name)
storePassword getPassword(currentUser, "Android_STORE_PASSWORD")
keyAlias 'jaredburrows'
keyPassword getPassword(currentUser, "Android_KEY_PASSWORD")
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}
これが私のやり方です。環境変数を使用する
signingConfigs {
release {
storeFile file(System.getenv("KEYSTORE"))
storePassword System.getenv("KEYSTORE_PASSWORD")
keyAlias System.getenv("KEY_ALIAS")
keyPassword System.getenv("KEY_PASSWORD")
}
受け入れられた回答では、ファイルを使用して、プロジェクトの同じルートフォルダーにあるAPKの署名に使用するキーストアを制御します。 Git のような vcs を使用する場合、プロパティファイルを追加してリストを無視するのを忘れると、悪いことになる可能性があります。パスワードを世界に公開するからです。問題はまだ残っています。
代わりに、プロジェクト内の同じディレクトリにプロパティファイルを作成し、外部に作成する必要があります。 gradle.propertiesファイルを使用して外部に作成します。
ここで手順:
1.ルートプロジェクトでgradle.propertiesを編集または作成し、次のコードを追加します。忘れずに独自のパスを編集してください。
AndroidProject.signing=/your/path/androidproject.properties
2./your/path /にandroidproject.propertiesを作成し、次のコードを追加します。/your/path/to/Android.keystoreをキーストアパスに変更することを忘れないでください:
STORE_FILE=/your/path/to/Android.keystore
STORE_PASSWORD=yourstorepassword
KEY_ALIAS=yourkeyalias
KEY_PASSWORD=yourkeypassword
3.アプリモジュールbuild.gradle(プロジェクトルートbuild.gradleではありません)に、次のコードが存在しない場合は追加するか、調整します:
signingConfigs {
release
}
buildTypes {
debug {
debuggable true
}
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-Android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}
}
4.手順3のコードの下に次のコードを追加します。
if (project.hasProperty("AndroidProject.signing")
&& new File(project.property("AndroidProject.signing").toString()).exists()) {
def Properties props = new Properties()
def propFile = new File(project.property("AndroidProject.signing").toString())
if(propFile.canRead()) {
props.load(new FileInputStream(propFile))
if (props!=null && props.containsKey('STORE_FILE') && props.containsKey('STORE_PASSWORD') &&
props.containsKey('KEY_ALIAS') && props.containsKey('KEY_PASSWORD')) {
Android.signingConfigs.release.storeFile = file(props['STORE_FILE'])
Android.signingConfigs.release.storePassword = props['STORE_PASSWORD']
Android.signingConfigs.release.keyAlias = props['KEY_ALIAS']
Android.signingConfigs.release.keyPassword = props['KEY_PASSWORD']
} else {
println 'androidproject.properties found but some entries are missing'
Android.buildTypes.release.signingConfig = null
}
} else {
println 'androidproject.properties file not found'
Android.buildTypes.release.signingConfig = null
}
}
このコードは、step 1からgradle.propertiesでAndroidProject.signingプロパティを検索します。プロパティが見つかった場合、プロパティ値をstep 2で作成したandroidproject.propertiesを指すファイルパスとして変換します。次に、そこからのすべてのプロパティ値がbuild.gradleの署名設定として使用されます。
これで、キーストアのパスワードが公開されるリスクを心配する必要がなくなりました。
既存のAndroid Studio gradleプロジェクトを取得し、ファイルを編集せずにコマンドラインからビルド/署名することができます。これにより、build.gradleファイルではなく、キーとパスワードを別々に保ちながら、プロジェクトをバージョン管理に保存することができます。
./gradlew assembleRelease -Pandroid.injected.signing.store.file=$KEYFILE -Pandroid.injected.signing.store.password=$STORE_PASSWORD -Pandroid.injected.signing.key.alias=$KEY_ALIAS -Pandroid.injected.signing.key.password=$KEY_PASSWORD
資格情報を外部JSONファイルに入れて、それをgradleから読み取ることを探している人にとって、これは私がやったことです:
my_project/credentials.json:
{
"Android": {
"storeFile": "/path/to/acuity.jks",
"storePassword": "your_store_password",
"keyAlias": "your_Android_alias",
"keyPassword": "your_key_password"
}
}
my_project/Android/app/build.gradle
// ...
signingConfigs {
release {
def credsFilePath = file("../../credentials.json").toString()
def credsFile = new File(credsFilePath, "").getText('UTF-8')
def json = new groovy.json.JsonSlurper().parseText(credsFile)
storeFile file(json.Android.storeFile)
storePassword = json.Android.storePassword
keyAlias = json.Android.keyAlias
keyPassword = json.Android.keyPassword
}
...
buildTypes {
release {
signingConfig signingConfigs.release //I added this
// ...
}
}
}
// ...
}
.json
ファイルタイプではなく.properties
ファイルタイプを選択した理由は(受け入れられた回答のように)、他のデータ(必要な他のカスタムプロパティ)も同じものに保存したかったからです。ファイル(my_project/credentials.json
)、およびgradleがそのファイル内からの署名情報も解析します。
この質問には多くの有効な回答が寄せられましたが、ライブラリメンテナーに役立つ可能性のあるコードを共有したかったのは、元のbuild.gradle
を非常にきれいなままにします。
gitignore
というモジュールディレクトリにフォルダーを追加します。次のようになります。
/signing
/keystore.jks
/signing.gradle
/signing.properties
keystore.jks
およびsigning.properties
は自明であるべきです。 signing.gradle
は次のようになります。
def propsFile = file('signing/signing.properties')
def buildType = "release"
if (!propsFile.exists()) throw new IllegalStateException("signing/signing.properties file missing")
def props = new Properties()
props.load(new FileInputStream(propsFile))
def keystoreFile = file("signing/keystore.jks")
if (!keystoreFile.exists()) throw new IllegalStateException("signing/keystore.jks file missing")
Android.signingConfigs.create(buildType, {
storeFile = keystoreFile
storePassword = props['storePassword']
keyAlias = props['keyAlias']
keyPassword = props['keyPassword']
})
Android.buildTypes[buildType].signingConfig = Android.signingConfigs[buildType]
元のbuild.gradle
apply plugin: 'com.Android.application'
if (project.file('signing/signing.gradle').exists()) {
apply from: 'signing/signing.gradle'
}
Android {
compileSdkVersion 27
defaultConfig {
applicationId ...
}
}
dependencies {
implementation ...
}
ご覧のとおり、buildTypesを指定する必要はありません。ユーザーが有効なsigning
ディレクトリにアクセスできる場合、モジュールにそれを配置するだけで、有効な署名済みリリースアプリケーションをビルドできます。普通に彼のように機能します。
コマンドラインからパスワードをリクエストできます:
...
signingConfigs {
if (gradle.startParameter.taskNames.any {it.contains('Release') }) {
release {
storeFile file("your.keystore")
storePassword new String(System.console().readPassword("\n\$ Enter keystore password: "))
keyAlias "key-alias"
keyPassword new String(System.console().readPassword("\n\$ Enter keys password: "))
}
} else {
//Here be dragons: unreachable else-branch forces Gradle to create
//install...Release tasks.
release {
keyAlias 'dummy'
keyPassword 'dummy'
storeFile file('dummy')
storePassword 'dummy'
}
}
}
...
buildTypes {
release {
...
signingConfig signingConfigs.release
}
...
}
...
この回答は以前に登場しました: https://stackoverflow.com/a/33765572/3664487