Recherche…


Introduction

Gradle est un système de génération basé sur JVM qui permet aux développeurs d'écrire des scripts de haut niveau pouvant être utilisés pour automatiser le processus de compilation et de production d'applications. C'est un système flexible basé sur un plug-in, qui vous permet d'automatiser divers aspects du processus de construction. y compris la compilation et la signature d'un .jar , le téléchargement et la gestion des dépendances externes, l'injection de champs dans AndroidManifest ou l'utilisation de versions spécifiques du SDK.

Syntaxe

  • apply plugin : Les plugins qui devraient normalement être utilisés juste 'com.android.application' ou 'com.android.library' .

  • android : la configuration principale de votre application

    • compileSdkVersion : La version du SDK de compilation
    • buildToolsVersion : La version des outils de construction
    • defaultConfig : les paramètres par défaut qui peuvent être écrasés par les saveurs et les types de construction
      • applicationId : l'identifiant de l'application que vous utilisez, par exemple dans le PlayStore, est le même que le nom de votre paquet
      • minSdkVersion : la version minimale requise du SDK
      • targetSdkVersion : La version du SDK sur laquelle vous compilez (devrait toujours être la nouvelle)
      • versionCode : Le numéro de version interne qui doit être plus grand à chaque mise à jour
      • versionName : le numéro de version que l'utilisateur peut voir dans la page de détails de l'application
    • buildTypes : Voir ailleurs (TODO)
  • dependencies : les dependencies maven ou locales de votre application

    • compile une seule dépendance
    • testCompile : une dépendance pour l'unité ou les tests d'intégration

Remarques

Voir également

Gradle pour Android - Documentation étendue:

Il y a une autre balise où vous pouvez trouver plus de sujets et d'exemples sur l'utilisation de gradle dans Android.
http://www.riptutorial.com/topic/2092

Un fichier de base build.gradle

Voici un exemple de fichier build.gradle par défaut dans un module.

apply plugin: 'com.android.application'

android {
    compileSdkVersion 25
    buildToolsVersion '25.0.3'

    signingConfigs {
        applicationName {
            keyAlias 'applicationName'
            keyPassword 'password'
            storeFile file('../key/applicationName.jks')
            storePassword 'keystorePassword'
        }
    }
    defaultConfig {
        applicationId 'com.company.applicationName'
        minSdkVersion 14
        targetSdkVersion 25
        versionCode 1
        versionName '1.0'
        signingConfig signingConfigs.applicationName
    }
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

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

    compile 'com.android.support:appcompat-v7:25.3.1'
    compile 'com.android.support:design:25.3.1'

    testCompile 'junit:junit:4.12'
}

DSL (langage spécifique au domaine)

Chaque bloc du fichier ci-dessus est appelé un DSL (langage spécifique au domaine).


Plugins

La première ligne, apply plugin: 'com.android.application' , applique le plug-in Android pour Gradle à la construction et rend le bloc android {} disponible pour déclarer les options de construction spécifiques à Android.

Pour une application Android :

apply plugin: 'com.android.application'

Pour une bibliothèque Android :

apply plugin: 'com.android.library'

Comprendre les DSL dans l'exemple ci-dessus

La deuxième partie, Le bloc android {...} , est la DSL Android qui contient des informations sur votre projet.

Par exemple, vous pouvez définir le compileSdkVersion qui spécifie le niveau d'API Android, qui doit être utilisé par Gradle pour compiler votre application.
Le sous-bloc defaultConfig contient les valeurs par défaut pour votre manifeste. Vous pouvez les override par des saveurs de produit .

Vous pouvez trouver plus d'informations dans ces exemples:


Les dépendances

Le bloc de dependencies est défini en dehors du bloc android {...} : cela signifie qu'il n'est pas défini par le plugin Android mais qu'il est standard.
Le bloc de dependencies spécifie les bibliothèques externes (généralement les bibliothèques Android, mais les bibliothèques Java sont également valides) que vous souhaitez inclure dans votre application. Gradle téléchargera automatiquement ces dépendances pour vous (s'il n'y a pas de copie locale disponible), il vous suffit d'ajouter des lignes de compile similaires lorsque vous souhaitez ajouter une autre bibliothèque.

Regardons l'une des lignes présentes ici:

compile 'com.android.support:design:25.3.1'

Cette ligne dit essentiellement

Ajouter une dépendance sur la bibliothèque de conception du support Android à mon projet.

Gradle s'assurera que la bibliothèque est téléchargée et présente afin que vous puissiez l'utiliser dans votre application, et son code sera également inclus dans votre application.

Si vous êtes familier avec Maven, cette syntaxe est GroupId , deux points, ArtifactId , un autre deux-points, puis la version de la dépendance que vous souhaitez inclure, vous donnant un contrôle total sur le versionnage.

Bien qu'il soit possible de spécifier des versions d'artefacts en utilisant le signe plus (+), la meilleure pratique consiste à éviter de le faire; Cela peut entraîner des problèmes si la bibliothèque est mise à jour à votre insu à l'aide de modifications, ce qui pourrait entraîner des pannes dans votre application.

Vous pouvez ajouter différents types de dépendances:

Une attention particulière devrait être consacrée aux dépendances à plat .

Vous pouvez trouver plus de détails dans cette rubrique.

Note sur le -v7 dans appcompat-v7

compile 'com.android.support:appcompat-v7:25.3.1'

Cela signifie simplement que cette bibliothèque ( appcompat ) est compatible avec l'API Android de niveau 7 et ultérieur.

Note sur le junit: junit: 4.12

Ceci est la dépendance de test pour les tests unitaires.


Spécification des dépendances spécifiques aux différentes configurations de construction

Vous pouvez spécifier qu'une dépendance ne doit être utilisé pour une certaine configuration de construction ou vous pouvez définir des dépendances pour les types de construction ou les saveurs des produits (par exemple, le débogage, de test ou libération) en utilisant debugCompile , testCompile ou releaseCompile au lieu de l'habituel compile .

Ceci est utile pour garder les dépendances liées au test et au débogage hors de votre version, ce qui maintiendra votre version APK aussi mince que possible et vous assurera que les informations de débogage ne peuvent pas être utilisées pour obtenir des informations internes sur votre application.


signatureConfig

Le signingConfig vous permet de configurer votre Gradle pour inclure keystore informations et faire en sorte que l'APK construit en utilisant ces configurations sont signés et prêts à jouer la libération de magasin.

Ici vous pouvez trouver un sujet dédié .

Remarque : Il n'est pas recommandé de conserver les informations d'identification de signature dans votre fichier Gradle. Pour supprimer les configurations de signature, omettez simplement la partie signingConfigs .
Vous pouvez les spécifier de différentes manières:

Voir cette rubrique pour plus de détails: Signer APK sans exposer le mot de passe du fichier de clés .


Vous trouverez d'autres informations sur Gradle pour Android dans le sujet dédié à Gradle .

Définition des arômes du produit

Les build.gradle produit sont définies dans le fichier build.gradle à l'intérieur du bloc android { ... } , comme build.gradle ci-dessous.

...
android {
    ...
    productFlavors {
        free {
            applicationId "com.example.app.free"
            versionName "1.0-free"
        }
        paid {
            applicationId "com.example.app.paid"
            versionName "1.0-paid"
        }
    }
}

Ce faisant, nous avons maintenant deux nouvelles saveurs de produits: free et paid . Chacun peut avoir sa propre configuration et ses propres attributs. Par exemple, nos deux nouvelles versions ont un versionName d' applicationId et un nom de versionName distincts de ceux de notre versionName main existante (disponible par défaut, donc non affichée ici).

Ajout de dépendances spécifiques au produit

Des dépendances peuvent être ajoutées pour une saveur de produit spécifique, de la même manière que vous pouvez les ajouter pour des configurations de construction spécifiques.

Pour cet exemple, supposons que nous ayons déjà défini deux variantes de produits appelées free et paid (plus sur la définition des saveurs ici ).
Nous pouvons alors ajouter la dépendance AdMob pour la version free et la bibliothèque Picasso pour la version paid comme ceci:

android {
    ...

    productFlavors {
        free {
            applicationId "com.example.app.free"
            versionName "1.0-free"
        }
        paid {
            applicationId "com.example.app.paid"
            versionName "1.0-paid"
        }
    }
}

...
dependencies {
    ...
    // Add AdMob only for free flavor
    freeCompile 'com.android.support:appcompat-v7:23.1.1'
    freeCompile 'com.google.android.gms:play-services-ads:8.4.0'
    freeCompile 'com.android.support:support-v4:23.1.1'

    // Add picasso only for paid flavor
    paidCompile 'com.squareup.picasso:picasso:2.5.2'
} 
...

Ajout de ressources spécifiques au produit

Des ressources peuvent être ajoutées pour une saveur de produit spécifique.

Pour cet exemple, supposons que nous avons déjà défini deux versions de produits appelées free et paid . Afin d'ajouter des ressources spécifiques aux produits, nous créons des dossiers de ressources supplémentaires à côté du dossier main/res , auquel nous pouvons ensuite ajouter des ressources comme d'habitude. Pour cet exemple, nous allons définir une chaîne, status , pour chaque version de produit:

/ src / main /res/values/strings.xml

<resources>
    <string name="status">Default</string>
</resources>

/ src / free /res/values/strings.xml

<resources>
    <string name="status">Free</string>
</resources>

/ src / paid /res/values/strings.xml

<resources>
    <string name="status">Paid</string>
</resources>

Les chaînes de status spécifiques à l'arôme du produit remplacent la valeur de status dans l'arôme main .

Définir et utiliser les champs de configuration de la construction

BuildConfigField

Gradle permet buildConfigField lignes buildConfigField de définir des constantes. Ces constantes seront accessibles au moment de l'exécution en tant que champs statiques de la classe BuildConfig . Cela peut être utilisé pour créer des arômes en définissant tous les champs dans le bloc defaultConfig , puis en les defaultConfig des defaultConfig build individuelles, selon les besoins.

Cet exemple définit la date de construction et marque la génération pour la production plutôt que de tester:

android {
    ...
    defaultConfig {
        ...
        // defining the build date
        buildConfigField "long", "BUILD_DATE", System.currentTimeMillis() + "L"
        // define whether this build is a production build
        buildConfigField "boolean", "IS_PRODUCTION", "false"
        // note that to define a string you need to escape it
        buildConfigField "String", "API_KEY", "\"my_api_key\""
    }

    productFlavors {
        prod {
            // override the productive flag for the flavor "prod"
            buildConfigField "boolean", "IS_PRODUCTION", "true"
            resValue 'string', 'app_name', 'My App Name'
        }
        dev {
            // inherit default fields
            resValue 'string', 'app_name', 'My App Name - Dev'
        }
    }
}

Le <package_name> généré automatiquement. BuildConfig .java dans le dossier gen contient les champs suivants basés sur la directive ci-dessus:

public class BuildConfig {
    // ... other generated fields ...
    public static final long BUILD_DATE = 1469504547000L;
    public static final boolean IS_PRODUCTION = false;
    public static final String API_KEY = "my_api_key";
}

Les champs définis peuvent désormais être utilisés dans l'application lors de l'exécution en accédant à la classe BuildConfig générée:

public void example() {
    // format the build date
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
    String buildDate = dateFormat.format(new Date(BuildConfig.BUILD_DATE));
    Log.d("build date", buildDate);
    
    // do something depending whether this is a productive build
    if (BuildConfig.IS_PRODUCTION) {
        connectToProductionApiEndpoint();
    } else {
        connectToStagingApiEndpoint();
    }
}

ResValue

La resValue dans le productFlavors crée une valeur de ressource. Cela peut être n'importe quel type de ressource ( string , dimen , color , etc.). Cela revient à définir une ressource dans le fichier approprié: par exemple, définir une chaîne dans un strings.xml . L'avantage étant que celui défini dans gradle peut être modifié en fonction de votre productFlavor / buildVariant. Pour accéder à la valeur, écrivez le même code que si vous accédiez à un fichier res à partir du fichier de ressources:

getResources().getString(R.string.app_name)

L'important est que les ressources définies de cette manière ne puissent pas modifier les ressources existantes définies dans les fichiers. Ils ne peuvent créer que de nouvelles valeurs de ressource.


