build.gradleにキーストア情報を入れずにAPKに署名する


152

キーストアパスワードとキーパスワードプロジェクトの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私のリポジトリインチ 私は入れていないことを好むだろうstoreFilekeyAliasのいずれかが。

build.gradle一部の外部ソースからパスワードを取得するようにを変更する方法はありますか(私のコンピューターにのみ存在するファイルなど)?

そしてもちろん、変更されたファイルbuild.gradleは他のコンピュータで使用できるはずです(コンピュータがパスワードにアクセスできない場合でも)。

Android StudioとMac OS X Mavericsを使用しています。


「そしてもちろん、変更されたbuild.gradleは(コンピュータとパスワードへのアクセス権を持っていなくても)他のコンピュータ上で使用可能でなければなりません」 -データがでない場合はbuild.gradle、あなたが以外の何かを持っている必要がありますbuild.gradleかどうか、これは、環境変数(1つの回答ごと)、プロパティファイル(別の回答ごと)、またはその他の手段に対する調整です。外に物を置きたくない場合はbuild.gradle、定義により、すべての署名情報が内部 にある必要がありbuid.gradleます。
CommonsWare 2013

2
@CommonsWareその通りです。ただし、build.gradle内に厳密に何かを置きたいとは言いませんでした。また、build.gradleが一部の外部ソース(自分のコンピューターにのみ存在するファイルなど)からパスワードを取得
Bobrovsky


回答:


120

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']
        }
    }
}

29
keystore.propertiesから引用符を削除する必要がありました
Jacob Tabak 2014年

6
プラグインバージョン0.9以降の署名付きバージョンは生成されません。signingConfigsブロックとbuildTypes.release.signingConfigアイテムをどうすればよいですか?それらを削除しますか?
フェルナンドガレゴ2014年

1
storeFileを任意の有効な値(例:)に設定storeFile file('AndroidManifest.xml')し、後でそれをオーバーライドすると、署名プロセスが行われるようです。
miracle2k 2014

5
ビルドすると、Error:(24, 0) Could not find property 'android' on root project 'RootProjectName'24行目がifブロックを含む行であるというエラーが発生します。apply plugin: 'com.android.application'ルートbuild.gradleに追加すると、ビルドも失敗します。何が悪いのですか?
PhilLab 2015年

2
これは2018年には機能しません。廃止する必要がありますか?エラーをスローしCould not get unknown property 'android' for root project
続け

106

または、自動生成されたGradleコードに類似した方法でスコットバルタの回答を適用する場合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、このコードを変更して、さまざまなキーストアとキーエイリアスに複数のプロパティセットを設定することもできます。


7
よく働く。私が使用if ( keystorePropertiesFile.exists() )してくださいファイルは、属性を取得してサインインしようしようとする前に存在であることを確認します。
Joshua Pinter 2017

そして.txtkeystore.propertiesファイルの最後に拡張子 を追加することを忘れないでください。
Levon Petrosyan 2018

11
ファイルに.txt拡張子を付ける必要はありませんkeystore.properties
Matt Zukowski、2018年

2
この情報のように見えますが、ここで追加されました- developer.android.com/studio/publish/...
ヴァディムコトフ

36

最も簡単な方法は、~/.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
        }
    }
}

1
〜/ .gradle / gradle.propertiesをgitignoreする必要がありますか?
vzhen 2017

完全な手順は、reactネイティブドキュメントにもあります。
Pencilcheck

23

いくつかのリンクを読んだ後:

http://blog.macromates.com/2006/keychain-access-from-shell/ http://www.thoughtworks.com/es/insights/blog/signing-open-source-android-apps-without-disclosing-パスワード

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
        }
    }
}

2
あなたの答えはMac OSXにのみ当てはまりますが、私は本当にそれが好きです!誰かがマルチプラットフォームサポートを実装する必要がある場合に備えて、指定した2番目のリンクには他のプラットフォームのバックアップソリューションが含まれていることに注意してください。
Delblanco 14

LinuxとWindowsにも同じソリューションを提供できますか?ありがとう。
Jay Mungara

18

