Zoeken…


Invoering

Gradle is een JVM-gebaseerd buildsysteem waarmee ontwikkelaars scripts op hoog niveau kunnen schrijven die kunnen worden gebruikt om het compilatie- en applicatieproces te automatiseren. Het is een flexibel, op plug-ins gebaseerd systeem, waarmee u verschillende aspecten van het bouwproces kunt automatiseren; inclusief het compileren en ondertekenen van een .jar , downloaden en beheren van externe afhankelijkheden, invoegen van velden in het AndroidManifest of het gebruik van specifieke SDK-versies.

Syntaxis

  • apply plugin : de plug-ins die normaal gesproken alleen 'com.android.application' of 'com.android.library' zouden moeten worden gebruikt.

  • android : de hoofdconfiguratie van uw app

    • compileSdkVersion : de compileer SDK-versie
    • buildToolsVersion : de versie van buildToolsVersion
    • defaultConfig : de standaardinstellingen die kunnen worden overschreven door smaken en defaultConfig
      • applicationId : de applicatie-ID die u bijvoorbeeld in de PlayStore gebruikt, is meestal dezelfde als uw pakketnaam
      • minSdkVersion : de minimaal vereiste SDK-versie
      • targetSdkVersion : De SDK-versie waarmee u compileert (moet altijd de nieuwste zijn)
      • versionCode : Het interne versienummer dat bij elke update groter moet zijn
      • versionName : het versienummer dat de gebruiker kan zien op de pagina met app-details
    • buildTypes : Zie ergens anders (TODO)
  • dependencies : de maven of lokale afhankelijkheden van uw app

    • compile een enkele afhankelijkheid
    • testCompile : een afhankelijkheid voor de unit- of integratietests

Opmerkingen

Zie ook

Gradle voor Android - Uitgebreide documentatie:

Er is nog een tag waar je meer onderwerpen en voorbeelden kunt vinden over het gebruik van gradle in Android.
http://www.riptutorial.com/topic/2092

Een eenvoudig build.gradle-bestand

Dit is een voorbeeld van een standaardbestand build.gradle in een 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 (domeinspecifieke taal)

Elk blok in het bovenstaande bestand wordt een DSL (domeinspecifieke taal) genoemd.


plugins

De eerste regel, apply plugin: 'com.android.application' , past de Android-plug-in voor Gradle toe op de build en stelt het android {} -blok beschikbaar om Android-specifieke build-opties te declareren.

Voor een Android-applicatie :

apply plugin: 'com.android.application'

Voor een Android-bibliotheek :

apply plugin: 'com.android.library'

Inzicht in de DSL's in het bovenstaande voorbeeld

Het tweede deel, het android {...} -blok, is de Android DSL die informatie over uw project bevat.

U kunt bijvoorbeeld de compileSdkVersion die het Android API-niveau specificeert, dat door compileSdkVersion moet worden gebruikt om uw app te compileren.
Het defaultConfig bevat de standaardwaarden voor uw manifest. Je kunt ze override met productaroma's .

U vindt meer info in deze voorbeelden:


afhankelijkheden

Het dependencies wordt buiten het android blok {...} gedefinieerd: dit betekent dat het niet door de Android-plug-in wordt gedefinieerd, maar standaard Gradle is.
Het dependencies geeft aan welke externe bibliotheken (meestal Android-bibliotheken, maar Java-bibliotheken ook geldig zijn) die u in uw app wilt opnemen. Gradle downloadt automatisch deze afhankelijkheden voor u (als er geen lokale kopie beschikbaar is), u hoeft alleen vergelijkbare compile toe te voegen wanneer u nog een bibliotheek wilt toevoegen.

Laten we eens kijken naar een van de hier aanwezige regels:

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

Deze regel zegt eigenlijk

een afhankelijkheid van de Android-ondersteuningsontwerpbibliotheek toevoegen aan mijn project.

Gradle zorgt ervoor dat de bibliotheek wordt gedownload en gepresenteerd, zodat u deze in uw app kunt gebruiken, en de code wordt ook opgenomen in uw app.

Als u bekend bent met Maven, is deze syntaxis de GroupId , een dubbele punt, ArtifactId , een andere dubbele punt, dan de versie van de afhankelijkheid die u wilt opnemen, waardoor u volledige controle hebt over versiebeheer.

Hoewel het mogelijk is om artefactversies op te geven met behulp van het plusteken (+), kunt u dit het beste vermijden; het kan tot problemen leiden als de bibliotheek zonder uw medeweten wordt bijgewerkt met het doorbreken van wijzigingen, wat waarschijnlijk zou leiden tot crashes in uw app.

U kunt verschillende soorten afhankelijkheden toevoegen:

Bijzondere aandacht moet worden besteed aan de aar flat afhankelijkheden .

U vindt meer informatie in dit onderwerp.

Opmerking over de -v7 in appcompat-v7

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

Dit betekent eenvoudig dat deze bibliotheek ( appcompat ) compatibel is met Android API niveau 7 en hoger.

Opmerking over de junit: junit: 4.12

Dit is het testen van afhankelijkheid voor het testen van eenheden.


Specifieke afhankelijkheden opgeven voor verschillende buildconfiguraties

U kunt opgeven dat een afhankelijkheid alleen mag worden gebruikt voor een bepaalde build configuratie of kunt u verschillende afhankelijkheden definiëren voor de types te bouwen of het product smaken (bv debuggen, testen of release) door gebruik te maken debugCompile , testCompile of releaseCompile plaats van de gebruikelijke compile .

Dit is handig om test- en debuggerelateerde afhankelijkheden uit uw release-build te houden, waardoor uw release- APK zo dun mogelijk blijft en ervoor zorgt dat eventuele foutopsporingsinformatie niet kan worden gebruikt om interne informatie over uw app te verkrijgen.


signingConfig

Met signingConfig kunt u uw signingConfig configureren om keystore informatie op te nemen en ervoor te zorgen dat de APK die met deze configuraties is gebouwd, is ondertekend en klaar is voor Play Store-release.

Hier kunt u een specifiek onderwerp vinden .

Opmerking : het wordt echter niet aanbevolen om de inloggegevens in uw Gradle-bestand te bewaren. Als u de ondertekeningsconfiguraties wilt verwijderen, laat u het gedeelte signingConfigs gewoon weg.
U kunt ze op verschillende manieren opgeven:

Zie dit onderwerp voor meer informatie: APK ondertekenen zonder keystore-wachtwoord bloot te leggen .


Meer informatie over Gradle voor Android vindt u in het speciale Gradle-onderwerp .

Productaroma's definiëren

Productaroma's worden gedefinieerd in het build.gradle bestand in het android { ... } -blok zoals hieronder te zien.

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

Door dit te doen, hebben we nu twee extra productsmaken: free en paid . Elk kan zijn eigen specifieke configuratie en attributen hebben. Bijvoorbeeld, zowel van onze nieuwe smaken heeft een aparte applicationId en versionName dan onze bestaande main smaak (standaard beschikbaar, dus hier niet afgebeeld).

Productspecifieke afhankelijkheden toevoegen

Afhankelijkheden kunnen worden toegevoegd voor een specifieke productsmaak , vergelijkbaar met hoe deze kunnen worden toegevoegd voor specifieke buildconfiguraties.

Neem in dit voorbeeld aan dat we al twee productaroma's hebben gedefinieerd die free en paid (meer over het definiëren van smaken hier ).
We kunnen vervolgens de AdMob-afhankelijkheid voor de free smaak toevoegen, en de Picasso-bibliotheek voor de paid smaak als volgt:

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

Productspecifieke middelen toevoegen

Bronnen kunnen worden toegevoegd voor een specifieke productsmaak .

Neem in dit voorbeeld aan dat we al twee productsmaken hebben gedefinieerd: free en paid . Om aromaspecifieke bronnen voor producten toe te voegen, maken we extra bronmappen naast de hoofdmap main/res map, waaraan we vervolgens zoals gewoonlijk bronnen kunnen toevoegen. Voor dit voorbeeld definiëren we een tekenreeks, status , voor elke productsmaak:

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

De productsmaak specifieke status tekenreeksen de waarde overschrijven status in de main smaak.

Definieer en gebruik Build Configuration Fields

BuildConfigField

Met buildConfigField kunnen buildConfigField lijnen constanten definiëren. Deze constanten zijn tijdens runtime toegankelijk als statische velden van de klasse BuildConfig . Dit kan worden gebruikt om smaken te maken door alle velden in het defaultConfig blok te definiëren en ze naar behoefte te vervangen voor individuele build-smaken.

Dit voorbeeld definieert de builddatum en markeert de build voor productie in plaats van 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'
        }
    }
}

De automatisch gegenereerde <pakketnaam>. BuildConfig .java in de map gen bevat de volgende velden op basis van de bovenstaande instructie:

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

De gedefinieerde velden kunnen nu tijdens runtime in de app worden gebruikt door toegang te krijgen tot de gegenereerde BuildConfig klasse:

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

De resValue in de productFlavors creëert een resource-waarde. Het kan elk type resource zijn ( string , dimen , color , etc.). Dit is vergelijkbaar met het definiëren van een bron in het juiste bestand: bijvoorbeeld het definiëren van tekenreeksen in een bestand strings.xml . Het voordeel is dat degene die in gradle is gedefinieerd, kan worden aangepast op basis van uw productFlavour / buildVariant. Om toegang te krijgen tot de waarde, schrijft u dezelfde code alsof u toegang hebt tot een onderzoek uit het bronnenbestand:

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

Het belangrijkste is dat bronnen die op deze manier zijn gedefinieerd, bestaande bronnen die in bestanden zijn gedefinieerd niet kunnen wijzigen. Ze kunnen alleen nieuwe bronwaarden maken.


Sommige bibliotheken (zoals de Google Maps Android API) vereisen een API-sleutel die in het Manifest wordt verstrekt als een meta-data . Als verschillende sleutels nodig zijn voor foutopsporing en productiebuilds, geeft u een manifestplaatsaanduiding op die is ingevuld door Gradle.

In uw AndroidManifest.xml bestand:

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

En stel vervolgens het veld dienovereenkomstig in in uw build.gradle bestand:

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

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

Het Android- BuildConfig.java genereert automatisch een aantal velden en plaatst deze in BuildConfig.java . Deze velden zijn:

Veld Beschrijving
DEBUG een Boolean waarin wordt vermeld of de app in de foutopsporings- of releasemodus staat
APPLICATION_ID een String die de ID van de toepassing bevat (bijvoorbeeld com.example.app )
BUILD_TYPE een String die het buildtype van de toepassing bevat (meestal debug of release )
FLAVOR een String die de specifieke smaak van de build bevat
VERSION_CODE een int met het versienummer (build).
Dit is hetzelfde als versionCode in build.gradle of versionCode in AndroidManifest.xml
VERSION_NAME een String die de versie (build) naam bevat.
Dit is hetzelfde als versionName in build.gradle of versionName in AndroidManifest.xml

Als u naast het bovenstaande meerdere dimensies van smaak hebt gedefinieerd, heeft elke dimensie zijn eigen waarde. Als u bijvoorbeeld twee smaakdimensies voor color en size hebt u ook de volgende variabelen:

Veld Beschrijving
FLAVOR_color een String met de waarde voor de smaak 'kleur'.
FLAVOR_size een String met de waarde voor de smaak 'grootte'.

Centralisatie van afhankelijkheden via het bestand "dependencies.gradle"

Wanneer u met multimodule-projecten werkt, is het handig om afhankelijkheden op één locatie te centraliseren in plaats van ze over meerdere buildbestanden te verspreiden, vooral voor veelgebruikte bibliotheken zoals de Android-ondersteuningsbibliotheken en de Firebase-bibliotheken .

Een aanbevolen manier is om de build.gradle te scheiden, met één build.gradle per module, evenals een in de project root en een andere voor de afhankelijkheden, bijvoorbeeld:

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

Vervolgens kunnen al uw afhankelijkheden zich bevinden 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}",
    ];
}

Dat kan vervolgens worden toegepast vanuit dat bestand in het bestand build.gradle op het hoogste niveau:

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

en in de module1/build.gradle als volgt:

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

Een andere benadering

Een minder uitgebreide benadering voor het centraliseren van versies van bibliotheekafhankelijkheid kan worden bereikt door het versienummer eenmaal als variabele te declareren en overal te gebruiken.

Voeg in de werkruimte root build.gradle dit toe:

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

En voeg in elke module die dezelfde bibliotheek gebruikt de benodigde bibliotheken toe

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

Directorystructuur voor smaakspecifieke bronnen

Verschillende smaken van applicatie-builds kunnen verschillende bronnen bevatten. Om een smaakspecifieke bron te maken, maakt u een map met de kleine letter van uw smaak in de map src en voegt u uw bronnen op dezelfde manier toe als u normaal zou doen.

Bijvoorbeeld, als je had een smaak Development en wilde een duidelijke launcher icoon voor het zou een map aan te maken bieden src/development/res/drawable-mdpi en in die map aan te maken een ic_launcher.png bestand met je ontwikkeling-specifiek pictogram.

De mapstructuur ziet er als volgt uit:

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'

(Natuurlijk zou u in dit geval ook pictogrammen maken voor drawable-hdpi, drawable-xhdpi enz. ).

Waarom zijn er twee build.gradle-bestanden in een Android Studio-project?

<PROJECT_ROOT>\app\build.gradle is specifiek voor app-module .

<PROJECT_ROOT>\build.gradle is een "Top-level build-bestand" waar u configuratie-opties kunt toevoegen die gemeenschappelijk zijn voor alle subprojecten / modules.

Als u een andere module in uw project gebruikt, zou u als lokale bibliotheek een ander build.gradle bestand hebben: <PROJECT_ROOT>\module\build.gradle

In het hoofdbestand kunt u algemene eigenschappen opgeven als het buildscript-blok of enkele algemene eigenschappen.

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

In de app\build.gradle definieert u alleen de eigenschappen voor de module:

apply plugin: 'com.android.application'


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

dependencies {
    //.....
}

Een shellscript uitvoeren vanuit Gradle

Een shellscript is een zeer veelzijdige manier om je build uit te breiden tot vrijwel alles wat je maar kunt bedenken.

Als een voorbeeld is hier een eenvoudig script om protobuf-bestanden te compileren en de java-bestanden van de resultaten toe te voegen aan de bronmap voor verdere compilatie:

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

project.afterEvaluate {
    compilePb()
}

Het shellscript 'pbScript.sh' voor dit voorbeeld bevindt zich in de hoofdmap van het project:

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

Foutopsporing van uw Gradle-fouten

Het volgende is een fragment uit Gradle - Wat is een exitwaarde die niet nul is en hoe kan ik deze oplossen? , zie het voor de volledige discussie.

Laten we zeggen dat u een applicatie ontwikkelt en dat u een Gradle-fout krijgt die lijkt en die er in het algemeen zo uitziet.

: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

U zoekt hier in StackOverflow naar uw probleem, en mensen zeggen dat u uw project moet opschonen en opnieuw opbouwen, of MultiDex moet inschakelen, en wanneer u dat probeert, lost het gewoon het probleem niet op.

Er zijn manieren om meer informatie te krijgen , maar de uitvoer van Gradle zelf moet wijzen op de werkelijke fout in de paar regels boven dat bericht tussen: module:someTask FAILED en de laatste :module:someOtherTask die is geslaagd. Daarom, als u een vraag over uw fout stelt, moet u uw vragen bewerken om meer context aan de fout toe te voegen.

U krijgt dus een 'niet-nul exit-waarde'. Welnu, dat aantal is een goede indicatie van wat u moet proberen op te lossen. Hier zijn er een paar die het meest voorkomen.

  • 1 is slechts een algemene foutcode en de fout is waarschijnlijk in de uitvoer Gradle
  • 2 lijkt verband te houden met overlappende afhankelijkheden of projectconfiguratie.
  • 3 lijkt afkomstig te zijn van teveel afhankelijkheden, of een geheugenprobleem.

De algemene oplossingen voor het bovenstaande (na een poging tot opschonen en opnieuw opbouwen van het project) zijn:

  • 1 - Los de genoemde fout op. Over het algemeen is dit een compilatiefout, wat betekent dat een stukje code in uw project niet geldig is. Dit omvat zowel XML als Java voor een Android-project.
  • 2 & 3 - Veel antwoorden hier vertellen u dat u multidex moet inschakelen. Hoewel het het probleem kan oplossen, is het waarschijnlijk een oplossing. Als je niet begrijpt waarom je het gebruikt (zie de link), heb je het waarschijnlijk niet nodig. Algemene oplossingen omvatten het terugdringen van uw overmatig gebruik van bibliotheekafhankelijkheid (zoals alle Google Play-services, wanneer u slechts één bibliotheek hoeft te gebruiken, zoals Maps of Sign-In, bijvoorbeeld).

Verschillende toepassings-ID's opgeven voor buildtypen en productaroma's

U kunt verschillende applicatie-ID's of pakketnamen voor elk buildType of productFlavor met behulp van het configuratie-kenmerk applicationIdSuffix :

Voorbeeld van het achtervoegsel van de applicationId voor elk 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"
    }
}

Onze resulterende applicationIds ID applicationIds zouden nu zijn:

  • com.package.android voor release
  • com.package.android. dev voor development
  • com.package.android. qa voor testing

Dit kan ook worden gedaan voor productFlavors :

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

De resulterende applicationIds ID applicationIds zouden zijn:

  • com.package.android. gratis voor de free smaak
  • com.package.android. betaald voor de paid smaak

Onderteken APK zonder het wachtwoord van de sleutelopslag bloot te leggen

U kunt de ondertekeningsconfiguratie definiëren om de apk in het bestand build.gradle te ondertekenen met behulp van deze eigenschappen:

  • storeFile : het keystore-bestand
  • storePassword : het sleutelarchiefwachtwoord
  • keyAlias : een belangrijke aliasnaam
  • keyPassword : een key alias-wachtwoord

In veel gevallen moet u dit soort informatie in het bestand build.gradle .

Methode A: Configureer vrijgave ondertekenen met behulp van een bestand keystore.properties

Het is mogelijk om de build.gradle uw app zo te configureren dat deze uw ondertekeningsconfiguratiegegevens leest uit een eigenschappenbestand zoals keystore.properties .

Zo instellen is voordelig omdat:

  • De configuratie-informatie van uw ondertekening staat los van uw build.gradle bestand
  • U hoeft niet in te grijpen tijdens het ondertekeningsproces om wachtwoorden voor uw keystore-bestand op te geven
  • U kunt het bestand keystore.properties eenvoudig uitsluiten van versiebeheer

Maak eerst een bestand met de naam keystore.properties in de root van uw project met inhoud zoals deze (vervang de waarden door die van uzelf):

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

Stel nu in het build.gradle bestand van uw app het blok signingConfigs als volgt in:

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

Dat is echt alles, maar vergeet niet zowel uw keystore-bestand als uw keystore.properties bestand uit te sluiten van versiebeheer .

Een paar dingen om op te merken:

  • Het storeFile pad dat is opgegeven in het bestand keystore.properties moet relatief zijn ten opzichte van het build.gradle bestand van uw app. In dit voorbeeld wordt ervan uitgegaan dat het keystore-bestand zich in dezelfde map bevindt als het build.gradle bestand van de app.
  • Dit voorbeeld heeft het bestand keystore.properties in de root van het project. Als u het ergens anders plaatst, moet u de waarde in rootProject.file('keystore.properties') in de locatie van uw, ten opzichte van de root van uw project.

Methode B: Door een omgevingsvariabele te gebruiken

Hetzelfde kan ook worden bereikt zonder een eigenschappenbestand, waardoor het wachtwoord moeilijker te vinden is:

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

De omgevingsvariabele "ps" kan globaal zijn, maar een veiligere aanpak kan zijn door deze alleen aan de shell van Android Studio toe te voegen.
In Linux kan dit worden gedaan door de Desktop Entry Android Studio te bewerken

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

U vindt meer informatie in dit onderwerp .

Versiebeheer van uw builds via het bestand "version.properties"

U kunt Gradle gebruiken om uw pakketversie automatisch te verhogen telkens wanneer u deze bouwt. Maak hiervoor een version.properties bestand in dezelfde map als uw build.gradle met de volgende inhoud:

VERSION_MAJOR=0
VERSION_MINOR=1
VERSION_BUILD=1

(Naar eigen inzicht de waarden voor majeur en mineur wijzigen). Voeg vervolgens in je build.gradle de volgende code toe aan het android gedeelte:

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

De informatie is toegankelijk in Java als een string BuildConfig.VERSION_NAME voor het volledige {major}. {Minor}. {Build} nummer en als een geheel getal BuildConfig.VERSION_CODE voor alleen het buildnummer.

Naam van output-apk wijzigen en versienaam toevoegen:

Dit is de code voor het wijzigen van de bestandsnaam van de uitvoertoepassing (.apk). De naam kan worden geconfigureerd door een andere waarde toe te newName aan 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 + "]");
        }
    }
}

Schakel beeldcompressie uit voor een kleinere APK-bestandsgrootte

Als u alle afbeeldingen handmatig optimaliseert, schakelt u APT Cruncher uit voor een kleinere APK-bestandsgrootte.

android {
    
    aaptOptions {
        cruncherEnabled = false
    }
}

Schakel Proguard in met behulp van gradle

Om Proguard-configuraties voor uw toepassing in te schakelen, moet u deze inschakelen in uw gradle-bestand op moduleniveau. U moet de waarde van minifyEnabled op true .

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

De bovenstaande code past uw Proguard-configuraties in de standaard Android SDK in combinatie met het bestand "proguard-rules.pro" op uw module toe op uw vrijgegeven apk.

Schakel experimentele NDK-plug-inondersteuning in voor Gradle en AndroidStudio

Schakel de experimentele Gradle-plug-in in en configureer deze om de NDK-ondersteuning van AndroidStudio te verbeteren. Controleer of u aan de volgende vereisten voldoet:

  • Gradle 2.10 (voor dit voorbeeld)
  • Android NDK r10 of hoger
  • Android SDK met build tools v19.0.0 of hoger

Configureer het bestand MyApp / build.gradle

Bewerk de dependencies.classpath-regel in build.gradle van bijv

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

naar

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

(v0.7.2 was de nieuwste versie op het moment van schrijven. Controleer zelf de nieuwste versie en pas uw regel dienovereenkomstig aan)

Het bestand build.gradle zou er ongeveer zo uit moeten zien:

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

allprojects {
    repositories {
        jcenter()
    }
}

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

Configureer het bestand MyApp / app / build.gradle

Bewerk het bestand build.gradle zodat het lijkt op het volgende voorbeeld. Uw versienummers kunnen er anders uitzien.

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

Synchroniseer en controleer of er geen fouten zijn in de Gradle-bestanden voordat u doorgaat.

Test of plug-in is ingeschakeld

Zorg er eerst voor dat je de Android NDK-module hebt gedownload. Maak vervolgens een nieuwe app in AndroidStudio en voeg het volgende toe aan het ActivityMain-bestand:

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

Het gedeelte getString() moet rood worden gemarkeerd om aan te geven dat de bijbehorende JNI-functie niet is gevonden. Beweeg uw muis over de functieaanroep totdat een rode gloeilamp verschijnt. Klik op de lamp en selecteer create function JNI_... Dit zou een myLib.c-bestand moeten genereren in de map myApp / app / src / main / jni met de juiste JNI-functie-aanroep. Het zou er ongeveer zo uit moeten zien:

#include <jni.h>

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

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

Als het er niet zo uitziet, is de plug-in niet correct geconfigureerd of is de NDK niet gedownload

Toon alle gradle-projecttaken

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

Verwijder "niet-uitgelijnd" apk automatisch

Als u niet automatisch gegenereerde apk-bestanden met unaligned achtervoegsel nodig hebt (wat u waarschijnlijk niet doet), kunt u de volgende code toevoegen aan het bestand 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()
        }
    }
  }
}

Vanaf hier

Negeren van bouwvariant

Om sommige redenen wilt u misschien uw build-varianten negeren. Bijvoorbeeld: u hebt een 'nep' productsmaak en u gebruikt deze alleen voor foutopsporingsdoeleinden, zoals eenheids- / instrumentatietests.

Laten we de mockRelease- variant uit ons project negeren. Open het build.gradle- bestand en schrijf:

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

Afhankelijkheidsboom zien

Gebruik de taakafhankelijkheden. Afhankelijk van hoe uw modules zijn ingesteld, kan het zijn ./gradlew dependencies of om de afhankelijkheden van het gebruik van de module-app te zien ./gradlew :app:dependencies

Het voorbeeld na het build.gradle-bestand

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

zal de volgende grafiek produceren:

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

. . .

Hier kunt u zien dat het project direct com.android.support:design versie 23.2.1 bevat, die zelf com.android.support:support-v4 met versie 23.2.1 brengt. com.google.android.gms:play-services zelf is echter afhankelijk van dezelfde support-v4 maar met een oudere versie 21.0.0, een conflict dat door gradle wordt gedetecteerd.

(*) worden gebruikt wanneer gradle de substructuur overslaat omdat die afhankelijkheden al eerder werden vermeld.

Gebruik gradle.properties voor centrale versienummer / buildconfiguraties

U kunt centrale configuratiegegevens definiëren in

of doe het met root gradle.properties bestand

de projectstructuur

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

algemene instelling voor alle submodules 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

gebruik in een submodule

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

Opmerking: als u uw app in de F-Droid app store wilt publiceren, moet u magische getallen in het gradle-bestand gebruiken, omdat f-droid robot anders de huidige versienummer niet kan lezen om versiewijzigingen te detecteren / verifiëren.

Toon ondertekeningsinformatie

In sommige omstandigheden (bijvoorbeeld het verkrijgen van een Google API-sleutel) moet u de sleutelafdruk van uw sleutelarchief vinden. Gradle heeft een handige taak die alle ondertekeningsinformatie weergeeft, inclusief keystore-vingerafdrukken:

./gradlew signingReport

Dit is een voorbeelduitvoer:

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

Build-typen definiëren

U kunt configureren maken en types te bouwen in de module-niveau build.gradle bestand in de android {} block.

    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
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow