webentwicklung-frage-antwort-db.com.de

Signieren Sie APK, ohne die Keystore-Informationen in build.gradle zu speichern

Ich versuche, den Signaturprozess so einzurichten, dass das Keystore-Kennwort und das Schlüsselkennwort nicht in der build.gradle - Datei des Projekts gespeichert werden.

Zur Zeit habe ich folgendes im build.gradle:

Android {
    ...
    signingConfigs {
        release {
            storeFile file("my.keystore")
            storePassword "store_password"
            keyAlias "my_key_alias"
            keyPassword "key_password"
        }
    }

    buildTypes {
        release {
            signingConfig signingConfigs.release            
        }
    }
}

Es funktioniert einwandfrei, aber ich darf nicht setze die Werte für storePassword und keyPassword in mein Repository. Ich würde es vorziehen, storeFile und keyAlias dort auch nicht zu setzen.

Gibt es eine Möglichkeit, den build.gradle So zu ändern, dass er Passwörter von einer externen Quelle erhält (wie eine Datei, die sich nur auf meinem Computer befindet)?

Und natürlich sollte der geänderte build.gradle Auf jedem anderen Computer verwendbar sein (auch wenn der Computer keinen Zugriff auf Passwörter hat).

Ich verwende Android Studio und in Mac OS X Maverics, wenn es darauf ankommt.

133
Bobrovsky

Das Schöne an Groovy ist, dass Sie Java Code frei mischen können und es ziemlich einfach ist, eine Schlüssel-/Wertdatei mit Java.util.Properties Einzulesen. Vielleicht gibt es einen noch einfacheren Weg idiomatisch Groovy, aber Java ist immer noch ziemlich einfach.

Erstellen Sie eine keystore.properties - Datei (in diesem Beispiel im Stammverzeichnis Ihres Projekts neben settings.gradle). Sie können sie jedoch beliebig ablegen:

storePassword=...
keyPassword=...
keyAlias=...
storeFile=...

Fügen Sie dies zu Ihrem build.gradle Hinzu:

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']
        }
    }
}
109
Scott Barta

Wenn Sie die Antwort von Scott Barta auf eine Weise anwenden möchten, die dem automatisch generierten Gradle-Code ähnlicher ist, können Sie alternativ ein keystore.properties Datei in Ihrem Projektstammordner:

storePassword=my.keystore
keyPassword=key_password
keyAlias=my_key_alias
storeFile=store_file  

und ändern Sie Ihren Gradle-Code zu:

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

    ...

}

Sie können diese Eigenschaftendatei im Stammverzeichnis Ihres Moduls speichern. Lassen Sie in diesem Fall einfach rootProject weg, und Sie können diesen Code so ändern, dass er mehrere Eigenschaftensätze für verschiedene Schlüsselspeicher und Schlüsselaliase enthält.

93
CurlyCorvus

Am einfachsten ist es, ein ~/.gradle/gradle.properties Datei.

Android_STORE_PASSWORD=hunter2
Android_KEY_PASSWORD=hunter2

Dann ist dein build.gradle Datei kann so aussehen:

Android {
    signingConfigs {
        release {
            storeFile file('yourfile.keystore')
            storePassword Android_STORE_PASSWORD
            keyAlias 'youralias'
            keyPassword Android_KEY_PASSWORD
        }
    }
    buildTypes {
        release {
            signingConfig signingConfigs.release
        }
    }
}
27
Dan Fabulich

Nach dem Lesen einiger Links:

http://blog.macromates.com/2006/keychain-access-from-Shell/http://www.thoughtworks.com/es/insights/blog/signing-open -Quelle-Android-Apps-ohne-Offenlegung-Passwörter

Da Sie Mac OS X verwenden, können Sie Ihre Passwörter über den Schlüsselbund-Zugriff speichern.

How to add password in Keychain Access

Dann in deinen Skripten:

/* 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]
}

Verwenden Sie wie folgt:

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
        }
    }
}
20
Jared Burrows

So mache ich es. Umgebungsvariablen verwenden

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

Die akzeptierte Antwort verwendet eine Datei, um zu steuern, welcher Schlüsselspeicher zum Signieren des APKs verwendet werden soll, das sich im selben Stammordner des Projekts befindet. Wenn wir vcs wie Git verwenden, kann dies eine schlechte Sache sein, wenn wir vergessen, die Eigenschaftendatei zum Ignorieren der Liste hinzuzufügen. Weil wir unser Passwort der Welt offenlegen werden. Die Probleme bestehen immer noch.

Anstatt die Eigenschaftendatei im selben Verzeichnis in unserem Projekt zu erstellen, sollten wir sie außerhalb erstellen. Wir machen es draußen, indem wir die Datei gradle.properties verwenden.

Hier die Schritte:

1.Bearbeiten oder erstellen Sie gradle.properties in Ihrem Stammprojekt und fügen Sie den folgenden Code hinzu. Denken Sie daran, den Pfad mit Ihrem eigenen Code zu bearbeiten:

AndroidProject.signing=/your/path/androidproject.properties  

2.Erstellen Sie androidproject.properties in/your/path/und fügen Sie den folgenden Code hinzu. Vergessen Sie nicht, /your/path/to/Android.keystore in Ihren Keystore-Pfad zu ändern:

STORE_FILE=/your/path/to/Android.keystore  
STORE_PASSWORD=yourstorepassword  
KEY_ALIAS=yourkeyalias  
KEY_PASSWORD=yourkeypassword  

3.Fügen Sie in Ihrem App-Modul build.gradle (nicht in Ihrem Projektstamm build.gradle) den folgenden Code hinzu, falls er nicht vorhanden ist, oder passen Sie ihn an:

signingConfigs {  
     release  
   }  
   buildTypes {  
   debug {  
     debuggable true  
   }  
   release {  
     minifyEnabled true  
     proguardFiles getDefaultProguardFile('proguard-Android.txt'), 'proguard-rules.pro'  
     signingConfig signingConfigs.release  
   }  
 }  

4.Fügen Sie den folgenden Code unter dem Code in Schritt 3 hinzu:

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

Dieser Code sucht nach der Eigenschaft AndroidProject.signing in gradle.properties von Schritt 1. Wenn die Eigenschaft gefunden wurde, wird der Eigenschaftswert als Dateipfad übersetzt, der auf androidproject.properties verweist, die wir in Schritt 2 erstellt haben. Dann wird der gesamte Eigenschaftswert daraus als Signaturkonfiguration für unser build.gradle verwendet.

Jetzt müssen wir uns nicht mehr um das Risiko kümmern, unser Keystore-Passwort preiszugeben.

Lesen Sie mehr unter Signing Android apk ohne Keystore-Informationen in build.gradle

Es ist möglich, ein vorhandenes Android Studio gradle-Projekt zu nehmen und es über die Befehlszeile zu erstellen/zu signieren, ohne Dateien zu bearbeiten. Dies macht es sehr praktisch, Ihr Projekt in der Versionskontrolle zu speichern, während Sie Ihre Schlüssel behalten und Passwörter sind getrennt und nicht in Ihrer build.gradle-Datei enthalten:

./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
6
Wayne Piekarski

Für diejenigen, die ihre Anmeldeinformationen in eine externe JSON-Datei schreiben möchten und lesen, dass ich vom gradle aus Folgendes getan habe:

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

Der Grund, warum ich mich für einen Dateityp .json Und nicht für einen Dateityp .properties (Wie in der akzeptierten Antwort) entschieden habe, ist, dass ich auch andere Daten (andere benutzerdefinierte Eigenschaften, die ich benötigte) speichern wollte Dieselbe Datei (my_project/credentials.json), und trotzdem muss gradle auch die Signaturinformationen aus dieser Datei analysieren.

6
SudoPlz

Diese Frage hat viele gültige Antworten erhalten, aber ich wollte meinen Code weitergeben, der für Bibliotheksbetreuer nützlich sein kann, weil er das Original verlässt build.gradle ganz sauber.

Ich füge dem Modulverzeichnis einen Ordner hinzu, den ich gitignore. Es sieht aus wie das:

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

keystore.jks und signing.properties sollte selbsterklärend sein. Und signing.gradle sieht aus wie das:

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]

Und das Original 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 ...
}

Wie Sie sehen, müssen Sie die buildTypes überhaupt nicht angeben. Wenn der Benutzer Zugriff auf ein gültiges signing -Verzeichnis hat, legt er es einfach im Modul ab und kann ansonsten eine gültige signierte Release-Anwendung erstellen es funktioniert nur für ihn wie es normalerweise tun würde.

3
Michał K

Sie können Kennwörter über die Befehlszeile anfordern:

...

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
  }

  ...
}

...

Diese Antwort erschien zuvor: https://stackoverflow.com/a/33765572/3664487

0
user2768