Certaines bibliothèques (telles que l'API Google Maps Android) nécessitent une clé API fournie dans le manifeste sous la forme d'une balise de meta-data . Si des clés différentes sont nécessaires pour le débogage et les générations de production, spécifiez un espace réservé de manifeste rempli par Gradle.

Dans votre fichier AndroidManifest.xml :

<meta-data
    android:name="com.google.android.geo.API_KEY"
    android:value="${MAPS_API_KEY}"/>

Et puis définissez le champ en conséquence dans votre fichier build.gradle :

android {
    defaultConfig {
        ...
        // Your development key
        manifestPlaceholders = [ MAPS_API_KEY: "AIza..." ]
    }

    productFlavors {
        prod {
            // Your production key
            manifestPlaceholders = [ MAPS_API_KEY: "AIza..." ]
        }
    }
}

Le système de génération Android génère automatiquement un certain nombre de champs et les place dans BuildConfig.java . Ces champs sont:

Champ La description
DEBUG un Boolean indiquant si l'application est en mode debug ou release
APPLICATION_ID une String contenant l'ID de l'application (par exemple, com.example.app )
BUILD_TYPE une String contenant le type de construction de l'application (généralement debug ou release )
FLAVOR une String contenant la saveur particulière de la construction
VERSION_CODE un int contenant le numéro de version (build).
Ceci est le même que versionCode dans build.gradle ou versionCode dans AndroidManifest.xml
VERSION_NAME une String contenant le nom de la version (build).
Ceci est le même que versionName dans build.gradle ou versionName dans AndroidManifest.xml

En plus de ce qui précède, si vous avez défini plusieurs dimensions de saveur, chaque dimension aura sa propre valeur. Par exemple, si vous avez deux dimensions de color pour la color et la size vous aurez également les variables suivantes:

Champ La description
FLAVOR_color une String contenant la valeur de la saveur 'color'.
FLAVOR_size une String contenant la valeur de la saveur "taille".

Centraliser les dépendances via le fichier "dependencies.gradle"

Lorsque vous travaillez avec des projets multi-modules, il est utile de centraliser les dépendances dans un seul emplacement plutôt que de les répartir sur de nombreux fichiers de construction, en particulier pour les bibliothèques communes telles que les bibliothèques de support Android et les bibliothèques Firebase .

Une méthode recommandée consiste à séparer les fichiers de construction Gradle, avec un build.gradle par module, ainsi qu’un dans la racine du projet et un autre pour les dépendances, par exemple:

root
  +- gradleScript/
  |     dependencies.gradle
  +- module1/
  |     build.gradle
  +- module2/
  |     build.gradle
  +- build.gradle

Ensuite, toutes vos dépendances peuvent être situées dans gradleScript/dependencies.gradle :

ext {
    // Version
    supportVersion = '24.1.0'

    // Support Libraries dependencies
    supportDependencies = [
            design:            "com.android.support:design:${supportVersion}",
            recyclerView:      "com.android.support:recyclerview-v7:${supportVersion}",
            cardView:          "com.android.support:cardview-v7:${supportVersion}",
            appCompat:         "com.android.support:appcompat-v7:${supportVersion}",
            supportAnnotation: "com.android.support:support-annotations:${supportVersion}",
    ]

    firebaseVersion = '9.2.0';

    firebaseDependencies = [
            core:         "com.google.firebase:firebase-core:${firebaseVersion}",
            database:     "com.google.firebase:firebase-database:${firebaseVersion}",
            storage:      "com.google.firebase:firebase-storage:${firebaseVersion}",
            crash:        "com.google.firebase:firebase-crash:${firebaseVersion}",
            auth:         "com.google.firebase:firebase-auth:${firebaseVersion}",
            messaging:    "com.google.firebase:firebase-messaging:${firebaseVersion}",
            remoteConfig: "com.google.firebase:firebase-config:${firebaseVersion}",
            invites:      "com.google.firebase:firebase-invites:${firebaseVersion}",
            adMod:        "com.google.firebase:firebase-ads:${firebaseVersion}",
            appIndexing:  "com.google.android.gms:play-services-appindexing:${firebaseVersion}",
    ];
}

Ce qui peut alors être appliqué à partir de ce fichier dans le fichier de niveau supérieur build.gradle comme ceci:

// Load dependencies
apply from: 'gradleScript/dependencies.gradle'

et dans le module1/build.gradle comme ceci:

// Module build file
dependencies {
    // ...
    compile supportDependencies.appCompat
    compile supportDependencies.design
    compile firebaseDependencies.crash
}

Une autre approche

Une approche moins détaillée pour centraliser les versions de dépendances de bibliothèque peut être obtenue en déclarant une fois le numéro de version comme variable et en l'utilisant partout.

Dans la racine de l'espace de travail, build.gradle ajoute ceci:

ext.v = [
    supportVersion:'24.1.1',
]

Et dans chaque module qui utilise la même bibliothèque, ajoutez les bibliothèques nécessaires

compile "com.android.support:support-v4:${v.supportVersion}"
compile "com.android.support:recyclerview-v7:${v.supportVersion}"
compile "com.android.support:design:${v.supportVersion}"
compile "com.android.support:support-annotations:${v.supportVersion}"

Structure de répertoire pour les ressources spécifiques aux saveurs

Les différentes versions des applications peuvent contenir des ressources différentes. Pour créer une ressource spécifique à une saveur, créez un répertoire avec le nom en minuscule de votre saveur dans le répertoire src et ajoutez vos ressources de la même manière que vous le feriez normalement.

Par exemple, si vous aviez un Development saveur et que vous souhaitiez lui fournir une icône de lanceur distincte, vous src/development/res/drawable-mdpi un répertoire src/development/res/drawable-mdpi et créez un fichier ic_launcher.png avec votre icône de développement.

La structure de répertoire ressemblera à ceci:

src/
  main/
    res/
      drawable-mdpi/
        ic_launcher.png  <-- the default launcher icon
  development/
    res/
      drawable-mdpi/
        ic_launcher.png  <-- the launcher icon used when the product flavor is 'Development'

(Bien sûr, dans ce cas, vous créeriez également des icônes pour drawable-hdpi, drawable-xhdpi, etc. ).

Pourquoi y a-t-il deux fichiers build.gradle dans un projet Android Studio?

<PROJECT_ROOT>\app\build.gradle est spécifique au module d'application .

<PROJECT_ROOT>\build.gradle est un "fichier de construction de premier niveau" dans lequel vous pouvez ajouter des options de configuration communes à tous les sous-projets / modules.

Si vous utilisez un autre module dans votre projet, en tant que bibliothèque locale, vous auriez un autre fichier build.gradle : <PROJECT_ROOT>\module\build.gradle

Dans le fichier de niveau supérieur, vous pouvez spécifier des propriétés communes en tant que bloc de génération ou certaines propriétés communes.

buildscript {
    repositories {
        mavenCentral()
    }

    dependencies {
       classpath 'com.android.tools.build:gradle:2.2.0'
       classpath 'com.google.gms:google-services:3.0.0'
    }
}

ext {
    compileSdkVersion = 23
    buildToolsVersion = "23.0.1"
}

Dans l' app\build.gradle vous ne définissez que les propriétés du module:

apply plugin: 'com.android.application'


android {
    compileSdkVersion rootProject.ext.compileSdkVersion
    buildToolsVersion rootProject.ext.buildToolsVersion
}

dependencies {
    //.....
}

Exécuter un script shell à partir de gradle

Un script shell est un moyen très polyvalent d'étendre votre build à tout ce que vous pouvez imaginer.

En guise d'exemple, voici un script simple pour compiler des fichiers protobuf et ajouter les fichiers Java de résultat au répertoire source pour une compilation supplémentaire:

def compilePb() {
    exec {
        // NOTICE: gradle will fail if there's an error in the protoc file...
        executable "../pbScript.sh"
    }
}

project.afterEvaluate {
    compilePb()
}

Le script shell 'pbScript.sh' pour cet exemple, situé dans le dossier racine du projet:

#!/usr/bin/env bash
pp=/home/myself/my/proto

/usr/local/bin/protoc -I=$pp \
 --java_out=./src/main/java \
  --proto_path=$pp \
 $pp/my.proto \
 --proto_path=$pp \
 $pp/my_other.proto

Déboguer vos erreurs Gradle

Ce qui suit est un extrait de Gradle - Quelle est une valeur de sortie non nulle et comment puis-je la corriger? , voir pour la discussion complète.

Disons que vous développez une application et que vous obtenez une erreur de Gradle qui apparaît généralement comme telle.

:module:someTask FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':module:someTask'.
> some message here...  finished with non-zero exit value X
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
BUILD FAILED
Total time: Y.ZZ secs

Vous recherchez ici votre problème sur StackOverflow, et les gens disent de nettoyer et de reconstruire votre projet ou d'activer MultiDex , et lorsque vous essayez cela, cela ne résout tout simplement pas le problème.

Il existe des moyens d'obtenir plus d'informations , mais la sortie de Gradle elle-même doit indiquer l'erreur réelle dans les quelques lignes au-dessus du message entre: module:someTask FAILED et le dernier :module:someOtherTask qui a réussi. Par conséquent, si vous posez une question sur votre erreur, veuillez modifier vos questions pour inclure plus de contexte à l'erreur.

Donc, vous obtenez une "valeur de sortie non nulle". Eh bien, ce nombre est un bon indicateur de ce que vous devriez essayer de corriger. En voici quelques-unes les plus fréquentes.

  • 1 est juste un code d'erreur général et l'erreur est probable dans la sortie Gradle
  • 2 semble être lié à des dépendances qui se chevauchent ou à une mauvaise configuration du projet.
  • 3 semble être d'inclure trop de dépendances, ou un problème de mémoire.

Les solutions générales pour ce qui précède (après avoir tenté un nettoyage et une reconstruction du projet) sont les suivantes:

  • 1 - Résoudre l'erreur mentionnée. En général, il s'agit d'une erreur de compilation, ce qui signifie qu'une partie de code de votre projet n'est pas valide. Cela inclut à la fois XML et Java pour un projet Android.
  • 2 & 3 - Plusieurs réponses vous indiquent d'activer le multidex . Bien qu'il puisse résoudre le problème, il s'agit probablement d'une solution de contournement. Si vous ne comprenez pas pourquoi vous l'utilisez (voir le lien), vous n'en avez probablement pas besoin. Les solutions générales impliquent de réduire la surutilisation des dépendances de bibliothèque (comme tous les services Google Play, par exemple, lorsque vous n’utilisez qu’une seule bibliothèque, par exemple Maps ou Sign-In).

Spécification de différents ID d'application pour les types de construction et les variantes de produit

Vous pouvez spécifier différents ID d'application ou noms de package pour chaque buildType ou productFlavor utilisant l'attribut de configuration applicationIdSuffix :

Exemple de suffixe de l’ applicationId pour chaque buildType :

defaultConfig {
    applicationId "com.package.android"
    minSdkVersion 17
    targetSdkVersion 23
    versionCode 1
    versionName "1.0"
}

buildTypes {
    release {
        debuggable false      
    }

    development {
        debuggable true
        applicationIdSuffix ".dev"
    }

    testing {
        debuggable true
        applicationIdSuffix ".qa"
    }
}

Nos applicationIds résultantes seraient désormais:

  • com.package.android pour release
  • com.package.android. dev pour le development
  • com.package.android. qa pour testing

Cela peut aussi être fait pour productFlavors :

productFlavors {
    free {
        applicationIdSuffix ".free"
    }
    paid {
        applicationIdSuffix ".paid"
    }
}

L' applicationIds résultante serait:

  • com.package.android. gratuit pour la saveur free
  • com.package.android. payé pour la saveur paid

Signer APK sans exposer le mot de passe du magasin de clés

Vous pouvez définir la configuration de signature pour signer le fichier build.gradle dans le fichier build.gradle en utilisant ces propriétés:

  • storeFile : le fichier de storeFile
  • storePassword : le mot de passe du storePassword
  • keyAlias : un nom d'alias de clé
  • keyPassword : un mot de passe alias de clé

Dans de nombreux cas, vous devrez peut-être éviter ce genre d’informations dans le fichier build.gradle .

Méthode A: Configurer la signature de version à l'aide d'un fichier keystore.properties

Il est possible de configurer le build.gradle votre application pour qu'il lise vos informations de configuration de signature à partir d'un fichier de propriétés tel que keystore.properties .

Mettre en place une telle signature est bénéfique car:

  • Vos informations de configuration de signature sont distinctes de votre fichier build.gradle
  • Vous n'avez pas besoin d'intervenir pendant le processus de signature pour fournir des mots de passe pour votre fichier de clés.
  • Vous pouvez facilement exclure le fichier keystore.properties du contrôle de version

Tout d'abord, créez un fichier appelé keystore.properties à la racine de votre projet avec un contenu comme celui-ci (en remplaçant les valeurs par les vôtres):

storeFile=keystore.jks
storePassword=storePassword
keyAlias=keyAlias
keyPassword=keyPassword

Maintenant, dans le fichier build.gradle votre application, configurez le bloc signingConfigs comme suit:

android {
...

    signingConfigs {
        release {
            def propsFile = rootProject.file('keystore.properties')
            if (propsFile.exists()) {
                def props = new Properties()
                props.load(new FileInputStream(propsFile))
                storeFile = file(props['storeFile'])
                storePassword = props['storePassword']
                keyAlias = props['keyAlias']
                keyPassword = props['keyPassword']
            }
        }
    }
}

C'est tout ce qu'il y a à faire, mais n'oubliez pas d'exclure votre fichier de clés et votre fichier keystore.properties du contrôle de version .

Quelques points à noter:

  • Le chemin storeFile spécifié dans le fichier keystore.properties doit être relatif au fichier build.gradle votre application. Cet exemple suppose que le fichier de clés se trouve dans le même répertoire que le fichier build.gradle l'application.
  • Cet exemple contient le fichier keystore.properties à la racine du projet. Si vous le placez ailleurs, veillez à changer la valeur dans rootProject.file('keystore.properties') à l'emplacement de votre compte, par rapport à la racine de votre projet.

Méthode B: En utilisant une variable d'environnement

La même chose peut être réalisée sans fichier de propriétés, ce qui rend le mot de passe plus difficile à trouver:

android {

  signingConfigs {
    release {
        storeFile file('/your/keystore/location/key')
        keyAlias 'your_alias'
        String ps = System.getenv("ps")
        if (ps == null) {
             throw new GradleException('missing ps env variable')
        }
        keyPassword ps
        storePassword ps
    }
}

La variable d'environnement "ps" peut être globale, mais une approche plus sûre peut être en l'ajoutant uniquement au shell d'Android Studio.
Dans Linux, cela peut être fait en éditant Desktop Entry Android Studio

Exec=sh -c "export ps=myPassword123 ; /path/to/studio.sh"

Vous pouvez trouver plus de détails dans cette rubrique .

Gestion des versions de votre build via le fichier "version.properties"

Vous pouvez utiliser Gradle pour incrémenter automatiquement la version de votre package à chaque fois que vous la créez. Pour ce faire, créez un fichier version.properties dans le même répertoire que votre build.gradle avec le contenu suivant:

VERSION_MAJOR=0
VERSION_MINOR=1
VERSION_BUILD=1

(Changer les valeurs pour majeur et mineur comme bon vous semble). Ensuite, dans votre build.gradle ajoutez le code suivant à la section android :

// Read version information from local file and increment as appropriate
def versionPropsFile = file('version.properties')
if (versionPropsFile.canRead()) {
  def Properties versionProps = new Properties()

  versionProps.load(new FileInputStream(versionPropsFile))

  def versionMajor = versionProps['VERSION_MAJOR'].toInteger()
  def versionMinor = versionProps['VERSION_MINOR'].toInteger()
  def versionBuild = versionProps['VERSION_BUILD'].toInteger() + 1

  // Update the build number in the local file
  versionProps['VERSION_BUILD'] = versionBuild.toString()
  versionProps.store(versionPropsFile.newWriter(), null)

  defaultConfig {
    versionCode versionBuild
    versionName "${versionMajor}.${versionMinor}." + String.format("%05d", versionBuild)
  }
}

Les informations sont accessibles en Java sous forme de chaîne BuildConfig.VERSION_NAME pour le BuildConfig.VERSION_NAME complet {major}. { BuildConfig.VERSION_NAME }. { BuildConfig.VERSION_CODE } et en tant BuildConfig.VERSION_CODE pour le numéro de build uniquement.

Modification du nom apk de la sortie et ajout du nom de la version:

C'est le code pour changer le nom du fichier d'application de sortie (.apk). Le nom peut être configuré en affectant une valeur différente à newName

android {

    applicationVariants.all { variant ->
        def newName = "ApkName";
        variant.outputs.each { output ->
            def apk = output.outputFile;

            newName += "-v" + defaultConfig.versionName;
            if (variant.buildType.name == "release") {
                newName += "-release.apk";
            } else {
                newName += ".apk";
            }
            if (!output.zipAlign) {
                newName = newName.replace(".apk", "-unaligned.apk");
            }

            output.outputFile = new File(apk.parentFile, newName);
            logger.info("INFO: Set outputFile to " 
                        + output.outputFile 
                        + " for [" + output.name + "]");
        }
    }
}

Désactiver la compression d'image pour une taille de fichier APK plus petite

Si vous optimisez toutes les images manuellement, désactivez APT Cruncher pour une taille de fichier APK plus petite.

android {
    
    aaptOptions {
        cruncherEnabled = false
    }
}

Activer Proguard en utilisant gradle

Pour activer les configurations Proguard pour votre application, vous devez l'activer dans votre fichier de gradation au niveau du module. Vous devez définir la valeur de minifyEnabled sur true .

buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

Le code ci-dessus appliquera vos configurations Proguard contenues dans le SDK Android par défaut combiné au fichier "proguard-rules.pro" de votre module à votre apk publiée.

Activer le support expérimental du plug-in NDK pour Gradle et AndroidStudio

Activez et configurez le plug-in expérimental Gradle pour améliorer le support NDK d'AndroidStudio. Vérifiez que vous remplissez les conditions suivantes:

  • Gradle 2.10 (pour cet exemple)
  • Android NDK r10 ou supérieur
  • SDK Android avec les outils de compilation v19.0.0 ou version ultérieure

Configurer le fichier MyApp / build.gradle

Editez la ligne dependencies.classpath dans build.gradle à partir par exemple

classpath 'com.android.tools.build:gradle:2.1.2'

à

classpath 'com.android.tools.build:gradle-experimental:0.7.2'

(v0.7.2 était la dernière version au moment de l'écriture. Vérifiez la dernière version vous-même et adaptez votre ligne en conséquence)

Le fichier build.gradle doit ressembler à ceci:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle-experimental:0.7.2'
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

Configurez le fichier MyApp / app / build.gradle

Modifiez le fichier build.gradle pour qu'il ressemble à l'exemple suivant. Vos numéros de version peuvent être différents.

apply plugin: 'com.android.model.application'

model {
    android {
        compileSdkVersion 19
        buildToolsVersion "24.0.1"

        defaultConfig {
            applicationId "com.example.mydomain.myapp"
            minSdkVersion.apiLevel 19
            targetSdkVersion.apiLevel 19
            versionCode 1
            versionName "1.0"
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles.add(file('proguard-android.txt'))
            }
        }
        ndk {
            moduleName "myLib"
            
            /* The following lines are examples of a some optional flags that 
               you may set to configure your build environment
            */ 
            cppFlags.add("-I${file("path/to/my/includes/dir")}".toString())
            cppFlags.add("-std=c++11")
            ldLibs.addAll(['log', 'm'])
            stl = "c++_static"
            abiFilters.add("armeabi-v7a")
        }
    }
}

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

Synchronisez et vérifiez qu'il n'y a pas d'erreurs dans les fichiers Gradle avant de continuer.

Tester si le plugin est activé

Assurez-vous d'abord d'avoir téléchargé le module Android NDK. Créez ensuite une nouvelle application dans AndroidStudio et ajoutez les éléments suivants au fichier ActivityMain:

public class MainActivity implements Activity {
    onCreate() {
        // Pregenerated code. Not important here
    }
    static {
        System.loadLibrary("myLib");
    }
    public static native String getString();
}

La partie getString() doit être surlignée en rouge pour indiquer que la fonction JNI correspondante est introuvable. Passez votre souris sur l'appel de fonction jusqu'à ce qu'une ampoule rouge apparaisse. Cliquez sur l'ampoule et sélectionnez create function JNI_... Cela devrait générer un fichier myLib.c dans le répertoire myApp / app / src / main / jni avec l'appel de fonction JNI correct. Cela devrait ressembler à ceci:

#include <jni.h>

JNIEXPORT jstring JNICALL 
Java_com_example_mydomain_myapp_MainActivity_getString(JNIEnv *env, jobject instance)     
{
    // TODO

    return (*env)->NewStringUTF(env, returnValue);
}

Si cela ne ressemble pas à ceci, alors le plugin n'a pas été correctement configuré ou le NDK n'a pas été téléchargé

Afficher toutes les tâches du projet de graduation

gradlew tasks -- show all tasks

 

Android tasks
-------------
androidDependencies - Displays the Android dependencies of the project.
signingReport - Displays the signing info for each variant.
sourceSets - Prints out all the source sets defined in this project.

Build tasks
-----------
assemble - Assembles all variants of all applications and secondary packages.
assembleAndroidTest - Assembles all the Test applications.
assembleDebug - Assembles all Debug builds.
assembleRelease - Assembles all Release builds.
build - Assembles and tests this project.
buildDependents - Assembles and tests this project and all projects that depend on it.
buildNeeded - Assembles and tests this project and all projects it depends on.
classes - Assembles main classes.
clean - Deletes the build directory.
compileDebugAndroidTestSources
compileDebugSources
compileDebugUnitTestSources
compileReleaseSources
compileReleaseUnitTestSources
extractDebugAnnotations - Extracts Android annotations for the debug variant into the archive file
extractReleaseAnnotations - Extracts Android annotations for the release variant into the archive file
jar - Assembles a jar archive containing the main classes.
mockableAndroidJar - Creates a version of android.jar that's suitable for unit tests.
testClasses - Assembles test classes.

Build Setup tasks
-----------------
init - Initializes a new Gradle build. [incubating]
wrapper - Generates Gradle wrapper files. [incubating]

Documentation tasks
-------------------
javadoc - Generates Javadoc API documentation for the main source code.

Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in root project 'LeitnerBoxPro'.
components - Displays the components produced by root project 'LeitnerBoxPro'. [incubating]
dependencies - Displays all dependencies declared in root project 'LeitnerBoxPro'.
dependencyInsight - Displays the insight into a specific dependency in root project 'LeitnerBoxPro'.
help - Displays a help message.
model - Displays the configuration model of root project 'LeitnerBoxPro'. [incubating]
projects - Displays the sub-projects of root project 'LeitnerBoxPro'.
properties - Displays the properties of root project 'LeitnerBoxPro'.
tasks - Displays the tasks runnable from root project 'LeitnerBoxPro' (some of the displayed tasks may belong to subprojects)
.

Install tasks
-------------
installDebug - Installs the Debug build.
installDebugAndroidTest - Installs the android (on device) tests for the Debug build.
uninstallAll - Uninstall all applications.
uninstallDebug - Uninstalls the Debug build.
uninstallDebugAndroidTest - Uninstalls the android (on device) tests for the Debug build.
uninstallRelease - Uninstalls the Release build.

Verification tasks
------------------
check - Runs all checks.
connectedAndroidTest - Installs and runs instrumentation tests for all flavors on connected devices.
connectedCheck - Runs all device checks on currently connected devices.
connectedDebugAndroidTest - Installs and runs the tests for debug on connected devices.
deviceAndroidTest - Installs and runs instrumentation tests using all Device Providers.
deviceCheck - Runs all device checks using Device Providers and Test Servers.
lint - Runs lint on all variants.
lintDebug - Runs lint on the Debug build.
lintRelease - Runs lint on the Release build.
test - Run unit tests for all variants.
testDebugUnitTest - Run unit tests for the debug build.
testReleaseUnitTest - Run unit tests for the release build.

Other tasks
-----------
assembleDefault
clean
jarDebugClasses
jarReleaseClasses
transformResourcesWithMergeJavaResForDebugUnitTest
transformResourcesWithMergeJavaResForReleaseUnitTest

Supprimer automatiquement "non aligné" apk

Si vous n'avez pas besoin de fichiers apk générés automatiquement avec un suffixe unaligned (que vous n'avez probablement pas), vous pouvez ajouter le code suivant au fichier build.gradle :

// delete unaligned files
android.applicationVariants.all { variant ->
  variant.assemble.doLast {
    variant.outputs.each { output ->
        println "aligned " + output.outputFile
        println "unaligned " + output.packageApplication.outputFile

        File unaligned = output.packageApplication.outputFile;
        File aligned = output.outputFile
        if (!unaligned.getName().equalsIgnoreCase(aligned.getName())) {
            println "deleting " + unaligned.getName()
            unaligned.delete()
        }
    }
  }
}

D' ici

Ignorer la variante de construction

Pour certaines raisons, vous pouvez ignorer vos variantes de build. Par exemple: vous avez une saveur de produit «fictive» et vous l'utilisez uniquement à des fins de débogage, comme les tests d'unité / d'instrumentation.

Ignorons la variante mockRelease de notre projet. Ouvrez le fichier build.gradle et écrivez:

    // Remove mockRelease as it's not needed.
    android.variantFilter { variant ->
        if (variant.buildType.name.equals('release') && variant.getFlavors().get(0).name.equals('mock')) {
            variant.setIgnore(true);
        }
    }

Voir arbre de dépendance

Utilisez les dépendances de tâches. En fonction de la configuration de vos modules, cela peut être soit des ./gradlew dependencies soit des dépendances de l'application du module ./gradlew :app:dependencies

L'exemple suivant du fichier build.gradle

dependencies {
    compile 'com.android.support:design:23.2.1'
    compile 'com.android.support:cardview-v7:23.1.1'

    compile 'com.google.android.gms:play-services:6.5.87'
}

produira le graphique suivant:

Parallel execution is an incubating feature.
:app:dependencies

------------------------------------------------------------
Project :app
------------------------------------------------------------
. . .
_releaseApk - ## Internal use, do not manually configure ##
+--- com.android.support:design:23.2.1
|    +--- com.android.support:support-v4:23.2.1
|    |    \--- com.android.support:support-annotations:23.2.1
|    +--- com.android.support:appcompat-v7:23.2.1
|    |    +--- com.android.support:support-v4:23.2.1 (*)
|    |    +--- com.android.support:animated-vector-drawable:23.2.1
|    |    |    \--- com.android.support:support-vector-drawable:23.2.1
|    |    |         \--- com.android.support:support-v4:23.2.1 (*)
|    |    \--- com.android.support:support-vector-drawable:23.2.1 (*)
|    \--- com.android.support:recyclerview-v7:23.2.1
|         +--- com.android.support:support-v4:23.2.1 (*)
|         \--- com.android.support:support-annotations:23.2.1
+--- com.android.support:cardview-v7:23.1.1
\--- com.google.android.gms:play-services:6.5.87
     \--- com.android.support:support-v4:21.0.0 -> 23.2.1 (*)

. . .

Ici, vous pouvez voir que le projet inclut directement com.android.support:design version 23.2.1, qui apporte lui-même com.android.support:support-v4 avec la version 23.2.1. Cependant, com.google.android.gms:play-services lui com.google.android.gms:play-services même a une dépendance sur le même support-v4 mais avec une ancienne version 21.0.0, qui est un conflit détecté par gradle.

(*) sont utilisés lorsque gradle ignore le sous-arbre car ces dépendances étaient déjà répertoriées précédemment.

Utilisez gradle.properties pour les versions centralisées de versionnumber / build

Vous pouvez définir les informations de configuration centrales dans

ou faites-le avec le fichier racine gradle.properties

la structure du projet

root
  +- module1/
  |     build.gradle
  +- module2/
  |     build.gradle
  +- build.gradle
  +- gradle.properties

paramètre global pour tous les sous-modules dans gradle.properties

# used for manifest
# todo increment for every release
appVersionCode=19
appVersionName=0.5.2.160726

# android tools settings
appCompileSdkVersion=23
appBuildToolsVersion=23.0.2

utilisation dans un sous-module

apply plugin: 'com.android.application'
android {
    // appXXX are defined in gradle.properties
    compileSdkVersion = Integer.valueOf(appCompileSdkVersion)
    buildToolsVersion = appBuildToolsVersion

    defaultConfig {
        // appXXX are defined in gradle.properties
        versionCode = Long.valueOf(appVersionCode)
        versionName = appVersionName
    }
}

dependencies {
    ...
}

Remarque: Si vous souhaitez publier votre application dans le magasin d’applications F-Droid, vous devez utiliser des chiffres magiques dans le fichier de graduation, sinon le robot f-droid ne peut pas lire le versionnumner actuel pour détecter / vérifier les modifications de version.

Afficher les informations de signature

Dans certaines circonstances (par exemple, l'obtention d'une clé API Google), vous devez rechercher votre empreinte digitale de fichier de clés. Gradle a une tâche pratique qui affiche toutes les informations de signature, y compris les empreintes de clés:

./gradlew signingReport

Ceci est un exemple de sortie:

:app:signingReport
Variant: release
Config: none
----------
Variant: debug
Config: debug
Store: /Users/user/.android/debug.keystore
Alias: AndroidDebugKey
MD5: 25:08:76:A9:7C:0C:19:35:99:02:7B:00:AA:1E:49:CA
SHA1: 26:BE:89:58:00:8C:5A:7D:A3:A9:D3:60:4A:30:53:7A:3D:4E:05:55
Valid until: Saturday 18 June 2044
----------
Variant: debugAndroidTest
Config: debug
Store: /Users/user/.android/debug.keystore
Alias: AndroidDebugKey
MD5: 25:08:76:A9:7C:0C:19:35:99:02:7B:00:AA:1E:49:CA
SHA1: 26:BE:89:58:00:8C:5A:7D:A3:A9:D3:60:4A:30:53:7A:3D:4E:05:55
Valid until: Saturday 18 June 2044
----------
Variant: debugUnitTest
Config: debug
Store: /Users/user/.android/debug.keystore
Alias: AndroidDebugKey
MD5: 25:08:76:A9:7C:0C:19:35:99:02:7B:00:AA:1E:49:CA
SHA1: 26:BE:89:58:00:8C:5A:7D:A3:A9:D3:60:4A:30:53:7A:3D:4E:05:55
Valid until: Saturday 18 June 2044
----------
Variant: releaseUnitTest
Config: none
----------

Définition des types de construction

Vous pouvez créer et configurer des types de construction dans le fichier build.gradle niveau du module build.gradle dans le bloc android {} .

    android {
        ...
        defaultConfig {...}
    
        buildTypes {
            release {
                minifyEnabled true
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
    
            debug {
                applicationIdSuffix ".debug"
            }
        }
    }


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow