Suche…


Einführung

Gradle ist ein JVM-basiertes Buildsystem, mit dem Entwickler übergeordnete Skripts schreiben können, mit denen der Kompilierungs- und Anwendungsprozess automatisiert werden kann. Es ist ein flexibles Plugin-basiertes System, mit dem Sie verschiedene Aspekte des Erstellungsprozesses automatisieren können. einschließlich der Zusammenstellung und eine Unterzeichnung .jar , Herunterladen und Verwalten von externen Abhängigkeiten, Injizieren Felder in die AndroidManifest oder spezifische SDK - Versionen verwendet wird .

Syntax

  • apply plugin : Die Plugins, die normalerweise verwendet werden sollten, sind nur 'com.android.application' oder 'com.android.library' .

  • android : Die Hauptkonfiguration Ihrer App

    • compileSdkVersion : Die kompilierte SDK-Version
    • buildToolsVersion : Die Version der Build-Tools
    • defaultConfig : Die Standardeinstellungen, die von Flavors und Build-Typen überschrieben werden können
      • applicationId : Die Anwendungs-ID, die Sie zB im PlayStore verwenden, stimmt im Wesentlichen mit Ihrem Paketnamen überein
      • minSdkVersion : Die minimal erforderliche SDK-Version
      • targetSdkVersion : Die SDK-Version, für die Sie kompilieren (sollte immer die neueste sein)
      • versionCode : Die interne Versionsnummer, die bei jedem Update größer sein muss
      • versionName : Die Versionsnummer, die der Benutzer auf der App- versionName sehen kann
    • buildTypes : Siehe woanders (TODO)
  • dependencies : Die Maven oder lokalen Abhängigkeiten Ihrer App

    • eine einzelne Abhängigkeit compile
    • testCompile : eine Abhängigkeit für die Einheiten- oder Integrationstests

Bemerkungen

Siehe auch

Gradle für Android - Erweiterte Dokumentation:

Es gibt ein weiteres Tag, wo Sie weitere Themen und Beispiele zur Verwendung von Gradle in Android finden können.
http://www.riptutorial.com/topic/2092

Eine grundlegende build.gradle-Datei

Dies ist ein Beispiel für eine Standarddatei build.gradle in einem Modul.

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 (domänenspezifische Sprache)

Jeder Block in der obigen Datei wird als DSL (domänenspezifische Sprache) bezeichnet.


Plugins

Die erste Zeile, apply plugin: 'com.android.application' , wendet das Android-Plugin für Gradle auf den Build an und macht den android {} -Block verfügbar, um Android-spezifische Build-Optionen zu deklarieren.

Für eine Android-Anwendung :

apply plugin: 'com.android.application'

Für eine Android-Bibliothek :

apply plugin: 'com.android.library'

Die DSLs im obigen Beispiel verstehen

Der zweite Teil, der android {...} Block android {...} , ist der Android- DSL der Informationen zu Ihrem Projekt enthält.

Sie können beispielsweise die compileSdkVersion die die Android-API-Ebene angibt. compileSdkVersion sollte von Gradle zum Kompilieren Ihrer App verwendet werden.
Der defaultConfig enthält die defaultConfig für Ihr Manifest. Sie können sie mit Produkt-Flavors override .

Weitere Informationen finden Sie in diesen Beispielen:


Abhängigkeiten

Der dependencies wird außerhalb des android Blocks {...} : Dies bedeutet, dass er nicht vom Android-Plugin definiert wird, sondern der Standardgradle.
Der dependencies gibt an, welche externen Bibliotheken (normalerweise Android-Bibliotheken, aber auch Java-Bibliotheken sind gültig) in Ihre App aufgenommen werden sollen. Gradle lädt diese Abhängigkeiten automatisch herunter (wenn keine lokale Kopie verfügbar ist). Sie müssen nur ähnliche compile hinzufügen compile wenn Sie eine andere Bibliothek hinzufügen möchten.

Schauen wir uns eine der hier dargestellten Zeilen an:

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

Diese Zeile sagt im Grunde

Fügen Sie meinem Projekt eine Abhängigkeit von der Android-Supportdesign-Bibliothek hinzu.

Gradle stellt sicher, dass die Bibliothek heruntergeladen und vorhanden ist, sodass Sie sie in Ihrer App verwenden können. Der Code wird auch in Ihre App aufgenommen.

Wenn Sie mit Maven vertraut sind, handelt es sich bei dieser Syntax um die GroupId , einen Doppelpunkt, ArtifactId , einen weiteren Doppelpunkt und die Version der Abhängigkeit, die Sie einschließen möchten. So haben Sie die vollständige Kontrolle über die Versionierung.

Es ist zwar möglich, Artefaktversionen mithilfe des Pluszeichens (+) anzugeben, dies sollte jedoch vermieden werden. Dies kann zu Problemen führen, wenn die Bibliothek ohne Ihr Wissen mit bahnbrechenden Änderungen aktualisiert wird, was zu Abstürzen in Ihrer App führen könnte.

Sie können verschiedene Arten von Abhängigkeiten hinzufügen:

Ein besonderes Augenmerk sollte den aflachen Abhängigkeiten gewidmet werden .

Weitere Details finden Sie in diesem Thema.

Hinweis zu -v7 in appcompat-v7

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

Dies bedeutet einfach, dass diese Bibliothek ( appcompat ) mit der Android-API-Ebene 7 und weiter kompatibel ist.

Anmerkung zum junit: junit: 4.12

Dies ist die Testabhängigkeit für Unit-Tests.


Festlegen von Abhängigkeiten für verschiedene Build-Konfigurationen

Sie können angeben, dass eine Abhängigkeit nur für eine bestimmte Build-Konfiguration verwendet werden soll, oder Sie können andere Abhängigkeiten für die Build-Typen oder die Produktvarianten (z. B. Debug, Test oder Release) debugCompile , indem Sie debugCompile , testCompile oder releaseCompile anstelle der üblichen compile .

Dies ist hilfreich, um Test- und Debug-abhängige Abhängigkeiten von Ihrem Release-Build fernzuhalten, wodurch Ihr Release- APK so gering wie möglich gehalten wird und sichergestellt wird, dass Debug-Informationen nicht zum Abrufen interner Informationen über Ihre App verwendet werden können.


signingConfig

Mit der signingConfig können Sie Ihren Gradle so konfigurieren, dass er keystore Informationen enthält und sicherstellen, dass die mit diesen Konfigurationen erstellten APK signiert und für die Play Store-Veröffentlichung bereit sind.

Hier finden Sie ein eigenes Thema .

Hinweis : Es wird jedoch nicht empfohlen, die Signaturdaten in Ihrer Gradle-Datei zu speichern. Um die signingConfigs zu entfernen, lassen Sie einfach den signingConfigs Teil aus.
Sie können sie auf verschiedene Arten angeben:

Weitere Informationen finden Sie in diesem Thema: Unterzeichnen Sie APK, ohne das Keystore-Kennwort verfügbar zu machen .


Weitere Informationen zu Gradle für Android finden Sie im entsprechenden Gradle-Thema .

Produktgeschmack definieren

Produktvarianten werden in der build.gradle -Datei innerhalb des android { ... } Blocks android { ... } (siehe unten).

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

Auf diese Weise haben wir jetzt zwei zusätzliche Produktvarianten: free und paid . Jeder kann seine spezifische Konfiguration und Attribute haben. Zum Beispiel hat unsere beiden neuen Geschmacksrichtungen einen separaten applicationId und versionName als unsere bestehenden main Geschmack ( als Standard verfügbar sind , so hier nicht dargestellt).

Hinzufügen produktspezifischer Abhängigkeiten

Abhängigkeiten können für eine bestimmte Produktvariante hinzugefügt werden, ähnlich wie sie für bestimmte Build-Konfigurationen hinzugefügt werden können.

Nehmen Sie für dieses Beispiel an, dass wir bereits zwei Produktvarianten definiert haben, die als free und paid (mehr zur Definition von Geschmacksrichtungen hier ).
Wir können dann die AdMob-Abhängigkeit für die free Variante und die Picasso-Bibliothek für die paid Version hinzufügen:

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

Hinzufügen produktspezifischer Ressourcen

Ressourcen können für einen bestimmten Produktgeschmack hinzugefügt werden.

Nehmen Sie für dieses Beispiel an, dass wir bereits zwei Produktvarianten definiert haben, die als free und paid . Um produktspezifische Ressourcen hinzuzufügen, erstellen wir neben dem main/res Ordner weitere Ressourcenordner, die Sie wie üblich hinzufügen können. In diesem Beispiel definieren wir eine Zeichenfolge ( status ) für jede Produktvariante:

/ 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 / bezahlt /res/values/strings.xml

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

Die produktgeschmacksspezifischen status überschreiben den Wert für den status im main .

Definieren und Verwenden von Build-Konfigurationsfeldern

BuildConfigField

Mit Gradle können buildConfigField mit buildConfigField Linien Konstanten definieren. Auf diese Konstanten kann während der Laufzeit als statische Felder der BuildConfig Klasse BuildConfig . Dies kann zum Erstellen von Flavors verwendet werden, indem alle Felder im defaultConfig Block definiert und bei Bedarf für einzelne Build-Flavors überschrieben werden.

In diesem Beispiel wird das Erstellungsdatum definiert und der Build für die Produktion und nicht für den Test markiert:

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

Der automatisch generierte <Paketname>. BuildConfig .java im Ordner gen enthält folgende Felder, die auf der obigen Anweisung basieren:

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

Die definierten Felder können jetzt zur Laufzeit innerhalb der App verwendet werden, indem auf die generierte BuildConfig Klasse BuildConfig :

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

Der resValue in den productFlavors erstellt einen Ressourcenwert. Dabei kann es sich um einen beliebigen Ressourcentyp handeln ( string , dimen , color usw.). Dies ist vergleichbar mit dem Definieren einer Ressource in der entsprechenden Datei: z. B. Definieren einer Zeichenfolge in einer Datei strings.xml . Der Vorteil besteht darin, dass der in Gradle definierte Wert basierend auf Ihrem productFlavor / buildVariant geändert werden kann. Um auf den Wert zuzugreifen, schreiben Sie den gleichen Code, als würden Sie aus der Ressourcendatei auf ein Res zugreifen:

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

Das Wichtigste ist, dass auf diese Weise definierte Ressourcen die in Dateien definierten Ressourcen nicht ändern können. Sie können nur neue Ressourcenwerte erstellen.


Einige Bibliotheken (z. B. Google Maps Android API) erfordern einen API-Schlüssel, der im Manifest als meta-data Tag bereitgestellt wird. Wenn für das Debugging und die Erstellung von Builds andere Schlüssel erforderlich sind, geben Sie einen durch Gradle ausgefüllten Platzhalter für Manifest an.

In Ihrer AndroidManifest.xml Datei:

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

build.gradle dann das Feld in Ihrer build.gradle -Datei entsprechend ein:

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

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

Das Android-Buildsystem generiert eine Reihe von Feldern automatisch und platziert sie in BuildConfig.java . Diese Felder sind:

Feld Beschreibung
DEBUG Ein Boolean Wert, der angibt, ob sich die App im Debug- oder Freigabemodus befindet
APPLICATION_ID einen String mit der ID der Anwendung (zB com.example.app )
BUILD_TYPE ein String , der den Build-Typ der Anwendung enthält (normalerweise debug oder release )
FLAVOR Eine String die den bestimmten Geschmack des Builds enthält
VERSION_CODE ein int das die Versionsnummer (Build-Nummer) enthält.
Dies ist die gleiche wie versionCode in build.gradle oder versionCode in AndroidManifest.xml
VERSION_NAME Ein String , der den Versionsnamen (Build) enthält.
Dies ist das gleiche wie versionName in build.gradle oder versionName in AndroidManifest.xml

Wenn Sie mehrere Flavordimensionen definiert haben, hat jede Dimension ihren eigenen Wert. Wenn Sie zum Beispiel zwei Geschmacksdimensionen für color und size Sie auch die folgenden Variablen:

Feld Beschreibung
FLAVOR_color eine String die den Wert für den Farbton enthält.
FLAVOR_size eine String die den Wert für den 'size'-Flavor enthält.

Abhängigkeiten über "dependencies.gradle" -Datei zentralisieren

Bei der Arbeit mit Projekten mit mehreren Modulen ist es hilfreich, Abhängigkeiten an einem einzigen Ort zu zentralisieren, anstatt sie auf viele Build-Dateien zu verteilen, insbesondere für gängige Bibliotheken wie die Android-Support-Bibliotheken und die Firebase-Bibliotheken .

Eine empfohlene Methode besteht darin, die Gradle-Build-Dateien mit einem build.gradle pro Modul sowie einer im Projektstammverzeichnis und einer für die Abhängigkeiten voneinander zu trennen. Beispiel:

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

Alle Ihre Abhängigkeiten können sich dann 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}",
    ];
}

Die kann dann aus dieser Datei in der obersten Datei build.gradle wie build.gradle werden:

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

und in der module1/build.gradle so:

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

Ein anderer Ansatz

Ein weniger ausführlicher Ansatz zur Zentralisierung von Bibliotheksabhängigkeitsversionen kann erreicht werden, indem die Versionsnummer einmal als Variable deklariert und überall verwendet wird.

build.gradle Sie im Arbeitsbereich root build.gradle hinzu:

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

Fügen Sie in jedem Modul, das dieselbe Bibliothek verwendet, die benötigten Bibliotheken hinzu

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

Verzeichnisstruktur für geschmacksspezifische Ressourcen

Verschiedene Arten von Anwendungserstellungen können unterschiedliche Ressourcen enthalten. Um eine Flavour-spezifische Ressource zu erstellen, erstellen Sie im src Verzeichnis ein Verzeichnis mit dem Kleinbuchstaben Ihrer Flavour und fügen Sie Ihre Ressourcen auf die gleiche Weise hinzu, wie Sie es normalerweise tun würden.

Zum Beispiel hatten , wenn Sie einen Geschmack Development und wollten ein deutliches Launcher - Symbol dafür zur Verfügung zu stellen Sie ein Verzeichnis erstellen würden src/development/res/drawable-mdpi und in diesem Verzeichnis eine erstellen ic_launcher.png Datei mit entwicklungsspezifischen Symbol.

Die Verzeichnisstruktur sieht folgendermaßen aus:

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'

(In diesem Fall würden Sie natürlich auch Symbole für drawable-hdpi, drawable-xhdpi usw. erstellen).

Warum gibt es in einem Android Studio-Projekt zwei build.gradle-Dateien?

<PROJECT_ROOT>\app\build.gradle ist spezifisch für das App-Modul .

<PROJECT_ROOT>\build.gradle ist eine "Build-Datei der obersten Ebene", in der Sie Konfigurationsoptionen hinzufügen können, die für alle Unterprojekte / Module gelten.

Wenn Sie ein anderes Modul in Ihrem Projekt verwenden, haben Sie als lokale Bibliothek eine andere Datei build.gradle : <PROJECT_ROOT>\module\build.gradle

In der Datei der obersten Ebene können Sie allgemeine Eigenschaften als Buildscript-Block oder einige allgemeine Eigenschaften angeben.

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 app\build.gradle definieren Sie nur die Eigenschaften für das Modul:

apply plugin: 'com.android.application'


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

dependencies {
    //.....
}

Ein Shell-Skript von Gradle ausführen

Ein Shellskript ist eine sehr vielseitige Möglichkeit, Ihren Build auf alles zu erweitern, was Sie sich vorstellen können.

Als Beispiel sei hier ein einfaches Skript zum Kompilieren von Protobuf-Dateien und zum Hinzufügen der Ergebnis-Java-Dateien zum Quellverzeichnis für die weitere Kompilierung aufgeführt:

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

project.afterEvaluate {
    compilePb()
}

Das Shell-Skript 'pbScript.sh' für dieses Beispiel, das sich im Stammordner des Projekts befindet:

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

Debuggen Ihrer Gradle-Fehler

Das Folgende ist ein Auszug aus Gradle - Was ist ein Exit-Wert ungleich Null und wie kann ich ihn beheben? Sehen Sie es für die vollständige Diskussion.

Nehmen wir an, Sie entwickeln eine Anwendung und erhalten einen Gradle-Fehler, der im Allgemeinen so aussieht.

: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

Sie suchen hier auf StackOverflow nach Ihrem Problem, und die Leute sagen, dass Sie Ihr Projekt bereinigen und neu erstellen oder MultiDex aktivieren sollten . Wenn Sie es versuchen, wird das Problem dadurch nicht behoben .

Es gibt Möglichkeiten, mehr Informationen zu erhalten , aber die Gradle-Ausgabe selbst sollte auf den tatsächlichen Fehler in den wenigen Zeilen über dieser Meldung zwischen: module:someTask FAILED und dem letzten :module:someOtherTask , die bestanden haben. Wenn Sie also eine Frage zu Ihrem Fehler stellen, bearbeiten Sie Ihre Fragen, um dem Fehler mehr Kontext hinzuzufügen.

Sie erhalten also einen Exit-Wert ungleich Null. Nun, diese Zahl ist ein guter Indikator dafür, was Sie beheben sollten. Hier kommen einige am häufigsten vor.

  • 1 ist nur ein allgemeiner Fehlercode und der Fehler ist wahrscheinlich in der Gradle-Ausgabe
  • 2 scheint mit überlappenden Abhängigkeiten oder falscher Projektkonfiguration zu tun zu haben.
  • 3 scheint zu viele Abhängigkeiten oder ein Speicherproblem zu haben.

Die allgemeinen Lösungen für das Vorstehende (nach dem Versuch eines Clean and Rebuild des Projekts) sind:

  • 1 - Beheben Sie den genannten Fehler. Im Allgemeinen ist dies ein Fehler bei der Kompilierung, was bedeutet, dass ein Teil des Codes in Ihrem Projekt nicht gültig ist. Dies umfasst sowohl XML als auch Java für ein Android-Projekt.
  • 2 & 3 - Viele Antworten geben an, Multidex zu aktivieren. Das Problem kann zwar behoben werden, es ist jedoch höchstwahrscheinlich eine Problemumgehung. Wenn Sie nicht verstehen, warum Sie es verwenden (siehe den Link), benötigen Sie es wahrscheinlich nicht. Bei allgemeinen Lösungen müssen Sie die übermäßige Nutzung von Bibliotheksabhängigkeiten reduzieren (z. B. alle Google Play-Services, wenn Sie nur eine Bibliothek verwenden müssen, wie z. B. Maps oder Anmelden).

Angeben verschiedener Anwendungs-IDs für Buildtypen und Produktvarianten

Sie können für jedes buildType oder productFlavor andere Anwendungs-IDs oder Paketnamen productFlavor indem Sie das Konfigurationsattribut applicationIdSuffix verwenden:

Beispiel für ein Suffix der applicationId für jeden 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"
    }
}

Unsere resultierenden applicationIds wären jetzt:

  • com.package.android zur release
  • com.package.android. dev für die development
  • com.package.android. qa zum testing

Dies kann auch für productFlavors werden:

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

Die resultierenden applicationIds wären:

  • com.package.android. kostenlos für den free Geschmack
  • com.package.android. für den bezahlten paid Geschmack

APK unterzeichnen, ohne das Keystore-Passwort freizulegen

Sie können die Signaturkonfiguration definieren, um die apk in der Datei build.gradle mit den folgenden Eigenschaften zu signieren:

  • storeFile : die Keystore-Datei
  • storePassword : das Schlüsselspeicherkennwort
  • keyAlias : ein Aliasname
  • keyPassword : Ein Schlüsselalias-Kennwort

In vielen Fällen müssen Sie diese Art von Informationen in der Datei build.gradle möglicherweise vermeiden.

Methode A: Konfigurieren Sie die Versionssignatur mit einer Datei keystore.properties

Es ist möglich , Ihre App zu konfigurieren build.gradle , so dass es Ihre Signatur - Konfigurationsinformationen von einer Eigenschaft wie Datei lesen keystore.properties .

Das Einrichten einer solchen Unterschrift ist vorteilhaft, weil:

  • Die Informationen zur Signierungskonfiguration sind von Ihrer build.gradle Datei getrennt
  • Sie müssen während des Signaturvorgangs nicht eingreifen, um Kennwörter für Ihre Keystore-Datei anzugeben
  • Sie können die Datei keystore.properties problemlos von der Versionskontrolle ausschließen

Erstellen Sie zunächst eine Datei mit dem Namen keystore.properties im Stammverzeichnis Ihres Projekts mit folgendem Inhalt (Ersetzen der Werte durch Ihre eigenen):

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

build.gradle den signingConfigs Block nun in der build.gradle Datei Ihrer App wie folgt ein:

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

Das ist wirklich alles, aber vergessen Sie nicht, sowohl Ihre Keystore-Datei als auch Ihre keystore.properties Datei von der Versionskontrolle auszuschließen .

Ein paar Dinge zu beachten:

  • Der storeFile Pfad in der angegebenen keystore.properties Datei sollte zu Ihrer App relativ seine build.gradle Datei. In diesem Beispiel wird davon build.gradle dass sich die Keystore-Datei im selben Verzeichnis wie die build.gradle -Datei der App build.gradle .
  • In diesem Beispiel befindet sich die Datei keystore.properties im Stammverzeichnis des Projekts. Wenn Sie es an einer anderen Stelle rootProject.file('keystore.properties') , müssen Sie den Wert in rootProject.file('keystore.properties') relativ zum Stammverzeichnis Ihres Projekts in rootProject.file('keystore.properties') ändern.

Methode B: Mit einer Umgebungsvariablen

Dasselbe kann auch ohne eine Eigenschaftsdatei erreicht werden, wodurch das Passwort schwieriger zu finden ist:

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

Die Umgebungsvariable "ps" kann global sein, es ist jedoch sicherer, sie nur der Shell von Android Studio hinzuzufügen.
In Linux kann dies durch Bearbeiten des Desktop Entry Eintrags von Android Studio erfolgen

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

Weitere Details finden Sie in diesem Thema .

Versionierung Ihrer Builds über die Datei "version.properties"

Sie können Gradle verwenden, um die Paketversion bei jeder Erstellung automatisch zu erhöhen. Erstellen Sie dazu eine version.properties Datei in demselben Verzeichnis wie Ihr build.gradle mit dem folgenden Inhalt:

VERSION_MAJOR=0
VERSION_MINOR=1
VERSION_BUILD=1

(Ändern Sie die Werte für Dur und Minor nach Ihren Wünschen). build.gradle Sie dann in Ihrem build.gradle den folgenden Code zum android Abschnitt hinzu:

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

Auf die Informationen kann in Java als String BuildConfig.VERSION_NAME für die vollständige {major}. {Minor}. {Build} BuildConfig.VERSION_CODE und als Ganzzahl BuildConfig.VERSION_CODE nur für die Build-Nummer BuildConfig.VERSION_CODE .

Ändern des Ausgabe-APK-Namens und Hinzufügen des Versionsnamens:

Dies ist der Code zum Ändern des Dateinamens der Ausgabeanwendung (.apk). Der Name kann konfiguriert werden, indem Sie newName einen anderen Wert 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 + "]");
        }
    }
}

Deaktivieren Sie die Bildkomprimierung für eine kleinere APK-Dateigröße

Wenn Sie alle Bilder manuell optimieren, deaktivieren Sie APT Cruncher für eine kleinere APK-Dateigröße.

android {
    
    aaptOptions {
        cruncherEnabled = false
    }
}

Aktivieren Sie Proguard mit Gradle

Um die Proguard-Konfigurationen für Ihre Anwendung zu aktivieren, müssen Sie sie in der Gradle-Datei auf Modulebene aktivieren. Sie müssen den Wert von minifyEnabled auf true .

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

Mit dem obigen Code werden Ihre Proguard-Konfigurationen, die im Standard-Android-SDK in Kombination mit der Datei "proguard-rules.pro" in Ihrem Modul enthalten sind, auf Ihre freigegebene apk-Datei angewendet.

Aktivieren Sie die experimentelle Unterstützung für das NDK-Plugin für Gradle und AndroidStudio

Aktivieren und konfigurieren Sie das experimentelle Gradle-Plugin, um die NDK-Unterstützung von AndroidStudio zu verbessern. Stellen Sie sicher, dass Sie die folgenden Anforderungen erfüllen:

  • Gradle 2.10 (für dieses Beispiel)
  • Android NDK R10 oder höher
  • Android SDK mit Build-Tools v19.0.0 oder höher

Konfigurieren Sie die Datei MyApp / build.gradle

Bearbeiten Sie die Zeile dependencies.classpath in build.gradle von zB

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

zu

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

(v0.7.2 war zum Zeitpunkt des Schreibens die neueste Version. Prüfen Sie die aktuelle Version selbst und passen Sie Ihre Zeile entsprechend an.)

Die build.gradle-Datei sollte folgendermaßen aussehen:

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

allprojects {
    repositories {
        jcenter()
    }
}

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

Konfigurieren Sie die Datei MyApp / app / build.gradle

Bearbeiten Sie die Datei build.gradle so, dass sie dem folgenden Beispiel ähnelt. Ihre Versionsnummern können anders aussehen.

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

Synchronisieren Sie und überprüfen Sie, ob die Gradle-Dateien fehlerfrei sind, bevor Sie fortfahren.

Testen Sie, ob das Plugin aktiviert ist

Stellen Sie zunächst sicher, dass Sie das Android NDK-Modul heruntergeladen haben. Erstellen Sie dann eine neue App in AndroidStudio und fügen Sie der ActivityMain-Datei Folgendes hinzu:

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

Der getString() Teil sollte rot hervorgehoben werden, um getString() , dass die entsprechende JNI-Funktion nicht gefunden werden konnte. Bewegen Sie die Maus über den Funktionsaufruf, bis eine rote Glühbirne erscheint. Klicken Sie auf die Birne und wählen Sie create function JNI_... . Dies sollte eine myLib.c-Datei im Verzeichnis myApp / app / src / main / jni mit dem richtigen JNI-Funktionsaufruf generieren. Es sollte ähnlich aussehen:

#include <jni.h>

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

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

Wenn es nicht so aussieht, wurde das Plugin nicht richtig konfiguriert oder der NDK wurde nicht heruntergeladen

Zeige alle gradle Projektaufgaben

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

Löschen Sie "nicht ausgerichtet" automatisch

Wenn Sie keine automatisch generierten APK-Dateien mit unaligned Suffix benötigen (was Sie wahrscheinlich nicht tun), können Sie den folgenden Code zur build.gradle Datei 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()
        }
    }
  }
}

Von hier aus

Build-Variante ignorieren

Aus einigen Gründen möchten Sie möglicherweise Ihre Build-Varianten ignorieren. Zum Beispiel: Sie haben ein "Mock" -Produktaroma und verwenden es nur für Debugging-Zwecke, wie z. B. Unit- / Instrumentationstests.

Lassen Sie uns die mockRelease- Variante aus unserem Projekt ignorieren. Öffnen Sie die Datei build.gradle und schreiben Sie:

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

Abhängigkeitsbaum sehen

Verwenden Sie die Aufgabenabhängigkeiten. Abhängig davon, wie Ihre Module eingerichtet sind, kann es sich entweder um ./gradlew dependencies oder um die Abhängigkeiten der Modul-App zu sehen ./gradlew :app:dependencies

Das Beispiel folgt der build.gradle -Datei

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

erzeugt die folgende Grafik:

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 können Sie sehen, dass das Projekt direkt com.android.support:design Version 23.2.1 enthält, das selbst com.android.support:support-v4 mit Version 23.2.1 enthält. com.google.android.gms:play-services selbst hängt jedoch von derselben support-v4 Version support-v4 jedoch von einer älteren Version 21.0.0, die von gradle erkannt wird.

(*) werden verwendet, wenn Gradle den Teilbaum überspringt, da diese Abhängigkeiten bereits zuvor aufgeführt wurden.

Verwenden Sie gradle.properties für zentrale Versionsnummern- / Buildkonfigurationen

Sie können zentrale Konfigurationsinformationen in definieren

oder machen Sie es mit der root gradle.properties Datei

die Projektstruktur

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

globale Einstellung für alle Submodule 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

Verwendung in einem Submodul

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

Hinweis: Wenn Sie Ihre App im F-Droid App Store veröffentlichen möchten, müssen Sie in der Gradle-Datei magische Zahlen verwenden, da der f-Droid-Roboter die aktuelle Versionsnummer nicht lesen kann, um Versionsänderungen zu erkennen / zu überprüfen.

Signaturinformationen anzeigen

Unter bestimmten Umständen (z. B. beim Erwerb eines Google-API-Schlüssels) müssen Sie den Fingerabdruck Ihres Keystores ermitteln. Gradle hat eine praktische Aufgabe, die alle Signaturinformationen einschließlich der Fingerabdrücke des Keystores anzeigt:

./gradlew signingReport

Dies ist eine Beispielausgabe:

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

Sie können Build-Typen in der build.gradle Datei auf build.gradle im android {} -Block erstellen und konfigurieren.

    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
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow