Ricerca…


introduzione

Gradle è un sistema di build basato su JVM che consente agli sviluppatori di scrivere script di alto livello che possono essere utilizzati per automatizzare il processo di compilazione e produzione di applicazioni. È un sistema flessibile basato su plugin, che consente di automatizzare vari aspetti del processo di creazione; inclusi la compilazione e la firma di un file .jar , il download e la gestione di dipendenze esterne, l'inserimento di campi AndroidManifest o l'utilizzo di versioni specifiche dell'SDK.

Sintassi

  • apply plugin : i plugin che dovrebbero essere usati normalmente solo 'com.android.application' o 'com.android.library' .

  • android : la configurazione principale della tua app

    • compileSdkVersion : la versione di compilazione dell'SDK
    • buildToolsVersion : la versione degli strumenti di compilazione
    • defaultConfig : le impostazioni predefinite che possono essere sovrascritte da sapori e tipi di build
      • applicationId : l'ID dell'applicazione che usi, ad esempio, nel Play Store, quasi uguale al nome del tuo pacchetto
      • minSdkVersion : la versione minima richiesta dell'SDK
      • targetSdkVersion : la versione dell'SDK con cui si compila (dovrebbe essere sempre la nuova)
      • versionCode : il numero di versione interno che deve essere più grande su ciascun aggiornamento
      • versionName : il numero di versione che l'utente può vedere nella pagina dei dettagli dell'app
    • buildTypes : guarda da qualche altra parte (TODO)
  • dependencies : le dependencies Maven o locali della tua app

    • compile una singola dipendenza
    • testCompile : una dipendenza per l'unità o test di integrazione

Osservazioni

Guarda anche

Gradle per Android - Documentazione estesa:

C'è un altro tag dove puoi trovare più argomenti ed esempi sull'uso di gradle in Android.
http://www.riptutorial.com/topic/2092

Un file build.gradle di base

Questo è un esempio di un file build.gradle predefinito in un modulo.

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 (linguaggio specifico del dominio)

Ogni blocco nel file sopra è chiamato DSL (linguaggio specifico del dominio).


plugin

La prima riga, apply plugin: 'com.android.application' , applica il plug-in Android per Gradle alla build e rende disponibile il blocco android {} per dichiarare le opzioni di generazione specifiche per Android.

Per un'applicazione Android :

apply plugin: 'com.android.application'

Per una libreria Android :

apply plugin: 'com.android.library'

Comprendere i DSL nell'esempio sopra

La seconda parte, il blocco android {...} , è il DSL Android che contiene informazioni sul tuo progetto.

Ad esempio, puoi impostare compileSdkVersion che specifica il livello dell'API Android, che dovrebbe essere usato da Gradle per compilare la tua app.
Il sub-blocco defaultConfig contiene i valori predefiniti per il manifest. Puoi override con gli aromi del prodotto .

Puoi trovare maggiori informazioni in questi esempi:


dipendenze

Il blocco delle dependencies è definito al di fuori del blocco android {...} : ciò significa che non è definito dal plug-in Android ma è Gradle standard.
Il blocco delle dependencies specifica quali librerie esterne (tipicamente le librerie Android, ma anche le librerie Java sono valide) che desideri includere nella tua app. Gradle scaricherà automaticamente queste dipendenze per te (se non è disponibile una copia locale), devi semplicemente aggiungere linee di compile simili quando desideri aggiungere un'altra libreria.

Diamo un'occhiata a una delle righe qui presenti:

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

Questa linea dice fondamentalmente

aggiungi una dipendenza dalla libreria di progettazione del supporto Android al mio progetto.

Gradle farà in modo che la libreria sia scaricata e presente in modo che tu possa usarla nella tua app e il suo codice sarà incluso anche nella tua app.

Se hai familiarità con Maven, questa sintassi è GroupId , due punti, ArtifactId , un altro punto, quindi la versione della dipendenza che desideri includere, dandoti il ​​pieno controllo sul controllo delle versioni.

Mentre è possibile specificare le versioni di artefatto usando il segno più (+), la migliore pratica è evitare di farlo; può portare a problemi se la libreria viene aggiornata con interruzioni di modifica a tua insaputa, il che probabilmente causerebbe arresti anomali nella tua app.

Puoi aggiungere diversi tipi di dipendenze:

Un'attenzione particolare dovrebbe essere dedicata alle dipendenze piatte .

Puoi trovare maggiori dettagli in questo argomento.

Nota su -v7 in appcompat-v7

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

Ciò significa semplicemente che questa libreria ( appcompat ) è compatibile con il livello API Android 7 e versioni successive.

Nota sulla junit: junit: 4.12

Questa è la dipendenza del test per il test dell'unità.


Specifica delle dipendenze specifiche per diverse configurazioni di build

È possibile specificare che una dipendenza deve essere utilizzato solo per un determinato configurazione di generazione oppure è possibile definire diverse dipendenze per i tipi di compilazione o dei sapori di prodotti (ad esempio, eseguire il debug, test o di rilascio) utilizzando debugCompile , testCompile o releaseCompile al posto della solita compile .

Questo è utile per mantenere le dipendenze test-debug-correlate fuori dalla build di rilascio, che manterrà il tuo APK release il più sottile possibile e ti aiuterà a garantire che qualsiasi informazione di debug non possa essere utilizzata per ottenere informazioni interne sulla tua app.


signingConfig

signingConfig consente di configurare Gradle in modo da includere le informazioni sul keystore e garantire che l'APK creato utilizzando queste configurazioni sia firmato e pronto per la versione Play Store.

Qui puoi trovare un argomento dedicato .

Nota : non è tuttavia consigliabile mantenere le credenziali di firma all'interno del file Gradle. Per rimuovere le configurazioni di firma, basta omettere la porzione signingConfigs .
Puoi specificarli in diversi modi:

Vedi questo argomento per maggiori dettagli: Firma APK senza esporre la password del keystore .


Puoi trovare ulteriori informazioni su Gradle per Android nell'argomento dedicato di Gradle .

Definire i sapori del prodotto

I sapori del prodotto sono definiti nel file build.gradle all'interno del blocco di android { ... } come mostrato di seguito.

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

In questo modo, ora disponiamo di due ulteriori prodotti: free e a paid . Ciascuno può avere la propria configurazione e attributi specifici. Ad esempio, entrambi i nostri nuovi aromi hanno un applicationId e versioneName versionName rispetto al nostro aroma main esistente (disponibile per impostazione predefinita, quindi non mostrato qui).

Aggiunta di dipendenze specifiche per il gusto del prodotto

Le dipendenze possono essere aggiunte per un determinato gusto del prodotto , in modo simile a come possono essere aggiunte per configurazioni di build specifiche.

Per questo esempio, supponiamo di aver già definito due aromi di prodotto chiamati free e a paid (più sulla definizione degli aromi qui ).
Possiamo quindi aggiungere la dipendenza di AdMob per l'aroma free e la libreria di Picasso per quella a paid modo:

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

Aggiunta di risorse specifiche per il gusto del prodotto

Le risorse possono essere aggiunte per un determinato gusto del prodotto .

Per questo esempio, supponiamo di aver già definito due sapori del prodotto chiamati free e a paid . Per aggiungere risorse specifiche per il gusto del prodotto, creiamo ulteriori cartelle di risorse accanto alla cartella main/res , che possiamo aggiungere come al solito. Per questo esempio, definiremo una stringa, lo status , per ogni gusto del prodotto:

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

Le stringhe di status specifiche per l'aroma del prodotto sostituiranno il valore per lo status nel gusto main .

Definire e utilizzare i Campi configurazione build

BuildConfigField

Gradle consente buildConfigField linee buildConfigField di definire le costanti. Queste costanti saranno accessibili in runtime come campi statici della classe BuildConfig . Questo può essere usato per creare aromi definendo tutti i campi all'interno del blocco defaultConfig , quindi sovrascrivendolo per i singoli sapori di build, se necessario.

Questo esempio definisce la data di costruzione e contrassegna la build per la produzione anziché il test:

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

Il <nome_pacchetto> generato automaticamente. BuildConfig .java nella cartella gen contiene i seguenti campi basati sulla direttiva sopra:

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

I campi definiti possono ora essere utilizzati all'interno dell'app in fase di runtime accedendo alla classe BuildConfig generata:

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

Il resValue nei productFlavors crea un valore di risorsa. Può essere qualsiasi tipo di risorsa ( string , dimen , color , ecc.). Questo è simile alla definizione di una risorsa nel file appropriato: ad es. strings.xml una stringa in un file strings.xml . Il vantaggio è che quello definito in gradle può essere modificato in base al prodotto Flavor / buildVariant. Per accedere al valore, scrivi lo stesso codice come se tu stessi accedendo a una res dal file delle risorse:

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

L'importante è che le risorse definite in questo modo non possano modificare le risorse esistenti definite nei file. Possono solo creare nuovi valori di risorse.


Alcune librerie (come l'API Android di Google Maps) richiedono una chiave API fornita nel Manifesto come tag dei meta-data . Se sono necessarie chiavi diverse per il debug e le build di produzione, specificare un segnaposto manifest compilato da Gradle.

Nel tuo file AndroidManifest.xml :

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

Quindi imposta il campo di conseguenza nel file build.gradle :

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

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

Il sistema di build Android genera automaticamente un numero di campi e li inserisce in BuildConfig.java . Questi campi sono:

Campo Descrizione
DEBUG un Boolean indica se l'app è in modalità di debug o di rilascio
APPLICATION_ID una String contenente l'ID dell'applicazione (es. com.example.app )
BUILD_TYPE una String contenente il tipo di build dell'applicazione (di solito sia il debug che il release )
FLAVOR una String contiene il particolare sapore della build
VERSION_CODE un int contenente il numero della versione (build).
È lo stesso di versionCode in build.gradle o versionCode in AndroidManifest.xml
VERSION_NAME una String contenente il nome della versione (build).
È lo stesso di versionName in build.gradle o versionName in AndroidManifest.xml

In aggiunta a quanto sopra, se hai definito più dimensioni di sapore, ciascuna dimensione avrà il suo valore. Ad esempio, se hai due dimensioni di aroma per color e size avrai anche le seguenti variabili:

Campo Descrizione
FLAVOR_color una String contenente il valore per il sapore "colore".
FLAVOR_size una String contenente il valore per il sapore "taglia".

Centralizzazione delle dipendenze tramite il file "dependencies.gradle"

Quando si lavora con progetti multi-modulo, è utile centralizzare le dipendenze in una singola posizione piuttosto che distribuirle su molti file di build, specialmente per le librerie comuni come le librerie di supporto Android e le librerie Firebase .

Un modo consigliato è quello di separare i file di build di Gradle, con un build.gradle per modulo, nonché uno nella root del progetto e un altro per le dipendenze, ad esempio:

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

Quindi, tutte le tue dipendenze possono trovarsi in 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}",
    ];
}

Quale può quindi essere applicato da quel file nel file di livello superiore build.gradle modo:

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

e nel module1/build.gradle modo:

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

Un altro approccio

Un approccio meno dettagliato per la centralizzazione delle versioni delle dipendenze della libreria può essere ottenuto dichiarando il numero di versione come variabile una volta e utilizzandolo ovunque.

Nell'area di lavoro root build.gradle aggiungere questo:

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

E in ogni modulo che usa la stessa libreria aggiungi le librerie necessarie

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

Struttura della directory per risorse specifiche per il gusto

Diversi tipi di build dell'applicazione possono contenere risorse diverse. Per creare una risorsa specifica per il gusto, crea una directory con il nome in minuscolo del tuo gusto nella directory src e aggiungi le tue risorse nello stesso modo in cui faresti normalmente.

Ad esempio, se si dispone di uno Development sapore e si desidera fornire un'icona di avvio distinta per esso, si creerà una directory src/development/res/drawable-mdpi e all'interno di tale directory creare un file ic_launcher.png con l'icona specifica per lo sviluppo.

La struttura della directory sarà simile a questa:

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'

(Naturalmente, in questo caso si creerebbero anche icone per disegnabili-hdpi, disegnabili-xhdpi, ecc .).

Perché ci sono due file build.gradle in un progetto Android Studio?

<PROJECT_ROOT>\app\build.gradle è specifico per il modulo app .

<PROJECT_ROOT>\build.gradle è un "file di build di livello superiore" in cui è possibile aggiungere opzioni di configurazione comuni a tutti i sottoprogetti / moduli.

Se utilizzi un altro modulo nel tuo progetto, come libreria locale avresti un altro file build.gradle : <PROJECT_ROOT>\module\build.gradle

Nel file di livello superiore è possibile specificare proprietà comuni come blocco di script o alcune proprietà comuni.

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

Nell'app app\build.gradle si definiscono solo le proprietà per il modulo:

apply plugin: 'com.android.application'


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

dependencies {
    //.....
}

Esecuzione di uno script di shell da gradle

Uno script di shell è un modo molto versatile per estendere la tua build a praticamente qualsiasi cosa tu possa pensare.

Come un exmaple, ecco un semplice script per compilare i file di protobuf e aggiungere i file java risultanti alla directory di origine per un'ulteriore compilazione:

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

project.afterEvaluate {
    compilePb()
}

Lo script di shell 'pbScript.sh' per questo esempio, che si trova nella cartella principale del progetto:

#!/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

Eseguire il debug degli errori di Gradle

Quello che segue è un estratto di Gradle - Cos'è un valore di uscita diverso da zero e come lo risolvo? , guardalo per la discussione completa.

Diciamo che stai sviluppando un'applicazione e ottieni un errore di Gradle che sembra che in genere sarà simile a quello.

: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

Cerca qui StackOverflow per il tuo problema e le persone dicono di pulire e ricostruire il tuo progetto, o abilitare MultiDex , e quando lo provi, non risolve il problema.

Ci sono modi per ottenere maggiori informazioni , ma l'output Gradle stesso dovrebbe puntare all'errore effettivo nelle poche righe sopra quel messaggio tra: module:someTask FAILED e l'ultimo :module:someOtherTask che è passato. Pertanto, se fai una domanda sul tuo errore, modifica le tue domande per includere più contesto nell'errore.

Quindi, ottieni un "valore di uscita diverso da zero". Bene, quel numero è un buon indicatore di ciò che dovresti provare a sistemare. Qui ci sono alcuni che si verificano più frequentemente.

  • 1 è solo un codice di errore generale e l'errore è probabile nell'uscita Gradle
  • 2 sembra essere correlato a dipendenze sovrapposte o errata configurazione del progetto.
  • 3 sembra che includa troppe dipendenze o un problema di memoria.

Le soluzioni generali per quanto sopra (dopo aver tentato di pulire e ricostruire il progetto) sono:

  • 1 - Risolvi l'errore menzionato. Generalmente, questo è un errore in fase di compilazione, nel senso che parte del codice nel tuo progetto non è valida. Questo include sia XML che Java per un progetto Android.
  • 2 e 3 - Molte risposte qui ti dicono di abilitare il multidex . Mentre può risolvere il problema, è molto probabile una soluzione alternativa. Se non capisci perché lo stai usando (vedi il link), probabilmente non ne hai bisogno. Le soluzioni generali comportano un taglio eccessivo delle dipendenze della libreria (come tutti i servizi di Google Play, quando è necessario utilizzare solo una libreria, ad esempio Maps o Accesso, ad esempio).

Specifica di diversi ID di applicazione per tipi di build e aromi di prodotto

È possibile specificare gli ID di applicazione diversi o nomi dei pacchetti per ogni buildType o productFlavor utilizzando l'attributo di configurazione applicationIdSuffix:

Esempio di buildType applicationId per ogni 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"
    }
}

I nostri applicationIds risultanti ora sarebbero:

  • com.package.android per il release
  • com.package.android. dev per lo development
  • com.package.android. qa per il testing

Questo può essere fatto anche per productFlavors :

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

Le applicationIds risultanti sarebbero:

  • com.package.android. gratis per il gusto free
  • com.package.android. pagato per il sapore paid

Firma APK senza esporre la password del keystore

