Comment créer un fichier apk signé en utilisant Gradle?


514

Je voudrais que ma génération Gradle crée un fichier apk signé avec Gradle.

Je ne sais pas si le code est correct ou si je manque un paramètre en le faisant gradle build?

Voici une partie du code dans mon fichier Gradle:

android {
    ...
    signingConfigs {
          release {
              storeFile file("release.keystore")
              storePassword "******"
              keyAlias "******"
              keyPassword "******"
         }
     }
}

La version Gradle se termine avec succès, et dans mon build/apkdossier, je ne vois que les fichiers ...-release-unsigned.apket ...-debug-unaligned.apk.

Des suggestions sur la façon de résoudre ce problème?



signer avec la version v1 (signature du pot) ou v2 (signature apk complète) du fichier gradle? solution ici: stackoverflow.com/questions/57943259/…
user1506104

Réponses:


430

Moyen plus simple que les réponses précédentes:

Mettez cela dans ~/.gradle/gradle.properties

RELEASE_STORE_FILE={path to your keystore}
RELEASE_STORE_PASSWORD=*****
RELEASE_KEY_ALIAS=*****
RELEASE_KEY_PASSWORD=*****

Modifiez votre app/build.gradle, et ajoutez ceci dans le android {bloc de code:

...    
signingConfigs {

   release {
       storeFile file(RELEASE_STORE_FILE)
       storePassword RELEASE_STORE_PASSWORD
       keyAlias RELEASE_KEY_ALIAS
       keyPassword RELEASE_KEY_PASSWORD

       // Optional, specify signing versions used
       v1SigningEnabled true
       v2SigningEnabled true
   }
}

buildTypes {
        release {
            signingConfig signingConfigs.release
        }
}
....

Ensuite, vous pouvez exécuter gradle assembleRelease


Voir également la référence du signingConfigsGradle DSL


12
Meilleure méthode si vous me demandez. N'enregistre rien dans mon dossier de projet / SVN et je peux extraire 10 versions de mes projets sans avoir à se soucier des clés.
Frank

8
Si vous utilisez gradlew sous Windows, vous devez vous assurer que GRADLE_USER_HOME est défini comme une variable d'environnement pour que cela fonctionne. Je l'ai placé dans un répertoire au-dessus du répertoire de mon projet et y ai placé mon magasin de clés. Le chemin d'accès à votre fichier de clés dans gradle.properties doit utiliser des barres obliques (/) ou des barres obliques inverses doubles (\\), pas des barres obliques inverses simples Windows. Pour créer un fichier de clés à partir de l'invite de commandes Windows, voir stackoverflow.com/questions/3997748/how-can-i-create-a-keystore
Anachronist

3
Le chemin est-il relatif à l'emplacement du fichier build.gradle ou relatif au répertoire racine des machines?
Prem

1
@Prem, file()suppose toujours des chemins relatifs. Utilisez-le new File(path)si vous souhaitez qu'il soit traité comme absolu.
ars-longa-vita-brevis

4
Cela a fonctionné pour moi et le plus simple. Dans gradle.properties, spécifiez storeFile par rapport à votre module build.gradle comme RELEASE_STORE_FILE = .. / mykeystore. N'ajoutez pas de citations sinon Gradle modifie le chemin
Lakshman Chilukuri

263

J'ai réussi à le résoudre en ajoutant ce code et en construisant avec gradle build:

android {
    ...
    signingConfigs {
        release {
            storeFile file("release.keystore")
            storePassword "******"
            keyAlias "******"
            keyPassword "******"
        }
    }
    buildTypes {
        release {
            signingConfig signingConfigs.release
        }
    }
}

Cela génère un fichier apk de version signée.


33
Existe-t-il un moyen de me demander les mots de passe? Ou d'autres suggestions pour garder les mots de passe hors de mes dépôts git?
user672009

3
J'édite mon build.gradle pour qu'il ressemble au vôtre, mais l'exécution de "Construit> Générer un fichier APK signé ..." me donne toujours cette boîte de dialogue ("Voir le guide de l'utilisateur Gradle pour plus d'informations." Etc.) et aucun fichier APK.
Semanticer

3
@Semanticer Execute gradle buildou gradlew builddans la commande Terminal / Prompt
Phillip Kamikaze

12
@ user672009 vous pouvez mettre des mots de passe dans un fichier de propriétés et l'exclure des dépôts avec .gitignore. Vous pouvez voir ce lien. gist.github.com/gabrielemariotti/6856974
Gabriele Mariotti

1
@GabrieleMariotti Cela laisse encore un référentiel incomplet. Une meilleure façon serait de créer un squelette signature.properties et après avoir validé l'émission "git update-index --assume-unchanged Signature.properties". Cependant, cela empêche les modifications Futura d'être validées. Quelque chose comme la première option suggérée par sdqali semble encore mieux.
user672009

67

Notez que le script de @ sdqali demandera (au moins lors de l'utilisation de Gradle 1.6) le mot de passe chaque fois que vous invoquerez une tâche Gradle. Comme vous n'en avez besoin que lorsque vous faites gradle assembleRelease(ou similaire), vous pouvez utiliser l'astuce suivante:

android {
    ...
    signingConfigs {
        release {
            // We can leave these in environment variables
            storeFile file(System.getenv("KEYSTORE"))
            keyAlias System.getenv("KEY_ALIAS")

            // These two lines make gradle believe that the signingConfigs
            // section is complete. Without them, tasks like installRelease
            // will not be available!
            storePassword "notYourRealPassword"
            keyPassword "notYourRealPassword"
        }
    }
    ...
}

task askForPasswords << {
    // Must create String because System.readPassword() returns char[]
    // (and assigning that below fails silently)
    def storePw = new String(System.console().readPassword("Keystore password: "))
    def keyPw  = new String(System.console().readPassword("Key password: "))

    android.signingConfigs.release.storePassword = storePw
    android.signingConfigs.release.keyPassword = keyPw
}

tasks.whenTaskAdded { theTask -> 
    if (theTask.name.equals("packageRelease")) {
        theTask.dependsOn "askForPasswords"
    }
}

Notez que j'ai également dû ajouter les éléments suivants (sous Android) pour que cela fonctionne:

buildTypes {
    release {
        signingConfig signingConfigs.release
    }
}

Après avoir implémenté cela, installReleasedisparu de la liste des tâches ... Pourquoi?
Kaarel

1
@caspase J'aimerais avoir pris votre commentaire sur ces faux "storePassword" et "keyPassword" plus au sérieux. Sans initialiser ces propriétés ("" par exemple) le * -release.apk signé n'est pas créé, aucune erreur ne s'affiche et vous êtes complètement perplexe avec juste le * -release-unsigned.apk dans votre répertoire PROJECT_NAME / build / apk / . Man ...: /
vizZ

Merci pour la note sur l'ajout de signatureConfig sous buildTypes -> Release. Cela a résolu la signature automatisée pour moi!
mm2001

1
J'ai créé un plugin Gradle simple qui demande des mots de passe lors de la construction de la version apk (en utilisant la méthode décrite dans cet article, mais vous n'aurez pas besoin de définir de faux storePassword et keyPassword). Il est également disponible en maven central. github.com/alexvasilkov/AndroidGradleSignPlugin
Alex Vasilkov

C'est bien. Attention, la variable d'environnement KEYSTOREdoit être définie même pour les builds de débogage et pour la "synchronisation gradle" dans Android Studio, sinon cela donnera une erreur sur le chemin étant nul.
Jerry101

63

Si vous souhaitez éviter de coder en dur votre fichier de clés et votre mot de passe dans build.gradle , vous pouvez utiliser un fichier de propriétés comme expliqué ici: GESTION DES CONFIGURATIONS DE SIGNATURE AVEC GRADLE

Fondamentalement:

1) créez un fichier myproject.properties dans / home/[usernameername//signing avec un tel contenu:

keystore=[path to]\release.keystore
keystore.password=*********
keyAlias=***********
keyPassword=********

2) créez un fichier gradle.properties (peut-être à la racine de votre répertoire de projet) avec le contenu:

MyProject.properties=/home/[username]/.signing/myproject.properties

3) faites-y référence dans votre build.gradle comme ceci:

    if(project.hasProperty("MyProject.properties")
        && new File(project.property("MyProject.properties")).exists()) {

    Properties props = new Properties()
    props.load(new FileInputStream(file(project.property("MyProject.properties"))))

    signingConfigs {
        release {
            storeFile file(props['keystore'])
            storePassword props['keystore.password']
            keyAlias props['keyAlias']
            keyPassword props['keyPassword']
        }
    }
}

1
Fonctionne très bien! Je vous remercie. Ce code doit être ajouté avant la section buildTypes {} et la section doit déclarer la signatureConfig signatureConfigs.release comme normale.
theczechsensation

Enfin, j'ai trouvé une solution à ce problème. La seule chose qui m'a vraiment aidé! Cela devrait être la réponse acceptée ...
devnull69

39

Signature automatique des applications avec Gradle lors de l'utilisation de git

Il est étonnant de voir combien de façons compliquées de le faire. Voici ma propre voie, où j'essaie d'adhérer à la propre recommandation de Google . Cependant, leur explication n'est pas entièrement claire, donc je vais décrire la procédure pour Linux en détail.


La description:

Les instructions par défaut de Google pour signer automatiquement une application pendant la génération, sans conserver les mots de passe et les fichiers de signature dans le chemin de développement de votre application (GIT), sont plutôt obscures. Voici les instructions étape par étape clarifiées sur la façon de procéder.

Hypothèses initiales:

Vous avez une application appelée « MyApp » dans un répertoire donné par le chemin suivant: $HOME/projects/mydev/MyApp. Cependant, le répertoire MyApp est utilisé et contrôlé avec GIT.

entrez la description de l'image ici

Problème

Nous ne voulons évidemment pas avoir nos fichiers de signature ou de mot de passe n'importe où dans le répertoire contrôlé par GIT, même si nous sommes très capables d'utiliser .gitignoreetc., c'est toujours trop risqué et facile de faire une erreur. Nous voulons donc que notre fichier de clés et nos fichiers de signature soient à l'extérieur.

Solution

Nous devons faire trois (3) choses:

  1. Créer un fichier de mots de passe à utiliser par Android Studio
  2. Créer un fichier de clés de signature
  3. Modifiez le build.gradlefichier de module pour utiliser (1) et (2).

Pour cet exemple, nous nommons les deux fichiers:

  1. keystore.properties
  2. MyApp-release-key.jks

Nous pouvons mettre ces deux fichiers ici:

cd $HOME/projects/mydev/

(1) Créez le fichier de mots de passe du magasin de clés

Le premier fichier contient les mots de passe en texte clair utilisés dans; et les chemins d'accès au fichier de clé de libération dans (2). Commencez par remplir ceci, car cela facilitera une opération de copier-coller pour l'étape suivante.

cd $HOME/projects/mydev/

Modifier keystore.propertiespour que son contenu soit:

storePassword=myStorePassword
keyPassword=mykeyPassword
keyAlias=myKeyAlias
storeFile=myStoreFileLocation

La seule partie délicate ici, c'est le myStoreFileLocation. Il s'agit du chemin tel qu'il apparaît dans le build.gradlefichier de module lors de la génération. Cela signifie généralement une voie similaire et par rapport à: $HOME/projects/mydev/MyApp/app/build.gradle. Donc, pour pointer vers le MyApp-release-key.jks fichier, ce que nous devons mettre ici est:

../../../MyApp-release-key.jks

Ici, nous avons également choisi l'alias "myapp" pour la clé. Ensuite, le fichier final devrait ressembler à:

storePassword=myStorePassword
keyPassword=mykeyPassword
keyAlias=myapp
storeFile=../../../MyApp-release-key.jks

(2) Créez le fichier de signature

Le deuxième fichier est généré automatiquement lorsque vous créez la clé de signature. Si vous n'avez aucune autre application et qu'il s'agit de votre seul magasin de clés, créez le fichier avec:

cd $HOME/projects/mydev/
keytool -genkeypair -v -keystore MyApp-release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias myapp

Cela vous demandera deux mots de passe et un tas d'informations. (Même chose que dans Android Studio.) Copiez / collez maintenant vos mots de passe précédemment choisis.

(3) Modifiez votre gradle.buildfichier de module pour utiliser ce qui précède

Les parties suivantes doivent être présentes dans le fichier de génération Gradle de votre application / module. Tout d'abord, ajoutez les lignes suivantes à l' extérieur et avant votre android {}bloc.

//def keystorePropertiesFile = rootProject.file("$HOME/.android/keystore.properties")
def keystorePropertiesFile = rootProject.file("../../keystore.properties")
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))

Ensuite, à l' intérieur du android {}bloc, ajoutez:

android {
    ...
    defaultConfig { ... }
    signingConfigs {
            release {
                keyAlias keystoreProperties['keyAlias']
                keyPassword keystoreProperties['keyPassword']
                storeFile file(keystoreProperties['storeFile'])
                storePassword keystoreProperties['storePassword']
            }
        }
    // Tell Gradle to sign your APK
    buildTypes {
        release {
            signingConfig signingConfigs.release
            ...
        }
    }
}

Maintenant, à partir du shell, vous pouvez reconstruire votre application avec:

cd $HOME/projects/mydev/MyApp/app/
./gradlew clean build

Cela devrait générer une application correctement signée qui peut être utilisée dans Google Play.


MISE À JOUR: 2019-04-02

Des versions plus récentes de keytoolet quelque chose vous disent que vous devez utiliser un fichier de clés basé sur PKCS12 au lieu de l'original / par défaut comme j'utilise ci-dessus. Ils vous disent ensuite que vous devez convertir au nouveau format PKCS12 ouvert. Cependant, il semble que les outils de développement Android ne soient pas encore prêts pour cela, car si vous le faites, vous obtiendrez les erreurs étranges suivantes:

com.android.ide.common.signing.KeytoolException:Échec de lecture de la clé XXX dans le magasin "F: \ XXX \ XXX.jks": échec de la récupération de la clé: le bloc final n'est pas correctement rempli. De tels problèmes peuvent survenir si une mauvaise clé est utilisée pendant le déchiffrement.

N'utilisez donc pas de clé convertie!


La signatureConfigs est-elle enregistrée dans l'apk et peut-elle être décompilée par n'importe quel utilisateur pour obtenir des mots de passe ou n'apparaît-elle pas dans l'apk?
JavierSegoviaCordoba

2
Fonctionne comme un charme. Merci, cela devrait être la réponse acceptée
pratham kesarkar

Que faire si vous souhaitez uniquement le fichier de clés et les mots de passe sur un serveur de génération? Avec la solution ci-dessus, chaque développeur de l'équipe doit avoir le magasin de clés sur sa machine locale. Sinon, la synchronisation du projet Gradle échouera: keystore.properties (aucun fichier ou répertoire de ce type).
Diana Farin

1
Vous pouvez valider un keystore.propertiesfichier factice pour le contrôle de code source, donc les builds fonctionnent sur les machines de développement. J'ai décrit une configuration de serveur de build ici .
dskrvk

1
Remarque sur votre dernière mise à jour concernant la keytoolgénération d'un fichier de clés PKCS12: vous pouvez passer -storetype JKSla keytoolcommande pour définir le type de fichier de clés sur JKS, ce qui est requis par les outils Android.
Trevor Halvorson

35

Comme l'a dit @Destil, mais permettez à d'autres qui n'ont pas la clé de construire: Plus simple que les réponses précédentes:

Mettez cela dans ~/.gradle/gradle.properties

RELEASE_STORE_FILE={path to your keystore}
RELEASE_STORE_PASSWORD=*****
RELEASE_KEY_ALIAS=*****
RELEASE_KEY_PASSWORD=*****

Modifiez votre build.gradlecomme ceci:

...    
if(project.hasProperty("RELEASE_STORE_FILE")) {
    signingConfigs {    
       release {
           storeFile file(RELEASE_STORE_FILE)
           storePassword RELEASE_STORE_PASSWORD
           keyAlias RELEASE_KEY_ALIAS
           keyPassword RELEASE_KEY_PASSWORD
       }
    }
}

buildTypes {
    if(project.hasProperty("RELEASE_STORE_FILE")) {
        release {
            signingConfig signingConfigs.release
        }
    }
}
....

Ensuite, vous pouvez exécuter gradle assembleRelease OU gradle build


Comment définir le chemin d'accès dans Windows: chemin d'accès à votre magasin de
clés

Le fichier storeFile ("C: \\ Users \\ xxxx \\ Documents \\ yyyy \\ mykey.jks") est-il correct?
reza_khalafi

28

(En réponse à user672009 ci-dessus.)

Une solution encore plus simple, si vous souhaitez conserver vos mots de passe hors d'un référentiel git; Pourtant, vouloir y inclure votre build.gradle, qui fonctionne même très bien avec les saveurs de produits, consiste à créer un fichier de notes distinct. Appelons-le «signature.gradle» (incluez-le dans votre .gitignore). Tout comme s'il s'agissait de votre fichier build.gradle moins tout ce qui n'est pas lié à sa connexion.

android {
    signingConfigs { 
        flavor1 {
            storeFile file("..")
            storePassword ".."
            keyAlias ".."
            keyPassword ".."
        }
        flavor2 {
            storeFile file("..")
            storePassword ".."
            keyAlias ".."
            keyPassword ".."
        }
    }
}

Ensuite, dans votre fichier build.gradle, incluez cette ligne juste en dessous "Appliquer le plugin: 'android'"

 apply from: 'signing.gradle'

Si vous n'avez pas ou n'utilisez pas plusieurs saveurs, renommez "flaveur1" en "version" ci-dessus, et vous devriez avoir terminé. Si vous utilisez des saveurs, continuez.

Enfin, liez vos versions à sa signatureConfig correcte dans votre fichier build.gradle et vous devriez avoir terminé.

  ...

  productFlavors {

      flavor1 {
          ...
          signingConfig signingConfigs.flavor1
      }

      flavor2 {
          ...
          signingConfig signingConfigs.flavor2
      }
  }

  ...

Pouvez-vous être un peu plus précis. Je ne peux pas le faire fonctionner: «ne peut pas résoudre la signature du symboleConfig».
Amio.io

Si j'inclus 'signature.gradle' dans le build.gradle - je suis obligé d'en avoir un dans le dépôt git (sinon j'obtiens l'erreur 'signature.gradle n'existe pas'). Et si je mets le 'signature.gradle' dans git, cela va à l'encontre du but. Comment puis-je rendre l'inclusion de signature.gradle facultative?
Jaguar

21

Si vous avez déjà le fichier de clés, cela peut être aussi simple que d'ajouter quelques paramètres à votre commande de génération:

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

Aucune modification permanente de votre projet Android n'est nécessaire.

Source: http://www.tinmith.net/wayne/blog/2014/08/gradle-sign-command-line.htm


18

Ceci est une réponse à user672009 et un ajout au message de sdqali (son code plantera lors de la construction de la version de débogage par le bouton "Exécuter" de l'IDE):

Vous pouvez utiliser le code suivant:

final Console console = System.console();
if (console != null) {

    // Building from console 
    signingConfigs {
        release {
            storeFile file(console.readLine("Enter keystore path: "))
            storePassword console.readLine("Enter keystore password: ")
            keyAlias console.readLine("Enter alias key: ")
            keyPassword console.readLine("Enter key password: ")
        }
    }

} else {

    // Building from IDE's "Run" button
    signingConfigs {
        release {

        }
    }

}

Existe-t-il un moyen d'avoir des valeurs par défaut? Mon magasin de clés est généralement le même. Le storePassword est généralement le même que le keyPassword et le keyAlias ​​le nom du projet en minuscules.
user672009

@ user672009 vous pouvez toujours utiliser du code Java à l'intérieur du script.
AChep

1
vous voudrez peut-être utiliser quelque chose comme ceci: keyPassword new String(console.readPassword("Enter key password: "))pour vous assurer que votre mot de passe n'est pas affiché lors de la saisie
Alex Semeniuk

Cela ne fonctionne plus, voir github.com/gradle/gradle/issues/1251
SqAR.org

16

Dans la version plus récente d'Android Studio, il existe une méthode GUI qui est très simple et qui remplit également le fichier Gradle.

  1. File -> Project Structure

  2. Module -> Choisissez le module principal («app» ou autre nom personnalisé)

  3. Signing onglet -> Image Plus pour ajouter une nouvelle configuration

  4. Remplissez les données sur le côté droit

  5. OK et le fichier Gradle est automatiquement créé

  6. Vous devrez ajouter manuellement une ligne à l' signingConfig signingConfigs.NameOfYourConfigintérieurbuiltTypes{release{}}

Images:

entrez la description de l'image ici

entrez la description de l'image ici

Deux notes importantes (!):

(EDIT 12/15)

  1. Pour créer un fichier APK signé, vous devez ouvrir l'onglet Terminal d'Android Studio (en bas de l'interface principale) et émettre une commande ./gradlew assembleRelease

  2. Si vous avez oublié keyAlias(ce qui m'arrive souvent), vous devrez lancer Build -> Generate Signed APKpour démarrer le processus et voir le nom de la clé Alias.


2
Cela code en dur vos mots de passe dans le build.gradlefichier, n'est-ce pas?
Joshua Pinter

16

Si vous construisez apk via la ligne de commande comme moi, vous pouvez fournir la configuration de signature comme arguments.

Ajoutez ceci à votre build.gradle

def getStore = { ->
    def result = project.hasProperty('storeFile') ? storeFile : "null"
    return result
}

def getStorePassword = { ->
    def result = project.hasProperty('storePassword') ? storePassword : ""
    return result
}

def getKeyAlias = { ->
    def result = project.hasProperty('keyAlias') ? keyAlias : ""
    return result
}

def getKeyPassword = { ->
    def result = project.hasProperty('keyPassword') ? keyPassword : ""
    return result
}

Faites signingConfigscomme ça

signingConfigs {
    release {
        storeFile file(getStore())
        storePassword getStorePassword()
        keyAlias getKeyAlias()
        keyPassword getKeyPassword()
    }
}

Ensuite, vous exécutez gradlewcomme ça

./gradlew assembleRelease -PstoreFile="keystore.jks" -PstorePassword="password" -PkeyAlias="alias" -PkeyPassword="password"

C'est quoi build.gradle? Haut niveau? Veuillez ajouter plus de code
Vlad

Pour clarifier, c'est le app/build.gradlefichier dont je parle.
Egis

11
android {
    compileSdkVersion 17
    buildToolsVersion "19.0.3"

    defaultConfig {
        minSdkVersion 9
        targetSdkVersion 18
    }

    File signFile = rootProject.file('sign/keystore.properties')
    if (signFile.exists()) {
        Properties properties = new Properties()
        properties.load(new FileInputStream(signFile))
        signingConfigs {
            release {
                storeFile rootProject.file(properties['keystore'])
                storePassword properties['storePassword']
                keyAlias properties['keyAlias']
                keyPassword properties['keyPassword']
            }
        }
    }

    buildTypes {
        release {
            runProguard true
            zipAlign true
            proguardFile rootProject.file('proguard-rules.cfg')
            signingConfig signingConfigs.release
        }
        debug {
            runProguard false
            zipAlign true
        }
    }
}

Utilisation d'Android Studio 0.5.1, Gradle 1.11 et du plug-in Gradle 0.9.
JP Ventura

1
La création de propriétés à la demande (alias propriétés dynamiques) est obsolète et devrait être supprimée dans Gradle 2.0
JP Ventura

10

Vous pouvez également utiliser l' option de ligne de commande -P de gradle pour faciliter la signature. Dans votre build.gradle, ajoutez singingConfigs comme ceci:

signingConfigs {
   release {
       storeFile file("path/to/your/keystore")
       storePassword RELEASE_STORE_PASSWORD
       keyAlias "your.key.alias"
       keyPassword RELEASE_KEY_PASSWORD
   }
}

Appelez ensuite gradle build comme ceci:

gradle -PRELEASE_KEYSTORE_PASSWORD=******* -PRELEASE_KEY_PASSWORD=****** build

Vous pouvez utiliser -P pour définir storeFile et keyAlias ​​si vous préférez.

Il s'agit essentiellement de la solution de Destil mais avec les options de ligne de commande.

Pour plus de détails sur les propriétés du gradle, consultez le guide d'utilisation du gradle .


7

La réponse de @ Destil est bonne si vous pouvez réutiliser la même configuration sur tous les projets. Alternativement, Android Studio est livré avec un local.propertiesfichier qui peut être utilisé à la place, mais il est censé être généré par IDE et je ne trouve pas de moyen de l'étendre à partir d'Android Studio.

Ceci est une variante de la réponse de @ jonbo . Cette réponse permet des paramètres spécifiques au projet, mais elle s'accompagne d'un peu de surcharge pour les développeurs. Plus précisément, un passe-partout important est nécessaire pour déplacer la signingConfigsdéfinition dans un fichier séparé - surtout si vous devez le faire pour plusieurs projets, ce qui est une raison principale pour choisir cette solution par rapport à Destil. Cela peut être quelque peu atténué en incluant également la ligne

apply plugin: 'com.android.application'

dans le fichier d'informations d'identification, car cela permettra l'achèvement de l'IDE.

Enfin, la plupart des solutions ici ne permettent pas de construire le projet en mode débogage - qui gère automatiquement la signature de débogage - sans fournir une signingConfigsdéfinition syntaxiquement sinon sémantiquement valide . Si vous n'avez pas besoin de produire une version de version à partir d'une machine donnée, cette étape supplémentaire peut être considérée comme un obstacle inutile. D'un autre côté, cela peut être une aide contre des collègues ignorants ou paresseux exécutant des builds de débogage en production.

Cette solution permettra de déboguer les builds sans se soucier des informations d'identification, mais elle nécessitera des informations d'identification valides pour produire des builds de version, et cela prend très peu de passe-partout. Cependant, comme inconvénient, cela pourrait encourager d'autres à remplacer les valeurs fictives par de véritables informations d'identification et il n'y a aucun moyen de se protéger contre cela.

// app/build.gradle
// Define this structure in signing.gradle to enable release builds.
ext.signing = [
        storeFilePath : 'path/to/keystore',
        storePassword : 'keystore password',
        keyAlias      : 'key alias',
        keyPassword   : 'key password',
]

if (file('signing.gradle').exists()) {
    apply from: 'signing.gradle'
}

android {
    ...
    signingConfigs {
        release {
            storeFile file(project.signing.storeFilePath)
            storePassword project.signing.storePassword
            keyAlias project.signing.keyAlias
            keyPassword project.signing.keyPassword
        }
    }
    buildTypes {
        debug { ... }
        release {
            signingConfig signingConfigs.release
            ...
        }
    }
}

Cela crée une propriété factice qui sert uniquement à produire un fichier de construction syntaxiquement valide. Les valeurs affectées aux ext.signingpropriétés de ne sont pas pertinentes en ce qui concerne les versions de débogage. Pour permettre la libération construit, copie ext.signingen signing.gradleet remplacer les valeurs fictives avec des informations d' identification valides.

// signing.gradle
ext.signing = [
        storeFilePath : 'real/keystore',
        storePassword : 'real keystore password',
        keyAlias : 'real key alias',
        keyPassword : 'real key password',
]

Bien sûr, signing.gradledevrait être ignoré par VCS.


6

Presque toutes les plates-formes offrent désormais une sorte de trousseau de clés, il n'y a donc aucune raison de laisser des mots de passe en texte clair.

Je propose une solution simple qui utilise le module Python Keyring (principalement le script de console compagnon keyring) et un wrapper minimal autour de la ['do', 'something'].execute() fonctionnalité Groovy :

def execOutput= { args ->
    def proc = args.execute()
    proc.waitFor()
    def stdout = proc.in.text
    return stdout.trim()
}

En utilisant cette fonction, la signingConfigssection devient:

signingConfigs {
    release {
        storeFile file("android.keystore")
        storePassword execOutput(["keyring", "get", "google-play", storeFile.name])
        keyAlias "com.example.app"
        keyPassword execOutput(["keyring", "get", "google-play", keyAlias])
    }
}

Avant d'exécuter, gradle assembleReleasevous devez définir les mots de passe dans votre trousseau de clés, une seule fois:

$ keyring set google-play android.keystore # will be prompted for the passwords
$ keyring set google-play com.example.app

Bonnes sorties!


5

En étendant la réponse de David Vavra, créez un fichier ~ / .gradle / gradle.properties et ajoutez

RELEASE_STORE_FILE=/path/to/.keystore
RELEASE_KEY_ALIAS=XXXXX
RELEASE_STORE_PASSWORD=XXXXXXXXX
RELEASE_KEY_PASSWORD=XXXXXXXXX

Puis dans build.gradle

  signingConfigs {
    release {
    }
  }

  buildTypes {
    release {
      minifyEnabled true
      shrinkResources true

    }
  }

  // make this optional
  if ( project.hasProperty("RELEASE_KEY_ALIAS") ) {
    signingConfigs {
      release {
        storeFile file(RELEASE_STORE_FILE)
        storePassword RELEASE_STORE_PASSWORD
        keyAlias RELEASE_KEY_ALIAS
        keyPassword RELEASE_KEY_PASSWORD
      }
    }
    buildTypes {
      release {
        signingConfig signingConfigs.release
      }
    }
  }

5

J'ai eu beaucoup de plaisir à comprendre celui-ci. Voici mon parcours.

Présentation de A à Z sur la façon de créer un fichier de génération Gradle dans IntelliJ (v.13.1.4) Cette procédure suppose que vous savez comment créer un fichier de clés. Pour que ce tutoriel fonctionne, vous aurez besoin que votre fichier de clés soit situé dans le dossier de votre application et vous aurez besoin que votre fichier zipalign.exe soit situé dans 'SDK-ROOT \ tools'. Ce fichier se trouve généralement dans «SDK-ROOT \ build-tools» et sous ce dossier, il se trouvera dans le dossier api le plus élevé (alpha ou beta, je recommande la version alpha).

Pour ceux d'entre vous qui souhaitent sauter directement, voici le fichier de construction gradle.

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.9.+'
    }
}
apply plugin: 'android'

repositories {
    mavenCentral()
}
android {
    compileSdkVersion 19
    buildToolsVersion '20.0.0'
    defaultConfig {
        minSdkVersion 8
        targetSdkVersion 19
        versionCode 1
        versionName "1.0"
    }
    signingConfigs {
        playstore {
            keyAlias 'developers4u'
            keyPassword 'thisIsNotMyRealPassword'
            storeFile file('developers4u.keystore')
            storePassword 'realyItIsNot'
        }
    }
    buildTypes {
        assembleRelease {
            debuggable false
            jniDebugBuild false
            runProguard true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
            zipAlign true
            signingConfig signingConfigs.playstore
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:support-v4:20.0.0'
    implementation 'com.android.support:appcompat-v7:20.0.0'
}

Vous pouvez créer une partie de ce fichier de construction (ci-dessus) à partir de l'option de menu: Structure de fichier / projet À partir d'ici, sélectionnez Facettes et cliquez sur 'Android-Gradle (App). De là, vous verrez des onglets: 'Propriétés', 'Signature', 'Saveurs', 'Types de build' et 'Dépendances' pour cette procédure, nous utiliserons simplement 'Signature' et 'Types de build'. Sous `` Types de build '' (dans la section nom), entrez le nom que vous souhaitez identifier la configuration de votre type de build et dans les 4 autres champs entrez vos informations de magasin de clés (en définissant le chemin du magasin de clés celui sous le dossier de votre application).

Sous 'Build Types', entrez la valeur 'assembleRelease' dans le champ du nom, 'Debuggable' doit être défini sur false, 'Jni Debug Build' doit être faux, définissez 'Run Proguard' sur true et 'Zip Align' sur true. Cela générera un fichier de construction, mais pas comme illustré ci-dessus, vous devrez ajouter quelques éléments au fichier de construction par la suite. L'emplacement du fichier ProGuard ici sera défini manuellement dans le fichier de construction gradle. (comme illustré ci-dessus)

Les conteneurs DSL que vous devrez ajouter par la suite sont les suivants:

android {
    ....
    compileSdkVersion 19
    buildToolsVersion '20.0.0'
    defaultConfig {
        minSdkVersion 8
        targetSdkVersion 19
        versionCode 1
        versionName "1.0"
    }
    ....
}

Vous devrez également ajouter:

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:support-v4:20.0.0'
    implementation 'com.android.support:appcompat-v7:20.0.0'
}

notez que ce conteneur DSL ci-dessus («dépendances») devrait être au bas du fichier de configuration mais pas à l'intérieur du conteneur DSL Android. Afin de construire le conteneur de dépendances à partir du menu IntelliJ, sélectionnez: Structure de fichier / projet. De là, sélectionnez à nouveau Facettes, puis Android-Gradle (application). Vous verrez les mêmes 5 onglets que ceux mentionnés ci-dessus. Sélectionnez l'onglet «Dépendances» et ajoutez les dépendances dont vous avez besoin.

Après tout cela, vous devriez voir un fichier de construction Gradle similaire au fichier en haut de cette procédure pas à pas. Pour créer votre version alignée avec zip, vous devrez ouvrir les tâches Gradle. Vous pouvez accéder à cette fenêtre en sélectionnant Affichage / Fenêtres d'outils / Gradle. De là, vous pouvez double-cliquer sur 'assemblerAssemblerRelease. Cela devrait générer votre APK déployable.

Les problèmes potentiels qui peuvent survenir lors de la compilation de votre version sont (mais sans s'y limiter): Votre fichier de génération Gradle est au mauvais endroit. Il existe deux fichiers de construction Gradle; un dans le dossier racine de votre application et un autre dans le dossier de l'application sous la racine de l'application. Vous devez utiliser ce dernier.

Vous pouvez également avoir des problèmes de peluches. (Remarque: Android Developer Studio est bien meilleur pour repérer les problèmes de Lint qu'IntelliJ, vous le remarquerez lorsque vous essayez de générer un APK signé à partir des options de menu)

Pour contourner les problèmes de peluches, vous devrez placer le conteneur DSL suivant dans le conteneur Android (en haut):

android {
        ....
    lintOptions {
        abortOnError false
    }
    ....
}

mettre ceci dans votre conteneur DSL Android entraînera la génération d'un fichier d'erreur dans le dossier de construction (directement sous le dossier de votre application) le nom du fichier devrait être quelque chose comme 'lint-results-release-fatal.html' ce fichier vous indiquera le la classe où l'erreur s'est produite. Un autre fichier qui sera généré est un fichier XML qui contient l'ID de problème associé à l'erreur de peluches. Le nom du fichier doit être quelque chose comme 'lint-results-release-fatal.xml'. Quelque part vers le haut du fichier, vous verrez un problème de nœud à l'intérieur duquel vous verrez quelque chose de similaire à 'id = "IDOfYourLintProblem"'

Pour corriger ce problème, ouvrez le fichier de votre projet qui était répertorié dans le fichier 'lint-results-assembleRelease-fatal.html' et entrez la ligne de code suivante dans le fichier de classe Java juste au-dessus du nom de classe: @SuppressLint ("IDOfYourLintProblem "). Vous devrez peut-être importer 'android.annotation.SuppressLint;'

Votre fichier de classe java devrait donc apparaître comme:

package com.WarwickWestonWright.developers4u.app.CandidateArea;

import android.annotation.SuppressLint;
... other imports

@SuppressLint("IDOfYourLintProblem")
public class SearchForJobsFragment extends Fragment {... rest of your class definition}

Notez que la suppression des erreurs de peluches n'est pas toujours la meilleure idée, il vaut mieux changer votre code à l'origine des erreurs de peluches.

Un autre problème qui pourrait se produire est que vous n'avez pas défini la variable d'environnement pour la variable d'environnement Gradle HOME. Cette variable est nommée 'GRADLE_HOME' et doit être définie sur le chemin du répertoire personnel de gradle, quelque chose comme 'C: \ gradle-1.12' Parfois, vous pouvez également définir la variable d'environnement pour 'ANDROID_HOME', définissez-la sur 'YOUR- SDK-Root \ sdk '

Après cela, revenez à la fenêtre des tâches Gradle et double-cliquez sur l'assembleAssembleRelease.

Si tout réussit, vous devriez pouvoir aller dans le dossier app \ build \ apk et trouver votre fichier APK déployable.


+1 pour l'effort et: 'lintOptions {abortOnError false}'
Raz Tourgman

4

Encore une autre approche du même problème. Comme il n'est pas recommandé de stocker tout type d'informations d'identification dans le code source, nous avons décidé de définir les mots de passe pour le magasin de clés et l'alias de clé dans un fichier de propriétés distinct comme suit:

key.store.password=[STORE PASSWORD]
key.alias.password=[KEY PASSWORD]

Si vous utilisez git, vous pouvez créer un fichier texte appelé, par exemple, secure.properties. Vous devez vous assurer de l'exclure de votre référentiel (si vous utilisez git, l'ajouter au fichier .gitignore). Ensuite, vous devrez créer une configuration de signature, comme l'indiquent certaines des autres réponses. La seule différence réside dans la façon dont vous chargez les informations d'identification:

android {
    ...
    signingConfigs {
        ...
        release {
            storeFile file('[PATH TO]/your_keystore_file.jks')
            keyAlias "your_key_alias"

            File propsFile = file("[PATH TO]/secure.properties");
            if (propsFile.exists()) {
                Properties props = new Properties();
                props.load(new FileInputStream(propsFile))
                storePassword props.getProperty('key.store.password')
                keyPassword props.getProperty('key.alias.password')
            }
        }
        ...
    }

    buildTypes {
        ...
        release {
            signingConfig signingConfigs.release
            runProguard true
            proguardFile file('proguard-rules.txt')
        }
        ...
    }
}

N'oubliez jamais d'attribuer manuellement la signature de configuration au type de build de la version (pour une raison quelconque, je suppose parfois qu'il sera utilisé automatiquement). En outre, il n'est pas obligatoire d'activer proguard, mais il est recommandé.

Nous aimons cette approche mieux que d'utiliser des variables d'environnement ou de demander une entrée utilisateur, car cela peut être fait à partir de l'EDI, en passant au type de build Realease et en exécutant l'application, plutôt que d'avoir à utiliser la ligne de commande.


1
Gradle ne compile pas en utilisant ceci: props = new Properties (); Impossible de définir la valeur de la propriété en lecture seule «accessoires»
cesards

Vous avez raison @ m3n0R. J'ai édité une ligne de ma réponse pour refléter le correctif que nous devions introduire dans notre application afin qu'il compile toujours en utilisant les dernières versions de Gradle. Fondamentalement, les accessoires doivent être déclarés comme une variable locale.
argenkiwi

comment cela serait-il adoptable en utilisant les outils cloud CI / CD .... le / path / to / keystore et /path/to/secure.props me lance .... merci pour cela cependant.
sirvon

4

Android Studio Allez dans Fichier -> Structure du projet ou appuyez sur Ctrl + Alt + Maj + S

Voir l'image

entrez la description de l'image ici

Cliquez sur OK

Ensuite, le signatureConfigs générera sur votre fichier build.gradle.

entrez la description de l'image ici


Et c'est exactement ce que vous ne voulez pas faire. De cette façon, tous vos mots de passe sont en texte clair et font partie de votre projet , et sont très faciles à inclure accidentellement, même dans votre build distribué.
not2qubit

2

J'ai eu plusieurs problèmes que j'ai mis la ligne suivante au mauvais endroit:

signingConfigs {
    release {
        // We can leave these in environment variables
        storeFile file("d:\\Fejlesztés\\******.keystore")
        keyAlias "mykey"

        // These two lines make gradle believe that the signingConfigs
        // section is complete. Without them, tasks like installRelease
        // will not be available!
        storePassword "*****"
        keyPassword "******"
    }
}

Assurez-vous que vous placez les pièces de signatureConfigs dans la section Android:

android
{
    ....
    signingConfigs {
        release {
          ...
        }
    }
}

au lieu de

android
{
    ....
}

signingConfigs {
   release {
        ...
   }
}

Il est facile de commettre cette erreur.


2

Nous sommes en 2019 et je dois signer l'APK avec V1 (signature du pot) ou V2 (signature APK complète). J'ai googlé "générer un grade apk signé" et cela m'a amené ici. J'ajoute donc ma solution d'origine ici.

signingConfigs {
    release {
        ...
        v1SigningEnabled true
        v2SigningEnabled true
    }
}

Ma question d'origine: comment utiliser V1 (signature Jar) ou V2 (signature APK complète) à partir du fichier build.gradle


Pas besoin de points-virgules; cela vous donnera une erreur.
Takeshi Kaga

C'est vrai. Merci. J'ai édité la réponse.
user1506104

1

Pour compléter les autres réponses, vous pouvez également placer votre fichier gradle.properties dans votre propre dossier de module, avec build.gradle, au cas où votre fichier de clés est spécifique à un projet.


1

je travaille dans Ubuntu14.04. vim ~ / .bashrc et ajouter l'exportation ANDROID_KEYSTORE = exporter ANDROID_KEYALIAS =

puis dans build.gradle set.

    final Console console = System.console();
if (console != null) {

    // Building from console
    signingConfigs {
        release {
            storeFile file(System.getenv("KEYSTORE"))
            storePassword new String(System.console().readPassword("\n\$ Enter keystore password: "))
            keyAlias System.getenv("KEY_ALIAS")
            keyPassword new String(System.console().readPassword("\n\$ Enter key password: "))
        }
    }

} else {

    // Building from IDE's "Run" button
    signingConfigs {
        release {

        }
    }

}

À mon humble avis, cela semble être la meilleure solution, mais malheureusement, il a cessé de fonctionner sur les nouvelles versions de Gradle : System.console()retours null.
Antonio Vinicius Menezes Medei

1

Une alternative consiste à définir une tâche qui s'exécute uniquement sur les versions de versions.

android {
  ...
  signingConfigs {
     release {
        // We can leave these in environment variables
        storeFile file('nameOfKeystore.keystore')
        keyAlias 'nameOfKeyAlias'

        // These two lines make gradle believe that the signingConfigs
        // section is complete. Without them, tasks like installRelease
        // will not be available!
        storePassword "notYourRealPassword"
        keyPassword "notYourRealPassword"

     }
  }
  buildTypes {
     ...
     release {
        signingConfig signingConfigs.release
        ...
     }
  }
  ...
}

task setupKeystore << {
final Console console = System.console();
if (console != null) {
    //def keyFile = console.readLine(“\nProject: “ + project.name + “Enter keystore path: "))
    //def keyAlias = console.readLine(“Project: “ + project.name + “Enter key alias: ")
        def storePw = new String(console.readPassword(“Project:  + project.name + “. Enter keystore password: "))
        def keyPw  = new String(console.readPassword(“Project: “ + project.name + “.Enter keystore password: "))

    //android.signingConfigs.release.storeFile = file(keyFile);
    //android.signingConfigs.release.keyAlias = keyAlias
        android.signingConfigs.release.storePassword = storePw
        android.signingConfigs.release.keyPassword = keyPw
}
}

//Validate t
def isReleaseConfig = gradle.startParameter.taskNames.any {it.contains('Release') }
if (isReleaseConfig) {
    setupKeystore.execute();
}

Ce qui me semble préférable: stackoverflow.com/a/19130098/3664487 Comment les deux approches se comparent-elles?
user2768

1

Vous pouvez demander des mots de passe à partir de la ligne de commande:

...

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
  }

  ...
}

...

Le if-then-elsebloc empêche les demandes de mots de passe lorsque vous créez une version. Bien que la elsebranche ne soit pas accessible, elle incite Gradle à créer une install...Releasetâche.

Backstory . Comme indiqué par https://stackoverflow.com/a/19130098/3664487 , "Les scripts Gradle peuvent demander une entrée utilisateur à l'aide de la méthode System.console (). ReadLine ." Malheureusement, Gradle demandera toujours un mot de passe, même lorsque vous créez une version de débogage (cf. Comment créer un fichier apk signé avec Gradle? ). Heureusement, cela peut être surmonté, comme je l'ai montré ci-dessus.


Ma réponse précédente a rencontré des problèmes en raison de stackoverflow.com/questions/33897802/… . J'ai révisé ma réponse pour éliminer ce problème.
user2768

@Haroon, cela a fonctionné le 24 novembre 2015. La communauté peut peut-être vous aider avec votre problème, mais vous devrez fournir plus de détails.
user2768

J'aime cette solution car elle évite de mettre le mot de passe en texte clair dans un fichier texte mais System.console (). ReadLine ne fonctionne pas en gradle à cause de ce problème ennuyeux.
morpheus

@morpheus, je n'ai jamais eu de problème. Ce qui précède fonctionne pour moi.
user2768

Je pense que vous exécutez le script à partir d'un IDE. si le script est exécuté à partir du terminal, vous verrez l'erreur. mais merci pour cette réponse. C'est ce que je cherchais.
morpheus

0

Ajout de ma façon de le faire dans React-Native en utilisant le package react-native-config .
Créez un fichier .env:

RELEASE_STORE_PASSWORD=[YOUR_PASSWORD]
RELEASE_KEY_PASSWORD=[YOUR_PASSWORD]

notez que cela ne devrait pas faire partie du contrôle de version.

dans votre build.gradle:

signingConfigs {
        debug {
            ...
        }
        release {
            storeFile file(RELEASE_STORE_FILE)
            storePassword project.env.get('RELEASE_STORE_PASSWORD')
            keyAlias RELEASE_KEY_ALIAS
            keyPassword project.env.get('RELEASE_KEY_PASSWORD')
        }
    }

0

Dans mon cas, je téléchargeais la mauvaise apk, vers la version d'une autre application.


0

Pour Groovy (build.gradle)

Vous ne devez pas mettre vos informations d'identification de signature directement dans le fichier build.gradle . Au lieu de cela, les informations d'identification doivent provenir d'un fichier qui n'est pas sous contrôle de version.

Placez un fichier signature.properties où se trouve le module build.gradle spécifique au module . N'oubliez pas de l'ajouter à votre fichier .gitignore !

signature.propriétés

storeFilePath=/home/willi/example.keystore
storePassword=secret
keyPassword=secret
keyAlias=myReleaseSigningKey

build.gradle

android {
    // ...
    signingConfigs{
        release {
            def props = new Properties()

            def fileInputStream = new FileInputStream(file('../signing.properties'))
            props.load(fileInputStream)
            fileInputStream.close()

            storeFile = file(props['storeFilePath'])
            storePassword = props['storePassword']
            keyAlias = props['keyAlias']
            keyPassword = props['keyPassword']
        }
    }

    buildTypes {
        release {
            signingConfig signingConfigs.release
            // ...
        }
    }
}

0

Pour le script Kotlin (build.gradle.kts)

Vous ne devez pas placer vos informations d'identification de signature directement dans le fichier build.gradle.kts . Au lieu de cela, les informations d'identification doivent provenir d'un fichier qui n'est pas sous contrôle de version.

Placez un fichier signature.properties où se trouve le module build.gradle.kts spécifique au module . N'oubliez pas de l'ajouter à votre fichier .gitignore !

signature.propriétés

storeFilePath=/home/willi/example.keystore
storePassword=secret
keyPassword=secret
keyAlias=myReleaseSigningKey

build.gradle.kts

android {
    // ...
    signingConfigs {
        create("release") {
            val properties = Properties().apply {
                load(File("signing.properties").reader())
            }
            storeFile = File(properties.getProperty("storeFilePath"))
            storePassword = properties.getProperty("storePassword")
            keyPassword = properties.getProperty("keyPassword")
            keyAlias = "release"
        }
    }

    buildTypes {
        getByName("release") {
            signingConfig = signingConfigs.getByName("release")
            // ...
        }
    }
}

-1

si vous ne voulez pas voir Impossible d'appeler la méthode readLine () sur un objet nul. vous devez d'abord écrire dans gradle.properties .

KEYSTORE_PASS=*****
ALIAS_NAME=*****
ALIAS_PASS=*****
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.