これが私のやり方です。環境変数を使用する

  signingConfigs {
    release {
        storeFile file(System.getenv("KEYSTORE"))
        storePassword System.getenv("KEYSTORE_PASSWORD")
        keyAlias System.getenv("KEY_ALIAS")
        keyPassword System.getenv("KEY_PASSWORD")
    }

3
残念ながら、これはために作成されるシステム環境を必要とする各プロジェクト各コンピュータ。そうしないと、次のエラーが発生しますNeither path nor baseDir may be null or empty string. path='null'
Bobrovsky

@Bobrovskyこの質問への回答はわかっていますが、システム環境変数またはgradle.propertiesファイルを使用できます。おそらく、gradle.propertiesファイルを使用する必要があります。複数のプロジェクトに使用できます。
Jared Burrows、2014

3
コマンドラインからAndroid Studioを実行しない限り、これはMacOSXでは機能しません。
Henrique de Sousa

上記すべてに同意します。私は同じ構成で、Androidスタジオでこれをコンパイルできません。これを機能させるには、コマンドラインから実行する必要があります。Android Studioで実行するときにこれらの行にコメントを付ける必要がないように、より良い方法を探しています。
Sayooj Valsan 2016

@Bobrovsky:Windowsで動作しますか?システム環境でこれらすべてについて言及する必要がありますか?
DKV 2018

12

既存の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

9

承認された回答では、ファイルを使用して、プロジェクトの同じルートフォルダーにある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  
   }  
 }  

ステップ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  
     }  
   }  

このコードは、手順1のgradle.propertiesでAndroidProject.signingプロパティを検索します。プロパティが見つかった場合は、プロパティ値を、手順2で作成したandroidproject.propertiesを指すファイルパスとして変換します。次に、それからのすべてのプロパティ値がbuild.gradleの署名設定として使用されます。

これで、キーストアのパスワードを公開するリスクを心配する必要がなくなりました。

build.gradleにキーストア情報を入力せずにAndroid APK署名するで詳細を読む


これでうまくいきます。storeFile file(System.getenv( "KEYSTORE"))を使用している理由を知るため
DKV

9

資格情報を外部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で解析するためです。そのファイル内からも情報に署名します。


私にとって最良の解決策のようです。
Aspiring Dev

4

この質問は、多くの有効な答えを受けているが、私はのために有用である可能性が私のコード共有したいと思ったライブラリのメンテナが、それはので、オリジナルを残しbuild.gradle、非常にきれい

フォルダーをモジュールディレクトリに追加しますgitignore。次のようになります。

/signing
    /keystore.jks
    /signing.gradle
    /signing.properties

keystore.jkssigning.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ディレクトリにアクセスできる場合は、モジュールに配置するだけで、有効な署名付きリリースアプリケーションを構築できます。それ以外の場合は、次のように機能します通常はそうなります。


私はこのソリューションが本当に好きです。ただし、ブロックのapply from後に来る必要があることに注意してくださいandroid
mgray88

0

コマンドラインからパスワードを要求できます。

...

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


このリンクで質問に答えることができますが、回答の重要な部分をここに含め、参照用のリンクを提供することをお勧めします。リンクされたページが変更されると、リンクのみの回答が無効になる可能性があります。- レビューから
mkobit

1
@mkobit、これはスタックオーバーフローのコンテンツへのリンクです!もちろん、リンクされたコンテンツをコピーして貼り付けることもできますが、その場合はコンテンツが重複します。したがって、私は仮定し、私が間違っている場合は修正します。リンクを投稿することが最善の解決策です。「リンクされたページの変更」という主張は、ここのコンテンツも変更される可能性があるという理由で却下されるべきです。私はあなたの解決策に対して削除することを強くお勧めします!リンクされたコンテンツが優れたソリューションを提供するからです。
user2768 2015年

ええと、問題はこれがまだ「リンクのみ」の答えであることだと思います。解決策は、コメントとして投稿するか、質問に重複としてフラグを立てるか、問題に対処する新しい回答をここに書き込むことだと思います。
mkobit 2015年

場合によっては、「リンクのみ」の回答が推奨されます。それにもかかわらず、私はあなたの助言と複製された内容に従いました。(一部のコンテンツは更新される可能性がありますが、残りのコンテンツは更新されない可能性があるため、重複したコンテンツは明らかに問題があります。)
user2768

確かに、私は答えを更新したばかりで、重複したコンテンツが問題を引き起こしています!リンクのみの回答に対するポリシーがある場合は、そのようなコーナーケースを検討するように適応させる必要があります。
user2768 2015年

0

私のパスワードにはドル記号$の特殊文字が含まれており、gradle.propertiesファイルでエスケープする必要がありました。その後、署名はうまくいきました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.