Google berkomitmen untuk mendorong terwujudnya keadilan rasial bagi komunitas Kulit Hitam. Lihat caranya.

Menambahkan dependensi build

Sistem build Gradle di Android Studio memudahkan Anda menyertakan biner eksternal atau modul library lainnya ke build Anda sebagai dependensi. Dependensi dapat ditemukan di komputer Anda atau di repositori jarak jauh, dan setiap dependensi transitif yang dideklarasikan akan otomatis disertakan. Halaman ini menjelaskan cara menggunakan dependensi dengan project Android Anda, termasuk detail tentang perilaku dan konfigurasi yang spesifik untuk plugin Android untuk Gradle. Untuk mendapatkan panduan konseptual yang lebih mendalam tentang dependensi Gradle, sebaiknya Anda juga membaca Panduan Gradle untuk pengelolaan dependensi, tetapi ingat bahwa project Android Anda hanya boleh menggunakan konfigurasi dependensi yang ditentukan pada halaman ini.

Jenis-jenis dependensi

Untuk menambahkan dependensi ke project Anda, tetapkan konfigurasi dependensi seperti implementation dalam blok dependencies file build.gradle Anda.

Misalnya, file build.gradle berikut untuk modul aplikasi menyertakan tiga jenis dependensi yang berbeda:

apply plugin: 'com.android.application'

android { ... }

dependencies {
    // Dependency on a local library module
    implementation project(":mylibrary")

    // Dependency on local binaries
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    // Dependency on a remote binary
    implementation 'com.example.android:app-magic:12.3'
}

Masing-masing meminta jenis dependensi library yang berbeda, seperti berikut:

Dependensi modul library lokal
implementation project(':mylibrary')

Baris ini mendeklarasikan dependensi pada modul library Android dengan nama "mylibrary" (nama ini harus sama dengan nama library yang ditentukan dengan include: di file settings.gradle). Ketika Anda membuat aplikasi, sistem build akan mengompilasi modul library dan memaketkan konten terkompilasi yang dihasilkannya ke dalam APK.

Dependensi biner lokal
implementation fileTree(dir: 'libs', include: ['*.jar'])

Gradle mendeklarasikan dependensi di file JAR dalam direktori module_name/libs/ project Anda (karena Gradle membaca jalur yang relatif ke file build.gradle).

Atau, Anda dapat menetapkan file tertentu seperti berikut:

implementation files('libs/foo.jar', 'libs/bar.jar')
Dependensi biner jarak jauh
implementation 'com.example.android:app-magic:12.3'

Cara ini sebenarnya merupakan pintasan untuk berikut ini:

implementation group: 'com.example.android', name: 'app-magic', version: '12.3'

Baris ini mendeklarasikan dependensi pada library "app-magic" versi 12.3, di dalam grup namespace "com.example.android".

Catatan: Dependensi jarak jauh seperti ini mengharuskan Anda mendeklarasikan repositori jarak jauh yang sesuai tempat Gradle harus mencari library. Jika library ini belum ada secara lokal, Gradle akan mengambilnya dari situs jarak jauh saat build memerlukannya (seperti saat Anda mengklik Sync Project with Gradle Files atau menjalankan build).

Konfigurasi dependensi

Dalam blok dependencies, Anda dapat mendeklarasikan dependensi library menggunakan salah satu dari sejumlah konfigurasi dependensi yang berbeda (seperti implementation yang ditampilkan di atas). Setiap konfigurasi dependensi memberikan petunjuk yang berbeda bagi Gradle untuk menggunakan dependensi. Tabel berikut ini menjelaskan setiap konfigurasi yang dapat Anda gunakan untuk dependensi dalam project Android Anda. Tabel tersebut juga membandingkan konfigurasi ini dengan konfigurasi yang tidak digunakan lagi sejak Plugin Android Gradle 3.0.0.

Konfigurasi baru Konfigurasi yang tidak digunakan lagi Perilaku
implementation compile Gradle menambahkan dependensi ke classpath kompilasi dan memaketkan dependensi ke output build. Namun, saat mengonfigurasi dependensi implementation, modul akan memberi tahu Gradle bahwa Anda tidak ingin modul tersebut membocorkan dependensi ke modul lain pada waktu kompilasi. Artinya, dependensi tersebut hanya tersedia untuk modul lain selama waktu proses.

Menggunakan konfigurasi dependensi ini dan bukan api atau compile (tidak digunakan lagi) dapat meningkatkan waktu build secara signifikan karena mengurangi jumlah modul yang perlu dikompilasi ulang oleh sistem build. Misalnya, jika dependensi implementation mengubah API-nya, Gradle hanya akan mengompilasi ulang dependensi tersebut dan modul yang bergantung langsung padanya. Sebagian besar modul pengujian dan aplikasi akan menggunakan konfigurasi ini.

api compile Gradle menambahkan dependensi ke classpath kompilasi dan output build. Jika modul menyertakan dependensi api, Gradle akan diberi tahu bahwa modul tersebut ingin mengekspor dependensi secara transitif ke modul lainnya agar tersedia untuk modul lain selama waktu proses dan waktu kompilasi.

Konfigurasi ini berperilaku seperti compile (yang sudah tidak digunakan lagi), tetapi Anda harus menggunakannya dengan hati-hati dan hanya dengan dependensi yang ingin Anda ekspor secara transitif ke konsumen upstream lain. Alasannya, jika dependensi api mengubah API eksternalnya, Gradle akan mengompilasi ulang semua modul yang memiliki akses ke dependensi tersebut pada waktu kompilasi. Oleh karena itu, memiliki banyak dependensi api dapat meningkatkan waktu build secara signifikan. Kecuali Anda ingin menunjukkan API dependensi ke modul lain, modul library sebaiknya menggunakan dependensi implementation.

compileOnly provided Gradle hanya menambahkan dependensi ke classpath kompilasi (artinya, dependensi tidak ditambahkan ke output build). Ini berguna saat Anda membuat modul Android dan memerlukan dependensi selama kompilasi, tetapi ketersediaannya opsional selama waktu proses.

Jika Anda menggunakan konfigurasi ini, modul library harus menyertakan kondisi waktu proses untuk memeriksa ketersediaan dependensi, lalu mengubah perilakunya dengan lancar agar tetap dapat berfungsi jika tidak disediakan. Cara ini membantu mengurangi ukuran APK akhir dengan tidak menambahkan dependensi sementara yang tidak begitu penting. Konfigurasi ini berperilaku seperti provided (yang sudah tidak digunakan lagi).

Catatan: Anda tidak dapat menggunakan konfigurasi compileOnly dengan dependensi AAR.

runtimeOnly apk Gradle hanya menambahkan dependensi ke output build, untuk digunakan selama waktu proses. Dengan kata lain, dependensi ini tidak ditambahkan ke classpath kompilasi. Konfigurasi ini berperilaku seperti apk (yang sudah tidak digunakan lagi).
annotationProcessor compile Untuk menambahkan dependensi pada library yang merupakan pemroses anotasi, Anda harus menambahkannya ke classpath pemroses anotasi menggunakan konfigurasi annotationProcessor. Ini dikarenakan penggunaan konfigurasi tersebut akan meningkatkan performa build dengan memisahkan classpath kompilasi dari classpath pemroses anotasi. Jika menemukan pemroses anotasi pada classpath kompilasi, Gradle akan menonaktifkan pencegahan kompilasi, yang berdampak negatif pada waktu build (Gradle 5.0 dan yang lebih tinggi mengabaikan pemroses anotasi yang ditemukan pada classpath kompilasi).

Plugin Android Gradle mengasumsikan dependensi adalah pemroses anotasi jika file JAR-nya berisi file berikut:
META-INF/services/javax.annotation.processing.Processor. Jika plugin mendeteksi pemroses anotasi yang ada pada classpath kompilasi, error build akan muncul.
lintChecks Gunakan konfigurasi ini untuk menyertakan pemeriksaan lint yang perlu dijalankan Gradle saat membuat project Anda.

Catatan: Saat menggunakan Plugin Android Gradle 3.4.0 dan yang lebih tinggi, konfigurasi dependensi ini tidak lagi memaketkan pemeriksaan lint ke dalam project library Android Anda. Untuk menyertakan dependensi pemeriksaan lint dalam library AAR, gunakan konfigurasi lintPublish yang dijelaskan di bawah.

lintPublish Gunakan konfigurasi ini di project library Android untuk menyertakan pemeriksaan lint yang perlu dikompilasi Gradle ke dalam paket dan file lint.jar di AAR Anda. Dengan demikian, project yang menggunakan AAR Anda juga menerapkan pemeriksaan lint tersebut. Jika sebelumnya menggunakan konfigurasi dependensi lintChecks untuk menyertakan pemeriksaan lint dalam AAR yang dipublikasikan, Anda perlu memigrasikan dependensi tersebut agar menggunakan konfigurasi lintPublish.

dependencies {
  // Executes lint checks from the ':checks' project
  // at build time.
  lintChecks project(':checks')
  // Compiles lint checks from the ':checks-to-publish'
  // into a lint.jar file and publishes it to your
  // Android library.
  lintPublish project(':checks-to-publish')
}

Konfigurasi di atas menerapkan dependensi ke semua varian build. Jika ingin mendeklarasikan dependensi hanya untuk set sumber varian build tertentu atau untuk set sumber pengujian, Anda harus membuat nama konfigurasi dengan huruf besar dan mengawalinya dengan nama varian build atau set sumber pengujian.

Misalnya, untuk menambahkan dependensi implementation hanya pada ragam produk "free" (menggunakan dependensi biner jarak jauh), caranya adalah seperti berikut:

dependencies {
    freeImplementation 'com.google.firebase:firebase-ads:9.8.0'
}

Namun, jika ingin menambahkan dependensi untuk varian yang menggabungkan ragam produk dan jenis build, Anda harus menginisialisasi nama konfigurasi dalam blok configurations. Contoh berikut menambahkan dependensi runtimeOnly ke varian build "freeDebug" (menggunakan dependensi biner lokal):

configurations {
    // Initializes a placeholder for the freeDebugRuntimeOnly dependency
    // configuration.
    freeDebugRuntimeOnly {}
}

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

Untuk menambahkan dependensi implementation bagi pengujian lokal dan pengujian berinstrumen, caranya adalah seperti berikut:

dependencies {
    // Adds a remote binary dependency only for local tests.
    testImplementation 'junit:junit:4.12'

    // Adds a remote binary dependency only for the instrumented test APK.
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

Namun, konfigurasi tertentu tidak cocok dengan situasi ini. Misalnya, karena modul lain tidak dapat bergantung pada androidTest, Anda akan mendapatkan peringatan berikut jika menggunakan konfigurasi androidTestApi:

WARNING: Configuration 'androidTestApi' is obsolete and has been replaced with
'androidTestImplementation'.

Menambahkan pemroses anotasi

Jika menambahkan pemroses anotasi ke classpath kompilasi, Anda akan melihat pesan error seperti berikut:

Error: Annotation processors must be explicitly declared now.

Untuk mengatasi error ini, tambahkan pemroses anotasi ke project Anda dengan mengonfigurasi dependensi menggunakan annotationProcessor seperti di bawah ini:

dependencies {
    // Adds libraries defining annotations to only the compile classpath.
    compileOnly 'com.google.dagger:dagger:version-number'
    // Adds the annotation processor dependency to the annotation processor classpath.
    annotationProcessor 'com.google.dagger:dagger-compiler:version-number'
}

Catatan: Plugin Android untuk Gradle 3.0.0 atau yang lebih baru tidak lagi mendukung plugin android-apt.

Meneruskan argumen ke pemroses anotasi

Jika perlu meneruskan argumen ke pemroses anotasi, Anda dapat melakukannya menggunakan blok AnnotationProcessorOptions dalam konfigurasi build modul. Misalnya, jika ingin meneruskan jenis data sederhana seperti key-value pair, Anda dapat menggunakan properti argument, seperti yang ditunjukkan di bawah.

android {
    ...
    defaultConfig {
        ...
        javaCompileOptions {
            annotationProcessorOptions {
                argument "key1", "value1"
                argument "key2", "value2"
            }
        }
    }
}

Namun, saat menggunakan plugin Android Gradle 3.2.0 dan yang lebih tinggi, Anda harus meneruskan argumen pemroses yang merepresentasikan file atau direktori menggunakan antarmuka CommandLineArgumentProvider Gradle.

Penggunaan CommandLineArgumentProvider memungkinkan Anda atau penulis pemroses anotasi meningkatkan ketepatan dan performa build inkremental dan clean build yang disimpan dalam cache dengan menerapkan anotasi jenis properti build inkremental ke setiap argumen.

Misalnya, class di bawah mengimplementasikan CommandLineArgumentProvider dan memberikan anotasi pada setiap argumen untuk pemroses. Contoh tersebut juga menggunakan sintaksis bahasa Groovy dan disertakan langsung dalam file build.gradle modul.

class MyArgsProvider implements CommandLineArgumentProvider {

    // Annotates each directory as either an input or output for the
    // annotation processor.
    @InputFiles
    // Using this annotation helps Gradle determine which part of the file path
    // should be considered during up-to-date checks.
    @PathSensitive(PathSensitivity.RELATIVE)
    FileCollection inputDir

    @OutputDirectory
    File outputDir

    // The class constructor sets the paths for the input and output directories.
    MyArgsProvider(FileCollection input, File output) {
        inputDir = input
        outputDir = output
    }

    // Specifies each directory as a command line argument for the processor.
    // The Android plugin uses this method to pass the arguments to the
    // annotation processor.
    @Override
    Iterable<String> asArguments() {
        // Use the form '-Akey[=value]' to pass your options to the Java compiler.
        ["-AinputDir=${inputDir.singleFile.absolutePath}",
         "-AoutputDir=${outputDir.absolutePath}"]
    }
}

android {...}

Setelah membuat class yang mengimplementasikan CommandLineArgumentProvider, Anda perlu menginisialisasi dan meneruskannya ke plugin Android menggunakan properti annotationProcessorOptions.compilerArgumentProvider, seperti di bawah ini.

// This is in your module's build.gradle file.
android {
    defaultConfig {
        javaCompileOptions {
            annotationProcessorOptions {
                // Creates a new MyArgsProvider object, specifies the input and
                // output paths for the constructor, and passes the object
                // to the Android plugin.
                compilerArgumentProvider new MyArgsProvider(files("input/path"),
                                         new File("output/path"))
            }
        }
    }
}

Untuk mempelajari lebih lanjut cara implementasi CommandLineArgumentProvider dapat membantu meningkatkan performa build, baca Menyimpan data project Java dalam cache.

Menonaktifkan pemeriksaan error pemroses anotasi

Jika memiliki dependensi pada classpath kompilasi yang menyertakan pemroses anotasi yang tidak dibutuhkan, Anda dapat menonaktifkan pemeriksaan error dengan menambahkan hal berikut ini ke file build.gradle. Perlu diingat bahwa pemroses anotasi yang Anda tambahkan ke classpath kompilasi tetap tidak ditambahkan ke classpath pemroses.

android {
    ...
    defaultConfig {
        ...
        javaCompileOptions {
            annotationProcessorOptions {
                includeCompileClasspath false
            }
        }
    }
}

Jika mengalami masalah setelah memigrasikan pemroses anotasi project ke classpath pemroses, Anda dapat mengizinkan pemroses anotasi pada classpath kompilasi dengan menetapkan includeCompileClasspath ke true. Namun, sebaiknya jangan menetapkan properti ini ke true, dan opsi untuk melakukannya akan dihapus pada update plugin Android mendatang.

Mengecualikan dependensi transitif

Seiring bertambahnya cakupan aplikasi, aplikasi dapat berisi sejumlah dependensi, termasuk dependensi langsung dan dependensi transitif (library yang digunakan oleh library yang diimpor milik aplikasi Anda). Untuk mengecualikan dependensi transitif yang sudah tidak dibutuhkan lagi, Anda dapat menggunakan kata kunci exclude seperti yang di bawah ini:

dependencies {
    implementation('some-library') {
        exclude group: 'com.example.imgtools', module: 'native'
    }
}

Mengecualikan dependensi transitif dari konfigurasi pengujian

Jika Anda perlu mengecualikan dependensi transitif tertentu dari pengujian, contoh kode yang ditunjukkan di atas mungkin tidak berfungsi sesuai harapan. Hal ini dikarenakan konfigurasi pengujian (misalnya androidTestImplementation) akan memperluas konfigurasi implementation modul. Dengan kata lain, pengujian selalu berisi dependensi implementation saat Gradle mengatasi konfigurasi ini.

Jadi, untuk mengecualikan dependensi transitif dari pengujian, Anda harus melakukannya pada waktu eksekusi, seperti di bawah ini:

android.testVariants.all { variant ->
    variant.getCompileConfiguration().exclude group: 'com.jakewharton.threetenabp', module: 'threetenabp'
    variant.getRuntimeConfiguration().exclude group: 'com.jakewharton.threetenabp', module: 'threetenabp'
}

Catatan: Anda tetap dapat menggunakan kata kunci exclude dalam blok dependensi seperti yang ditunjukkan dalam contoh kode asli dari bagian Mengecualikan dependensi untuk menghilangkan dependensi transitif yang spesifik untuk konfigurasi pengujian dan tidak termasuk dalam konfigurasi lain.

Menggunakan pengelolaan dependensi yang peka terhadap varian

Plugin Android 3.0.0 dan yang lebih tinggi menyertakan mekanisme dependensi baru yang otomatis mencocokkan varian saat menggunakan library. Hal ini berarti varian debug aplikasi akan otomatis menggunakan varian debug library, dan seterusnya. Ini juga berfungsi saat menggunakan ragam, varian freeDebug aplikasi akan menggunakan varian freeDebug library.

Agar plugin mencocokkan varian secara akurat, Anda perlu menyediakan penggantian pencocokan untuk instance jika pencocokan langsung tidak memungkinkan. Pertimbangkan jika aplikasi Anda mengonfigurasi jenis build yang disebut "staging", tetapi salah satu dependensi library-nya tidak. Saat mencoba membuat versi "staging" aplikasi Anda, plugin tidak akan tahu versi library mana yang akan digunakan, dan Anda akan melihat pesan error seperti berikut ini:

Error:Failed to resolve: Could not resolve project :mylibrary.
Required by:
    project :app

Mengatasi error build terkait pencocokan varian

Plugin menyertakan elemen DSL untuk membantu Anda mengontrol bagaimana Gradle harus mengatasi situasi ketika pencocokan varian langsung antara aplikasi dan dependensi tidak mungkin dilakukan. Lihat tabel di bawah ini untuk menentukan properti DSL mana yang harus Anda gunakan untuk mengatasi error build tertentu terkait pencocokan dependensi yang peka terhadap varian.

Penyebab error buildResolusi

Aplikasi Anda menyertakan jenis build yang tidak disertakan oleh dependensi library.

Misalnya, aplikasi Anda menyertakan jenis build "staging", tetapi dependensi hanya menyertakan jenis build "debug" dan "release".

Perlu diperhatikan bahwa tidak akan ada masalah jika dependensi library menyertakan jenis build yang tidak disertakan aplikasi Anda. Hal ini dikarenakan plugin tidak pernah meminta jenis build tersebut dari dependensi.

Gunakan matchingFallbacks untuk menentukan kecocokan alternatif bagi jenis build tertentu, seperti di bawah:


// In the app's build.gradle file.
android {
    buildTypes {
        debug {}
        release {}
        staging {
            // Specifies a sorted list of fallback build types that the
            // plugin should try to use when a dependency does not include a
            // "staging" build type. You may specify as many fallbacks as you
            // like, and the plugin selects the first build type that's
            // available in the dependency.
            matchingFallbacks = ['debug', 'qa', 'release']
        }
    }
}

Untuk dimensi ragam tertentu yang ada dalam aplikasi dan dependensi library-nya, aplikasi Anda menyertakan ragam yang tidak disertakan oleh library.

Misalnya, aplikasi Anda dan dependensi library-nya menyertakan dimensi ragam "tier". Namun, dimensi "tier" dalam aplikasi menyertakan ragam "free" dan "paid", sementara dependensi hanya menyertakan ragam "demo" dan "paid" untuk dimensi yang sama.

Perlu diperhatikan bahwa untuk dimensi ragam tertentu yang ada dalam aplikasi dan dependensi library-nya, tidak akan ada masalah jika library menyertakan ragam produk yang tidak disertakan aplikasi Anda. Hal ini dikarenakan plugin tidak pernah meminta ragam tersebut dari dependensi.

Gunakan matchingFallbacks untuk menetapkan pencocokan alternatif bagi ragam produk "free" aplikasi, seperti ditunjukkan di bawah:


// In the app's build.gradle file.
android {
    defaultConfig{
    // Do not configure matchingFallbacks in the defaultConfig block.
    // Instead, you must specify fallbacks for a given product flavor in the
    // productFlavors block, as shown below.
  }
    flavorDimensions 'tier'
    productFlavors {
        paid {
            dimension 'tier'
            // Because the dependency already includes a "paid" flavor in its
            // "tier" dimension, you don't need to provide a list of fallbacks
            // for the "paid" flavor.
        }
        free {
            dimension 'tier'
            // Specifies a sorted list of fallback flavors that the plugin
            // should try to use when a dependency's matching dimension does
            // not include a "free" flavor. You may specify as many
            // fallbacks as you like, and the plugin selects the first flavor
            // that's available in the dependency's "tier" dimension.
            matchingFallbacks = ['demo', 'trial']
        }
    }
}

Dependensi library menyertakan dimensi ragam yang tidak disertakan aplikasi Anda.

Misalnya, dependensi library menyertakan ragam untuk dimensi "minApi", sementara aplikasi Anda hanya menyertakan ragam untuk dimensi "tier". Jadi, saat Anda ingin membuat versi "freeDebug" aplikasi, plugin tidak tahu apakah akan menggunakan versi dependensi "minApi23Debug" atau "minApi18Debug".

Perlu diperhatikan bahwa tidak akan ada masalah jika aplikasi Anda menyertakan dimensi ragam yang tidak disertakan dependensi library. Hal ini dikarenakan plugin tersebut hanya mencocokkan ragam dari dimensi yang ada dalam dependensi. Misalnya, jika dependensi tidak menyertakan dimensi untuk ABI, versi "freeX86Debug" aplikasi Anda akan menggunakan versi "freeDebug" dependensi.

Gunakan missingDimensionStrategy dalam blok defaultConfig untuk menetapkan ragam default yang harus dipilih plugin dari setiap dimensi yang tidak ditemukan, seperti dalam contoh di bawah. Anda juga dapat mengganti pilihan dalam blok productFlavors, sehingga setiap ragam dapat menetapkan strategi pencocokan yang berbeda untuk dimensi yang tidak ditemukan.


// In the app's build.gradle file.
android {
    defaultConfig{
    // Specifies a sorted list of flavors that the plugin should try to use from
    // a given dimension. The following tells the plugin that, when encountering
    // a dependency that includes a "minApi" dimension, it should select the
    // "minApi18" flavor. You can include additional flavor names to provide a
    // sorted list of fallbacks for the dimension.
    missingDimensionStrategy 'minApi', 'minApi18', 'minApi23'
    // You should specify a missingDimensionStrategy property for each
    // dimension that exists in a local dependency but not in your app.
    missingDimensionStrategy 'abi', 'x86', 'arm64'
    }
    flavorDimensions 'tier'
    productFlavors {
        free {
            dimension 'tier'
            // You can override the default selection at the product flavor
            // level by configuring another missingDimensionStrategy property
            // for the "minApi" dimension.
            missingDimensionStrategy 'minApi', 'minApi23', 'minApi18'
        }
        paid {}
    }
}

Mengonfigurasi dependensi aplikasi Wear OS

Mengonfigurasi dependensi untuk modul Wear OS mirip dengan mengonfigurasi modul lainnya. Artinya, keduanya menggunakan konfigurasi dependensi yang sama, seperti implementation dan compileOnly.

Modul Wear juga mendukung pengelolaan dependensi yang peka terhadap varian. Oleh karena itu, jika modul aplikasi dasar Anda memiliki dependensi pada modul Wear, setiap varian modul dasar akan menggunakan varian yang cocok dari modul Wear. Jika Anda akan membuat aplikasi sederhana dengan dependensi pada satu modul Wear saja, yang nantinya modul tersebut mengonfigurasi varian yang sama dengan modul dasar, Anda perlu menetapkan konfigurasi wearApp di file build.gradle modul dasar Anda, seperti di bawah ini:

dependencies {
    // If the main and Wear app modules have the same variants,
    // variant-aware dependency management automatically matches
    // variants of the main app module with that of the wear module.
    wearApp project(':wearable')
}

Jika memiliki beberapa modul Wear dan ingin menentukan modul Wear yang berbeda untuk setiap ragam aplikasi, Anda dapat melakukannya menggunakan konfigurasi flavorWearApp seperti berikut (tetapi Anda tidak dapat menyertakan dependensi lain yang menggunakan konfigurasi wearApp):

dependencies {
    paidWearApp project(':wear1')
    demoWearApp project(':wear1')
    freeWearApp project(':wear2')
}

Repositori jarak jauh

Jika dependensi Anda bukan merupakan library lokal atau hierarki file, Gradle akan mencari file tersebut di repositori online mana pun yang ditetapkan dalam blok repositories file build.gradle Anda. Urutan pencantuman masing-masing repositori menentukan urutan pencarian repositori oleh Gradle untuk setiap dependensi project. Misalnya, jika sebuah dependensi tersedia dari repositori A dan B, dan Anda mencantumkan A terlebih dahulu, Gradle akan mendownload dependensi dari repositori A.

Secara default, project Android Studio baru akan menetapkan repositori Maven Google dan JCenter sebagai lokasi repositori dalam file build.gradle tingkat teratas project, seperti di bawah ini:

allprojects {
    repositories {
        google()
        jcenter()
    }
}

Jika Anda menginginkan sesuatu dari repositori pusat Maven, tambahkan mavenCentral(), atau gunakan mavenLocal() untuk repositori lokal:

allprojects {
    repositories {
        google()
        jcenter()
        mavenCentral()
        mavenLocal()
    }
}

Atau Anda dapat mendeklarasikan repositori Maven atau Ivy tertentu seperti berikut:

allprojects {
    repositories {
        maven {
            url "https://repo.example.com/maven2"
        }
        maven {
            url "file://local/repo/"
        }
        ivy {
            url "https://repo.example.com/ivy"
        }
    }
}

Untuk mengetahui informasi selengkapnya, baca Panduan Repositori Gradle.

Repositori Maven Google

Versi terbaru library Android berikut tersedia dari repositori Maven Google:

Anda dapat melihat semua artefak yang tersedia dalam indeks repositori Maven Google (lihat di bawah untuk akses terprogram).

Untuk menambahkan salah satu library ini ke build Anda, sertakan repositori Maven Google dalam file build.gradle tingkat teratas:

allprojects {
    repositories {
        google()

        // If you're using a version of Gradle lower than 4.1, you must instead use:
        // maven {
        //     url 'https://maven.google.com'
        // }
        // An alternative URL is 'https://dl.google.com/dl/android/maven2/'
    }
}

Selanjutnya, tambahkan library yang diinginkan ke blok dependencies modul Anda. Misalnya, library appcompat akan terlihat seperti ini:

dependencies {
    implementation 'com.android.support:appcompat-v7:28.0.0'
}

Namun, jika Anda mencoba menggunakan versi yang lebih lama dari library di atas dan dependensi Anda gagal, library tersebut tidak akan tersedia di repositori Maven dan Anda harus mendapatkan library dari repositori offline.

Akses terprogram

Untuk mendapatkan akses terprogram ke artefak Maven Google, Anda dapat memperoleh daftar XML grup artefak dari maven.google.com/master-index.xml. Kemudian, untuk grup apa saja, Anda dapat melihat nama dan versi library-nya di:

maven.google.com/group_path/group-index.xml

Misalnya, library dalam grup android.arch.lifecycle dicantumkan di maven.google.com/android/arch/lifecycle/group-index.xml.

Anda juga dapat mendownload file POM dan JAR di:

maven.google.com/group_path/library/version/library-version.ext

Misalnya: maven.google.com/android/arch/lifecycle/compiler/1.0.0/compiler-1. 0.0.pom.

Repositori offline dari SDK Manager

Untuk library yang tidak tersedia dari repositori Maven Google (biasanya versi library yang lebih lama), Anda harus mendownload paket offline Repositori Google dari SDK Manager.

Selanjutnya, Anda dapat menambahkan library ini ke blok dependencies seperti biasa.

Library offline disimpan di android_sdk/extras/.

Urutan dependensi

Urutan pencantuman dependensi menunjukkan prioritas untuk tiap-tiapnya: library pertama memiliki prioritas lebih tinggi daripada library kedua, library kedua memiliki prioritas lebih tinggi daripada library ketiga, dan seterusnya. Urutan ini penting jika resource digabungkan atau elemen manifes digabungkan ke dalam aplikasi Anda dari library.

Misalnya, jika project Anda mendeklarasikan berikut ini:

  • Dependensi pada LIB_A dan LIB_B (dalam urutan tersebut)
  • Dan LIB_A bergantung pada LIB_C dan LIB_D (dalam urutan tersebut)
  • Serta LIB_B juga bergantung pada LIB_C

Urutan dependensi rata akan menjadi seperti berikut:

  1. LIB_A
  2. LIB_D
  3. LIB_B
  4. LIB_C

Ini memastikan bahwa baik LIB_A maupun LIB_B dapat menggantikan LIB_C; dan LIB_D masih lebih tinggi prioritasnya daripada LIB_B karena LIB_A (yang bergantung padanya) memiliki prioritas lebih tinggi daripada LIB_B.

Untuk mengetahui informasi selengkapnya tentang penggabungan manifes dari sumber/dependensi project yang berbeda, baca Menggabungkan beberapa file manifes.

Menampilkan dependensi modul

Sebagian dependensi langsung mungkin memiliki dependensi sendiri. Dependensi semacam ini disebut dependensi transitif. Gradle mengumpulkan dan menambahkannya secara otomatis sehingga Anda tidak harus mendeklarasikan setiap dependensi transitif secara manual. Plugin Android untuk Gradle menyediakan tugas yang menampilkan daftar dependensi yang diselesaikan Gradle untuk modul tertentu.

Untuk setiap modul, laporan juga mengelompokkan dependensi berdasarkan varian build, set sumber pengujian, dan classpath. Berikut ini adalah laporan contoh untuk classpath waktu proses modul aplikasi dari varian build debug dan classpath kompilasi set sumber pengujian berinstrumen.

debugRuntimeClasspath - Dependencies for runtime/packaging
+--- :mylibrary (variant: debug)
+--- com.google.android.material:material:1.0.0@aar
+--- androidx.appcompat:appcompat:1.0.2@aar
+--- androidx.constraintlayout:constraintlayout:1.1.3@aar
+--- androidx.fragment:fragment:1.0.0@aar
+--- androidx.vectordrawable:vectordrawable-animated:1.0.0@aar
+--- androidx.recyclerview:recyclerview:1.0.0@aar
+--- androidx.legacy:legacy-support-core-ui:1.0.0@aar
...

debugAndroidTest
debugAndroidTestCompileClasspath - Dependencies for compilation
+--- androidx.test.ext:junit:1.1.0@aar
+--- androidx.test.espresso:espresso-core:3.1.1@aar
+--- androidx.test:runner:1.1.1@aar
+--- junit:junit:4.12@jar
...

Untuk menjalankan tugas ini, lakukan langkah berikut:

  1. Pilih View > Tool Windows > Gradle (atau klik Gradle di panel jendela alat).
  2. Luaskan AppName > Tasks > android, lalu klik dua kali androidDependencies. Setelah Gradle mengeksekusi tugas, jendela Run akan terbuka untuk menampilkan output.

Untuk mengetahui informasi selengkapnya tentang mengelola dependensi di Gradle, baca Dasar-dasar pengelolaan dependensi dalam Panduan Pengguna Gradle.

Memperbaiki error penyelesaian dependensi

Jika Anda menambahkan beberapa dependensi ke project aplikasi Anda, dependensi langsung dan transitif tersebut mungkin berkonflik satu sama lain. Plugin Android Gradle mencoba mengatasi konflik ini tanpa hambatan, tetapi beberapa konflik dapat menyebabkan error waktu kompilasi atau error waktu proses.

Untuk membantu Anda menyelidiki dependensi mana yang mengakibatkan error, periksa hierarki dependensi aplikasi Anda dan temukan dependensi yang muncul lebih dari sekali, atau yang muncul dengan versi yang berkonflik.

Jika Anda kesulitan mengenali dependensi duplikat, cobalah menggunakan UI Android Studio untuk menelusuri dependensi yang menyertakan class duplikat seperti berikut:

  1. Pilih Navigate > Class dari panel menu.
  2. Dalam dialog penelusuran pop-up, pastikan kotak di samping Include non-project items dicentang.
  3. Ketikkan nama class yang muncul dalam error build.
  4. Periksa hasilnya untuk menemukan dependensi yang menyertakan class tersebut.

Bagian berikut ini menjelaskan berbagai jenis error penyelesaian dependensi yang mungkin Anda jumpai dan cara memperbaikinya.

Memperbaiki error class duplikat

Jika sebuah class muncul lebih dari sekali pada classpath waktu proses, Anda akan mendapat error yang terlihat seperti berikut:

Program type already present com.example.MyClass

Error ini biasanya terjadi akibat salah satu keadaan berikut:

  • Sebuah dependensi biner menyertakan library yang juga disertakan oleh aplikasi Anda sebagai dependensi langsung. Misalnya, aplikasi Anda mendeklarasikan dependensi langsung pada Library A dan Library B, tetapi Library A sudah menyertakan Library B dalam binernya.
    • Untuk mengatasi masalah ini, hapus Library B sebagai dependensi langsung.
  • Aplikasi Anda memiliki dependensi biner lokal dan dependensi biner jarak jauh pada library yang sama.
    • Untuk mengatasi masalah ini, hapus salah satu dependensi biner.

Mengatasi konflik antar-classpath

Saat menangani classpath kompilasi, Gradle akan menangani classpath waktu proses terlebih dahulu dan menggunakan hasilnya untuk menentukan versi dependensi yang harus ditambahkan ke classpath kompilasi. Dengan kata lain, classpath waktu proses menentukan nomor versi yang diperlukan untuk dependensi identik pada classpath downstream.

Classpath waktu proses aplikasi Anda juga menentukan nomor versi yang diperlukan Gradle untuk mencocokkan dependensi dalam classpath waktu proses bagi APK pengujian aplikasi. Hierarki classpath dijelaskan dalam gambar 1.

Gambar 1. Nomor versi dependensi yang muncul di beberapa classpath harus cocok sesuai dengan hierarki ini.

Konflik ketika versi berbeda dari dependensi yang sama muncul di beberapa classpath dapat terjadi jika, misalnya, aplikasi Anda menyertakan versi dependensi menggunakan implementation konfigurasi dependensi sementara modul library menyertakan versi dependensi yang berbeda menggunakan konfigurasi runtimeOnly.

Saat menyelesaikan dependensi pada classpath waktu proses dan classpath waktu kompilasi, plugin Android Gradle 3.3.0 dan yang lebih tinggi mencoba untuk memperbaiki konflik versi downstream tertentu secara otomatis. Misalnya, jika classpath waktu proses menyertakan Library A versi 2.0 dan classpath kompilasi menyertakan Library A versi 1.0, plugin akan otomatis memperbarui dependensi pada classpath kompilasi ke Library A versi 2.0 untuk menghindari error.

Namun, jika classpath waktu proses menyertakan Library A versi 1.0 dan classpath kompilasi menyertakan Library A versi 2.0, plugin tidak akan mendowngrade dependensi pada classpath kompilasi ke Library A versi 1.0, dan Anda tetap mendapatkan error seperti berikut ini:

Conflict with dependency 'com.example.library:some-lib:2.0' in project 'my-library'.
Resolved versions for runtime classpath (1.0) and compile classpath (2.0) differ.

Untuk mengatasi masalah ini, lakukan salah satu langkah berikut:

  • Sertakan versi dependensi yang diinginkan dari dependensi sebagai dependensi api ke modul library Anda. Artinya, hanya modul library Anda yang mendeklarasikan dependensi, tetapi secara transitif, modul aplikasi juga akan memiliki akses ke API-nya.
  • Atau, Anda dapat mendeklarasikan dependensi pada kedua modul, tetapi Anda harus memastikan bahwa setiap modul menggunakan versi dependensi yang sama. Sebaiknya konfigurasikan properti skala project untuk memastikan konsistensi versi setiap dependensi di seluruh project Anda.

Menerapkan logika build kustom

Bagian ini menjelaskan topik lanjutan yang berguna jika Anda ingin memperluas plugin Android Gradle atau menulis plugin Anda sendiri.

Memublikasikan dependensi varian ke logika kustom

Library dapat memiliki fungsionalitas yang mungkin perlu digunakan oleh project atau subproject lain. Memublikasikan library adalah proses yang menjadikan library tersebut tersedia bagi konsumennya. Library dapat mengontrol dependensi mana saja yang dapat diakses oleh konsumennya pada waktu kompilasi dan waktu proses.

Ada dua konfigurasi terpisah yang menyimpan dependensi transitif setiap classpath yang harus digunakan oleh konsumen untuk menggunakan library seperti yang dijelaskan di bawah ini:

  • variant_nameApiElements: Konfigurasi ini menyimpan dependensi transitif yang tersedia bagi konsumen pada waktu kompilasi.
  • variant_nameRuntimeElements: Konfigurasi ini menyimpan dependensi transitif yang tersedia bagi konsumen pada waktu proses.

Untuk mempelajari hubungan antara berbagai konfigurasi lebih lanjut, baca Konfigurasi plugin library Java.

Strategi penyelesaian dependensi kustom

Suatu project mungkin menyertakan dependensi pada dua versi berbeda dari library yang sama, dan hal ini dapat mengakibatkan konflik dependensi. Misalnya, jika project Anda bergantung pada versi 1 modul A dan versi 2 modul B, dan modul A secara transitif bergantung pada versi 3 modul B, konflik versi dependensi akan muncul.

Untuk mengatasi konflik ini, Plugin Android Gradle menggunakan strategi penyelesaian dependensi berikut: saat plugin mendeteksi adanya versi berbeda dari modul yang sama dalam grafik dependensi, plugin akan memilih dependensi dengan nomor versi tertinggi secara default.

Namun, strategi ini mungkin tidak selalu berjalan seperti yang Anda harapkan. Untuk menyesuaikan strategi penyelesaian dependensi, gunakan konfigurasi berikut untuk menyelesaikan dependensi khusus varian yang diperlukan untuk tugas Anda:

  • variant_nameCompileClasspath: Konfigurasi ini berisi strategi penyelesaian untuk classpath kompilasi varian tertentu.
  • variant_nameRuntimeClasspath: Konfigurasi ini berisi strategi penyelesaian untuk classpath waktu proses varian tertentu.

Plugin Android Gradle menyertakan pengambil yang dapat Anda gunakan untuk mengakses objek konfigurasi setiap varian. Dengan demikian, Anda dapat menggunakan API varian untuk membuat kueri penyelesaian dependensi seperti dalam contoh di bawah ini:

android {
    applicationVariants.all { variant ->
        // Return compile configuration objects of a variant.
        variant.getCompileConfiguration().resolutionStrategy {
        // Use Gradle's ResolutionStrategy API
        // to customize how this variant resolves dependencies.
            ...
        }
        // Return runtime configuration objects of a variant.
        variant.getRuntimeConfiguration().resolutionStrategy {
            ...
        }
        // Return annotation processor configuration of a variant.
        variant.getAnnotationProcessorConfiguration().resolutionStrategy {
            ...
        }
    }
}