Android
Gradle pour Android
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
: lesdependencies
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
- La page d'accueil officielle
- Comment configurer les builds de gradle
- Le plugin android pour gradle
- Android Gradle DSL
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:
- stocker dans un fichier externe
- les stocker dans la définition des variables d'environnement .
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 destoreFile
-
storePassword
: le mot de passe dustorePassword
-
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 fichierkeystore.properties
doit être relatif au fichierbuild.gradle
votre application. Cet exemple suppose que le fichier de clés se trouve dans le même répertoire que le fichierbuild.gradle
l'application. - Cet exemple contient le fichier
keystore.properties
à la racine du projet. Si vous le placez ailleurs, veillez à changer la valeur dansrootProject.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
- un fichier d'inclusion de graduation séparé Centraliser les dépendances via le fichier "dependencies.gradle"
- un fichier de propriétés autonome Contrôle de version de vos builds via le fichier "version.properties"
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" } } }