È possibile definire la configurazione della firma per firmare l'apk nel file build.gradle utilizzando queste proprietà:

  • storeFile : il file keystore
  • storePassword : la password del keystore
  • keyAlias : un nome alias chiave
  • keyPassword : una password alias chiave

In molti casi potrebbe essere necessario evitare questo tipo di informazioni nel file build.gradle .

Metodo A: Configurare la firma di rilascio utilizzando un file keystore.properties

È possibile configurare build.gradle modo che legga le informazioni sulla configurazione della firma da un file delle proprietà come keystore.properties .

Impostare la firma in questo modo è utile perché:

  • Le informazioni sulla configurazione della firma sono separate dal file build.gradle
  • Non è necessario intervenire durante la procedura di firma per fornire password per il file del keystore
  • È possibile escludere facilmente il file keystore.properties dal controllo di versione

Per prima cosa, crea un file chiamato keystore.properties nella radice del tuo progetto con contenuto come questo (sostituendo i valori con il tuo):

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

Ora, nel file build.gradle della tua app, imposta il blocco signingConfigs come segue:

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

Questo è davvero tutto quello che c'è da fare, ma non dimenticare di escludere sia il file keystore.properties file keystore.properties dal controllo di versione .

Un paio di cose da notare:

  • Il percorso del file storeFile specificato nel file keystore.properties deve essere relativo al file build.gradle dell'app. In questo esempio si presuppone che il file keystore si trovi nella stessa directory del file build.gradle dell'app.
  • Questo esempio ha il file keystore.properties nella radice del progetto. Se lo metti da qualche altra parte, assicurati di cambiare il valore in rootProject.file('keystore.properties') nella posizione del tuo, rispetto alla radice del tuo progetto.

Metodo B: utilizzando una variabile di ambiente

Lo stesso può essere ottenuto anche senza un file di proprietà, rendendo la password più difficile da trovare:

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 variabile di ambiente "ps" può essere globale, ma un approccio più sicuro può essere aggiungendolo alla shell di Android Studio.
In Linux questo può essere fatto modificando la Desktop Entry Android Studio

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

Puoi trovare maggiori dettagli in questo argomento .

Eseguendo il controllo delle versioni tramite il file "version.properties"

Puoi utilizzare Gradle per incrementare automaticamente la versione del pacchetto ogni volta che lo compili. Per fare in modo di creare un version.properties file nella stessa directory del build.gradle con il seguente contenuto:

VERSION_MAJOR=0
VERSION_MINOR=1
VERSION_BUILD=1

(Cambiando i valori per maggiore e minore come meglio credi). Quindi nel tuo build.gradle aggiungi il seguente codice alla sezione 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)
  }
}

È possibile accedere alle informazioni in Java come una stringa BuildConfig.VERSION_NAME per il numero {major}. {Minor}. { BuildConfig.VERSION_NAME } completo e come un intero BuildConfig.VERSION_CODE per il solo numero di build.

Modifica del nome apk di output e aggiunta del nome della versione:

Questo è il codice per cambiare il nome del file dell'applicazione di output (.apk). Il nome può essere configurato assegnando un valore diverso a 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 + "]");
        }
    }
}

Disattiva la compressione dell'immagine per una dimensione file APK più piccola

Se si stanno ottimizzando manualmente tutte le immagini, disabilitare Cruncher APT per una dimensione file APK più piccola.

android {
    
    aaptOptions {
        cruncherEnabled = false
    }
}

Abilita Proguard usando Gradle

Per abilitare le configurazioni Proguard per la tua applicazione devi abilitarlo nel tuo file gradle a livello di modulo. È necessario impostare il valore di minifyEnabled su true .

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

Il codice sopra riportato applicherà le configurazioni Proguard contenute nell'SDK Android predefinito combinato con il file "proguard-rules.pro" sul tuo modulo per l'apk rilasciato.

Abilita il supporto del plug-in NDK sperimentale per Gradle e AndroidStudio

Abilita e configura il plugin Gradle sperimentale per migliorare il supporto NDK di AndroidStudio. Verifica di soddisfare i seguenti requisiti:

  • Gradle 2.10 (per questo esempio)
  • Android NDK r10 o successivo
  • Android SDK con strumenti di compilazione v19.0.0 o versioni successive

Configura il file MyApp / build.gradle

Modifica la linea dependencies.classpath in build.gradle da es

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

a

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

(V0.7.2 era l'ultima versione al momento della stesura. Controlla la versione più recente e adatta la tua linea di conseguenza)

Il file build.gradle dovrebbe essere simile a questo:

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

allprojects {
    repositories {
        jcenter()
    }
}

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

Configura il file MyApp / app / build.gradle

Modifica il file build.gradle in modo che assomigli al seguente esempio. I numeri di versione potrebbero essere diversi.

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

Sincronizzare e controllare che non ci siano errori nei file Gradle prima di procedere.

Verifica se il plugin è abilitato

Innanzitutto assicurati di aver scaricato il modulo NDK di Android. Quindi crea una nuova app in AndroidStudio e aggiungi quanto segue al file ActivityMain:

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

La parte getString() dovrebbe essere evidenziata in rosso per indicare che non è stato possibile trovare la funzione JNI corrispondente. Passa il mouse sopra la chiamata di funzione fino a quando non viene visualizzata una lampadina rossa. Fare clic sulla lampadina e selezionare create function JNI_... Questo dovrebbe generare un file myLib.c nella directory myApp / app / src / main / jni con la chiamata della funzione JNI corretta. Dovrebbe assomigliare a questo:

#include <jni.h>

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

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

Se non sembra così, il plugin non è stato configurato correttamente o l'NDK non è stato scaricato

Mostra tutte le attività del progetto gradle

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

Elimina automaticamente l'apk "non allineato"

Se non hai bisogno di file apk generati automaticamente con suffisso unaligned (cosa che probabilmente non fai), puoi aggiungere il seguente codice al file 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()
        }
    }
  }
}

Da qui

Ignorando la variante di costruzione

Per alcuni motivi potresti voler ignorare le varianti di costruzione. Ad esempio: hai "schernito" l'aroma del prodotto e lo utilizzi solo a scopo di debug, come i test di unità / strumentazione.

Ignoriamo la variante di mockRelease dal nostro progetto. Aprire il file build.gradle e scrivere:

    // 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);
        }
    }

Vedere l'albero delle dipendenze

Usa le dipendenze delle attività. A seconda di come sono configurati i tuoi moduli, possono essere le ./gradlew dependencies o vedere le dipendenze dell'app modulo utilizzare ./gradlew :app:dependencies

L'esempio seguente il file 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'
}

produrrà il seguente grafico:

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 (*)

. . .

Qui puoi vedere che il progetto include direttamente com.android.support:design versione 23.2.1, che a sua volta sta portando com.android.support:support-v4 con la versione 23.2.1. Tuttavia, com.google.android.gms:play-services stessa hanno una dipendenza dallo stesso support-v4 ma con una versione precedente 21.0.0, che è un conflitto rilevato da gradle.

(*) vengono utilizzati quando gradle salta la sottostruttura perché quelle dipendenze erano già elencate in precedenza.

Usa gradle.properties per versionnumber centrale / buildconfigurations

È possibile definire le informazioni di configurazione centrale in

oppure farlo con il file root gradle.properties

la struttura del progetto

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

impostazione globale per tutti i sottomoduli in 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

utilizzo in un sottomodulo

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

Nota: se si desidera pubblicare la propria app nell'app store F-Droid, è necessario utilizzare numeri magici nel file gradle perché altrimenti il ​​robot f-droid non può leggere il versionnumner corrente per rilevare / verificare le modifiche della versione.

Visualizza le informazioni di firma

In alcune circostanze (ad esempio, ottenere una chiave API di Google) è necessario trovare l'impronta digitale del keystore. Gradle ha un compito utile che visualizza tutte le informazioni sulla firma, incluse le impronte digitali del keystore:

./gradlew signingReport

Questo è un esempio di output:

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

Definizione dei tipi di build

È possibile creare e configurare i tipi di build nel file build.gradle livello di build.gradle all'interno del blocco di 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
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow