Aplikasi multi ragam berdasarkan pustaka multi ragam di Android Gradle

102

Aplikasi saya memiliki beberapa varian untuk beberapa pasar sistem penagihan dalam aplikasi.

Saya memiliki satu perpustakaan yang berbagi kode dasar untuk semua proyek saya. Jadi saya memutuskan untuk menambahkan sistem pembayaran tersebut ke perpustakaan ini sebagai cita rasa produk.

Pertanyaannya adalah bisakah perpustakaan android memiliki rasa produk?

Jika ya, bagaimana saya dapat memasukkan rasa yang berbeda dalam masing-masing rasa aplikasi?

Saya banyak mencari, dan saya tidak dapat menemukan apa pun tentang skenario ini. Satu-satunya hal yang dekat yang saya temukan adalah di http://tools.android.com/tech-docs/new-build-system/user-guide :

dependencies {
    flavor1Compile project(path: ':lib1', configuration: 'flavor1Release')
    flavor2Compile project(path: ':lib1', configuration: 'flavor2Release')
}

Saya mengubah konfigurasi ke hal yang berbeda tetapi tidak berhasil!

Saya menggunakan android studio 0.8.2.

Ali
sumber
setelah banyak pencarian, saya tidak menemukan cara untuk mencapai ini, bahkan saya memutakhirkan plugin android ke 3.4.2versi terbaru dan gradle ke yang terbaru 5.5.1, masih gagal dengan waktu kompilasi, atau penautan sumber daya gagal dalam aapt, atau tidak dapat menemukan simbol yang ada di dalam perpustakaan modul
VinceStyling

Jawaban:

141

Akhirnya saya menemukan cara melakukan ini, saya akan menjelaskannya di sini untuk orang lain yang menghadapi masalah yang sama:

Bagian kuncinya adalah menyetel publishNonDefault ke true di perpustakaan build.gradle, Kemudian Anda harus menentukan dependensi seperti yang disarankan oleh panduan pengguna.

Keseluruhan proyek akan menjadi seperti ini:

Library build.gradle:

apply plugin: 'com.android.library'

android {        
    ....
    publishNonDefault true
    productFlavors {
        market1 {}
        market2 {}
    }
}

proyek build.gradle:

apply plugin: 'com.android.application'

android {
    ....
    productFlavors {
        market1 {}
        market2 {}
    }
}

dependencies {
    ....
    market1Compile project(path: ':lib', configuration: 'market1Release')
    market2Compile project(path: ':lib', configuration: 'market2Release')
}

Sekarang Anda dapat memilih ragam aplikasi dan panel Build Variants dan pustaka akan dipilih sesuai dengan itu dan semua build dan run akan dilakukan berdasarkan ragam yang dipilih.

Jika Anda memiliki beberapa modul aplikasi berdasarkan pustaka Android Studio akan mengeluh tentang konflik pemilihan varian, Tidak apa-apa, abaikan saja.

masukkan deskripsi gambar di sini

Ali
sumber
Terima kasih telah berbagi, sekarang saya dapat menyingkirkan solusi defaultPublishConfig saya.
Delblanco
2
Menjalankan AS 1.1.0, solusi di atas tampaknya masih berfungsi, namun 1) pilihan debug / rilis build hilang dan saya tampaknya terus mengalami masalah dengan AIDL yang ditemukan di perpustakaan yang sering gagal menghasilkan kode yang sesuai. Ada pemikiran tentang ini?
3c71
1
@IgorGanapolsky buildTypes tidak ada hubungannya dengan ini. Setiap ragam memiliki semua jenis build (biasanya debug dan rilis) dan semuanya berfungsi dengan pendekatan ini.
Ali
1
@ An-droid mendefinisikan perpustakaan yang akan digunakan untuk rasa market1!
Ali
1
Mengapa ini disetel ke jenis build "rilis"? Apakah jenis build "rilis" dipilih selama build debug?
WindRider
35

Ada satu masalah dengan jawaban Ali . Kami kehilangan satu dimensi yang sangat penting dalam varian build kami. Jika kita ingin memiliki semua opsi (dalam contoh saya di bawah 4 (2 x 2)) kita hanya perlu menambahkan konfigurasi khusus dalam file modul utama build.gradle agar dapat menggunakan semua multi-flavor multi-buildType in Build Variants. Kita juga harus menyetel publishNonDefault true di modul perpustakaan file build.gradle .

Contoh solusi:

Lib build.gradle

android {

    publishNonDefault true

    buildTypes {
        release {
        }
        debug {
        }
    }
    productFlavors {
        free {
        }
        paid {
        }
    }
}

App build.gradle

android {

    buildTypes {
        debug {
        }
        release {
        }
    }
    productFlavors {
        free {
        }
        paid {
        }
    }
}

configurations {
    freeDebugCompile
    paidDebugCompile
    freeReleaseCompile
    paidReleaseCompile
}

dependencies {

    freeDebugCompile project(path: ':lib', configuration: 'freeDebug')
    paidDebugCompile project(path: ':lib', configuration: 'paidDebug')
    freeReleaseCompile project(path: ':lib', configuration: 'freeRelease')
    paidReleaseCompile project(path: ':lib', configuration: 'paidRelease')

}
AppiDevo
sumber
Setelah melakukan hal yang sama di Lamaran Saya Error:java.lang.RuntimeException: Error: more than one library with package name, terjadi
Chetan Joshi
21

Pembaruan untuk Android Plugin 3.0.0 dan lebih tinggi

Menurut Dokumentasi Android resmi - Migrasikan konfigurasi ketergantungan untuk modul lokal ,

Dengan resolusi dependensi yang peka varian, Anda tidak perlu lagi menggunakan konfigurasi khusus varian, seperti freeDebugImplementation, untuk dependensi modul lokal — plugin akan menangani ini untuk Anda

Sebagai gantinya, Anda harus mengonfigurasi dependensi Anda sebagai berikut:

dependencies {
    // This is the old method and no longer works for local
    // library modules:
    // debugImplementation project(path: ':library', configuration: 'debug')
    // releaseImplementation project(path: ':library', configuration: 'release')

    // Instead, simply use the following to take advantage of
    // variant-aware dependency resolution. You can learn more about
    // the 'implementation' configuration in the section about
    // new dependency configurations.
    implementation project(':library')

    // You can, however, keep using variant-specific configurations when
    // targeting external dependencies. The following line adds 'app-magic'
    // as a dependency to only the "debug" version of your module.

    debugImplementation 'com.example.android:app-magic:12.3'
}

Jadi dalam jawaban Ali, ubah

dependencies {
    ....
    market1Compile project(path: ':lib', configuration: 'market1Release')
    market2Compile project(path: ':lib', configuration: 'market2Release')
}

untuk

implementation project(':lib')

Dan plugin akan menangani konfigurasi spesifik varian secara otomatis. Semoga dapat membantu orang lain dalam mengupgrade Android Studio Plugin ke 3.0.0 dan lebih tinggi.

Harsh4789
sumber
7

Plugin Android saya adalah 3.4.0, dan saya merasa tidak memerlukan konfigurasi sekarang. Yang Anda butuhkan hanyalah memastikan flavorDimensions dan productFlavours dalam aplikasi berisi satu productFlavor dari flavorDimensions dan productFlavours yang sama di perpustakaan. Contoh:

Di mylibrary's build.gradle

apply plugin: 'com.android.library'

android {        
    ....
    flavorDimensions "mylibFlavor"

    productFlavors {
        market1
        market2
    }
}

build.gradle aplikasi:

apply plugin: 'com.android.application'

android {
    ....
    flavorDimensions "mylibFlavor", "appFlavor"
    productFlavors {
        market1 {
            dimension "mylibFlavor"
        }
        market2 {
            dimension "mylibFlavor"
        }
        common1 {
            dimension "appFlavor"
        }
        common2 {
            dimension "appFlavor"
        }
    }
}

dependencies {
    ....
    implementation project(path: ':mylibrary')
}

Setelah sinkronisasi, Anda dapat mengganti semua opsi di Build Variants Window: masukkan deskripsi gambar di sini

JiajiaGu
sumber
Tetapi bagaimana jika saya tidak ingin memiliki rasa yang sama di modul aplikasi utama saya? Misalkan saya memiliki beberapa modul aplikasi yang memiliki rasa spesifiknya sendiri dan satu modul umum yang memiliki rasa sendiri dan saya ingin menggunakan lib saya dengan rasa tertentu di aplikasi saya. Bagaimana Anda melakukannya? Tidak masuk akal untuk menyalin rasa lib saya ke semua aplikasi.
Billda
@Billda Anda tidak perlu menyalin semua, cukup simpan satu productFlavor yang sama di aplikasi, untuk contoh saya, saya bisa menyimpan market1 atau market2 di build.gradle aplikasi.
JiajiaGu
2

Agar ragam berfungsi pada pustaka AAR, Anda perlu mendefinisikan defaultPublishConfig di file build.gradle modul Android Library Anda.

Untuk informasi lebih lanjut, lihat: Publikasi Perpustakaan .

Publikasi Perpustakaan

Secara default, perpustakaan hanya menerbitkan varian rilisnya. Varian ini akan digunakan oleh semua project yang mereferensikan library tersebut, apa pun varian yang mereka buat sendiri. Ini adalah batasan sementara karena batasan Gradle yang sedang kami upayakan untuk dihapus. Anda dapat mengontrol varian mana yang dipublikasikan:

android {defaultPublishConfig "debug"}

Perhatikan bahwa nama konfigurasi penerbitan ini merujuk pada nama varian lengkap. Rilis dan debug hanya berlaku jika tidak ada varian. Jika Anda ingin mengubah varian terbitan default saat menggunakan ragam, Anda harus menulis:

android {defaultPublishConfig "flavor1Debug"}

David Lev
sumber
1

Saat ini tidak mungkin, meskipun jika saya ingat dengan benar itu adalah fitur yang ingin mereka tambahkan. (Edit 2: link , link2 )

Edit: Untuk saat ini saya menggunakan defaultPublishConfigopsi untuk mendeklarasikan varian library mana yang dipublikasikan:

android {
    defaultPublishConfig fullRelease
    defaultPublishConfig demoRelease 
}
Delblanco
sumber
1
Jadi, setiap kali saya akan mengompilasi aplikasi, saya harus mengubahnya di build.gradle library?
Ali
Ya ... setiap kali Anda ingin mengompilasi aplikasi dengan rasa yang berbeda.
Delblanco
Sebenarnya ketika saya mendefinisikan ragam untuk modul perpustakaan, paket R yang diwariskan tidak ditemukan modul aplikasi.
Ali
Apakah Anda menyinkronkan file gradle dalam AS?
Delblanco
@Delblanco Ini sepertinya pekerjaan manual dan sangat rapuh (pengembang malas dan lupa memodifikasi file build.gradle mereka).
IgorGanapolsky
1

Saya tahu subjek ini telah ditutup, tetapi hanya pembaruan dengan gradle 3.0, lihat ini: https://developer.android.com/studio/build/gradle-plugin-3-0-0-migration.html#variant_aware dan grep matchingFallbacksdan missingDimensionStrategy. Sekarang jauh lebih mudah untuk mendeklarasikan dependensi antara ragam modul.

... dan dalam kasus yang tepat dengan gradle3.0 ini, karena rasa memiliki nama yang sama, gradle akan memetakannya secara ajaib, tidak diperlukan konfigurasi.

AlexG
sumber
Bagi saya tampaknya hal-hal yang dihasilkan waktu proses dilewati. Sebagai contoh simonvt-> schematics generation tidak berfungsi lagi dengan cara baru bagi saya. : - /
Stefan Sprenger
1

Saya juga mengalami masalah menyusun modul untuk berbagai opsi.

Apa yang saya temukan:

Sepertinya kita tidak perlu menambahkan publishNonDefault trueke dalam build.gradlefile lib , karena Gradle 3.0.1 .

Setelah mendekompilasi kelas BaseExtensionmenemukan ini:

public void setPublishNonDefault(boolean publishNonDefault) {
   this.logger.warn("publishNonDefault is deprecated and has no effect anymore. All variants are now published.");
}

Dan alih-alih:

dependencies {
...
   Compile project(path: ':lib', configuration: 'config1Debug')
}

Kita harus menggunakan:

dependencies {
...
   implementation project(':lib')
}

Hanya yang penting, adalah menambahkan configurations {...}bagian ke build.gradle.

Jadi, varian terakhir dari build.gradlefile aplikasi adalah:

buildTypes {
   debug {
      ...
   }

   release {
      ...
   }
}

flavorDimensions "productType", "serverType"
productFlavors {
   Free {
      dimension "productType"
      ...
   }
   Paid {
      dimension "productType"
      ...
   }
   Test {
      dimension "serverType"
      ...
   }
   Prod {
      dimension "serverType"
      ...
   }
}

configurations {
   FreeTestDebug
   FreeTestRelease
   FreeProdDebug
   FreeProdRelease
   PaidTestDebug
   PaidTestRelease
   PaidProdDebug
   PaidProdRelease
}

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

Selain itu, Anda dapat menggunakan varian Filter untuk membatasi varian build.

Ps jangan lupa menyertakan modul di settings.gradlefile, seperti:

include ':app'
include ':lib'
project(':lib').projectDir = new File('app/libs/lib')
Sergio
sumber
Pak, dapatkah Anda menjelaskan bagaimana skrip akan menentukan cuaca untuk memasukkan perpustakaan ke konfigurasi tertentu atau tidak? Maksud saya, saya punya kasus ketika saya perlu menggunakan beberapa lib untuk rasa tertentu, tetapi saya tidak perlu menggunakannya untuk rasa lain
Jenya Kirmiza
Tidak masuk ke situasi seperti itu. Tetapi seorang pengembang tutorial google.android.com/studio/build/dependencies menyarankan untuk menambahkan awalan sebelum perintah "implementasi" di blok "dependencies {...}". Yaitu dependensi {paidImplementation project (': lib')}, atau dependensi {debugImplementation project (': lib')}, atau beberapa kombinasi varian dependensi {paidProdDebugImplementation project (': lib')}. Lihat dan beri kami umpan balik :)
Sergio