Menggunakan Build Flavours - Menyusun folder sumber dan build.gradle dengan benar

166

Harap dicatat: Jawaban diedit setelah Jawaban Xavier

Saya mencoba menggunakan Build Flavours berbeda untuk satu proyek Aplikasi yang sama di Android Studio. Namun, saya sepertinya mengalami kesulitan mengaturnya agar berfungsi dengan benar.

Langkah:

  1. Buat Proyek Android Studio baru, bernama 'Tes'.
  2. Buka build.gradle * dan tambahkan baris berikut:

    productFlavors {
    flavor1 {
        packageName 'com.android.studio.test.flavor1'
        }
    flavor2 {
        packageName 'com.android.studio.test.flavor2'
        }
    }
    
  3. Setelah memulai ulang Android Studio, saya sekarang melihat 4 varian build di bawah bagian Build Variants. Berarti kami berhasil mengatur rasa produk sejauh ini. **
  4. Membuat folder Sumber baru untuk flavor1 ; Namun, saya tidak yakin apakah saya melakukannya dengan cara yang benar. Begini cara saya melakukannya:

    • Perlu diingat bahwa nama Paket saya untuk proyek ini adalah: com.foo.test
    • Klik kanan pada srcfolder, untuk flavor1, saya benar-benar membuat folder individu di explorer, dengan cara strukturnya src/flavor1/java/com/foo/test/MainActivity.java.
    • Hal di atas berfungsi dengan baik, karena folder 'java' berwarna biru , yang berarti IDE mengetahui direktori sumbernya yang aktif. Juga, paket itu dibuat secara otomatis. Meskipun demikian, saya mendapatkan peringatan untuk duplikat kelas ditemukan. Lihat tangkapan layar di sini.
    • Untuk flavour2, saya mencoba membuat paket secara manual, tetapi folder 'src' untuk flavour2 tampaknya tidak berwarna biru, dan karena itu pilihannya berbeda ketika diklik kanan, dan 'Paket Baru' tidak tersedia untuk saya gunakan. Lihat gambar di sini.
    • Perhatikan bahwa untuk flavor1, saya juga membuat direktori 'res', yang berubah menjadi biru, tetapi terlepas dari itu, tidak menawarkan kemampuan untuk membuat file Sumber Daya Android, atau direktori sumber daya Andorid, jika saya ingin menggunakan yang berbeda resoruces untuk rasa yang berbeda.

Apakah saya melakukan sesuatu yang salah? Atau apakah saya melewatkan sesuatu? Beritahu saya jika Anda membutuhkan info lebih lanjut.

* Proyek saya tampaknya memiliki dua file build.gradle. Satu terletak di root folder proyek (\ GradleTest), ini kosong. Yang kedua terletak di root subfolder dari \ GradleTest, juga berlabel 'GradleTest' (GradleTest-GradleTest), ini adalah yang sudah memiliki kode ketika dibuka; oleh karena itu, itulah yang saya edit.

** Aku memeriksa pengaturan Gradle dan tampaknya Gunakan auto-impor itu sudah diaktifkan. Meskipun demikian, membuat perubahan pada file build.gradle tidak secara otomatis memperbarui varian build. Catatan: Saya juga mencoba menggunakan Build - Rebuild Project, dan / atau Build - Make Project, no-go. Saya masih harus menutup proyek, dan membuka kembali agar perubahan berlaku.

daniel_c05
sumber
Perhatikan bahwa applicationIdsekarang yang didukung bukan packageName.
Hamzeh Soboh

Jawaban:

220

Jika Anda masuk ke preferensi Studio, di bawah bagian Gradle, Anda dapat mengaktifkan impor otomatis untuk proyek Anda (kami akan mengaktifkannya secara default nanti). Ini akan memungkinkan Studio mengimpor kembali build.gradle Anda setiap kali Anda mengeditnya.

Membuat rasa tidak berarti Anda akan menggunakan kode khusus untuk mereka sehingga kami tidak membuat folder. Anda harus membuatnya sendiri.

Jika Anda melihat pembicaraan IO saya, Anda akan melihat bagaimana kami menggabungkan nilai-nilai bersama dari rasa dan tipe build untuk membuat varian.

Untuk sumber Java:

src/main/java
src/flavor1/java
src/debug/java

semua 3 digunakan untuk membuat output tunggal. Ini berarti mereka tidak dapat mendefinisikan kelas yang sama.

Jika Anda ingin memiliki versi berbeda dari kelas yang sama dalam dua rasa, Anda harus membuatnya dalam kedua rasa.

src/flavor1/java/com/foo/A.java
src/flavor2/java/com/foo/A.java

Dan kemudian kode Anda di src / main / java dapat dilakukan

import com.foo.A

tergantung pada rasa yang dipilih, versi com.foo.A yang tepat digunakan.

Ini juga berarti kedua versi A harus memiliki API yang sama (setidaknya ketika datang ke API yang digunakan oleh kelas di src / main / java / ...

Edit untuk mencocokkan pertanyaan yang direvisi

Selain itu, penting untuk menempatkan kelas A yang sama hanya di folder sumber yang saling eksklusif. Dalam hal ini src / flavour1 / java dan src / flavour2 / java tidak pernah dipilih bersama, tetapi main dan flav1 adalah.

Jika Anda ingin memberikan versi aktivitas yang berbeda dalam rasa yang berbeda, jangan letakkan di src / main / java.

Perhatikan bahwa jika Anda memiliki 3 rasa dan hanya menginginkan yang khusus untuk rasa1, sementara rasa2 dan rasa3 berbagi aktivitas yang sama, Anda dapat membuat folder sumber umum untuk dua aktivitas lainnya. Anda memiliki fleksibilitas total dalam membuat folder sumber baru dan mengonfigurasi set sumber untuk menggunakannya.

Ke poin Anda yang lain:

Itu normal bahwa folder sumber rasa ke-2 tidak biru. Anda perlu beralih ke citarasa ke-2 untuk mengaktifkannya, dan kemudian Anda bisa membuat paket dan kelas di dalamnya. Sampai saat itu, Studio tidak menganggapnya sebagai folder sumber. Semoga kami akan meningkatkan ini di masa mendatang untuk membuat IDE mengetahui folder sumber yang tidak aktif tersebut .

Saya pikir itu juga normal bahwa Anda tidak dapat membuat file sumber daya di folder res. Sistem menu belum diperbarui untuk menangani semua folder sumber daya tambahan ini. Ini akan datang nanti.

Xavier Ducrohet
sumber
1
Saya menambahkan beberapa elemen baru di akhir jawaban saya, tetapi duplikatnya masuk akal. Anda tidak dapat memiliki kelas yang sama di kedua src / main / java dan src / flavor1 / java karena keduanya digunakan saat memilih flavor1. Dalam jawaban saya, perhatikan bagaimana saya menempatkan kelas yang sama di hanya flavor1 / java dan flavor2 / java karena ini eksklusif dan tidak pernah diaktifkan bersama.
Xavier Ducrohet
Hai Xavier, dapatkah Anda memberi saya deskripsi yang lebih terperinci tentang bagaimana saya dapat menggunakan versi berbeda dari suatu aktivitas sesuai selera saya? Saya memiliki proyek uji di mana saya ingin menggunakan berbagai versi MainActivity saya, tetapi di kedua apks (flavor1 dan flavor2) hanya ada versi main / java. Ketika saya tidak memasukkan MainActivity di dalam main / java, aplikasi mogok ketika saya memulainya.
JensJensen
@XavierDucrohet bagaimana kalau memiliki sumber daya yang berbeda serta kode berbeda berdasarkan rasa, tetapi memilikinya dalam modul yang berbeda sehingga kita dapat memasukkan satu modul atau yang lain berdasarkan rasa, tanpa harus mencampur kode dan sumber daya dalam proyek root yang sama? Apakah itu didukung?
Valerio Santinelli
3
@ValerioSantinelli Anda dapat melakukan dependensi per rasa. GunakanflavorCompile ...
Xavier Ducrohet
@XavierDucrohet Saya mencoba apa yang Anda sarankan tetapi tidak berfungsi seperti yang saya harapkan. Anda dapat melihat bagaimana proyek saya terstruktur di sana: stackoverflow.com/q/24410995/443136
Valerio Santinelli
19

"Rasa Produk" di Android

Terkadang saya ditanya bagaimana cara bekerja dengan berbagai host, ikon, atau bahkan nama paket, tergantung pada versi berbeda dari aplikasi yang sama.

Ada banyak alasan untuk melakukan ini dan satu cara mudah untuk pergi: Rasa Produk.

Anda dapat mendefinisikan pada skrip build.gradle Anda hal-hal semacam ini yang telah saya jelaskan sebelumnya.

Citarasa produk Bagian dari artikel ini adalah pemikiran tertulis tentang citarasa produk, jadi, apa itu? Mengenai dokumentasi Android:

Citarasa produk mendefinisikan versi kustom aplikasi yang dibuat oleh proyek. Satu proyek dapat memiliki citarasa berbeda yang mengubah aplikasi yang dihasilkan.

Bagaimana Anda bisa mendefinisikannya? Anda harus menulis di build.gradle Anda yang rasa yang ingin Anda tetapkan:

productFlavors {  
        ...
        devel {
            ...
        }

        prod {
            ...
        }
    }

Sekarang, kita akan memiliki dua rasa berbeda dari aplikasi kita. Anda dapat memeriksanya di Android Studio juga di dalam tab Build Variants

Bangun varian

Beberapa nama paket

Bagaimana jika Anda ingin menginstal satu aplikasi di ponsel Anda dengan status pengembangan dan satu untuk status produksi. Seperti yang mungkin Anda ketahui, Anda hanya dapat menginstal satu aplikasi dengan nama paket yang sama (jika Anda mencoba menginstal beberapa APK baru dengan yang sama dengan yang diinstal pada ponsel Anda, ia akan mencoba memperbaruinya).

Satu-satunya hal yang harus Anda lakukan adalah mendefinisikannya pada setiap rasa produk Anda:

android {  
    productFlavors {
        devel {
            applicationId "zuul.com.android.devel"
        }
        prod {
            applicationId "zuul.com.android"
        }
    }
}

Mengirim permintaan ke beberapa host tergantung pada rasa. Seperti sebelumnya, Anda harus memasukkan beberapa params pada bidang konfigurasi rasa produk Anda.

android {  
    productFlavors {
        devel {
            applicationId "zuul.com.android.devel"
            buildConfigField 'String', 'HOST', '"http://192.168.1.34:3000"'

        }

        prod {
            applicationId "zuul.com.android"
               buildConfigField 'String', 'HOST', '"http://api.zuul.com"'

        }
    }
}

Sebagai contoh, kami akan mencoba menunjukkan kepada Anda bagaimana Anda dapat mengintegrasikan ini dengan Retrofit untuk mengirim permintaan ke server yang sesuai tanpa menangani server mana yang Anda tunjuk dan didasarkan pada rasanya. Dalam hal ini, ini adalah kutipan dari aplikasi Android Zuul:

public class RetrofitModule {

    public ZuulService getRestAdapter() {
        RestAdapter restAdapter = new RestAdapter.Builder()
                .setEndpoint(BuildConfig.HOST)
                .setLogLevel(RestAdapter.LogLevel.FULL)
                .build();
        return restAdapter.create(ZuulService.class);
    }

}

Seperti yang Anda lihat, Anda hanya perlu menggunakan BuildConfigclass untuk mengakses variabel yang baru saja Anda tetapkan.

Variabel apa pun yang tersedia melalui kode Anda Variabel HOST bukan satu-satunya yang dapat Anda ungkapkan dalam kode Anda. Anda dapat melakukannya dengan apa pun yang Anda inginkan:

prod {  
    applicationId "zuul.com.android"
    buildConfigField 'String', 'HOST', '"http://api.zuul.com"'
    buildConfigField 'String', 'FLAVOR', '"prod"'
    buildConfigField "boolean", "REPORT_CRASHES", "true"
}

Anda dapat mengaksesnya sebagai berikut:

BuildConfig.HOST  
BuildConfig.FLAVOR  
BuildConfig.REPORT_CRASHES  

Ikon yang berbeda per rasa Jika Anda ingin memiliki ikon yang berbeda per rasa, sehingga Anda dapat secara visual mendeteksi yang mana yang Anda buka (Anda bisa melakukannya dengan namanya juga ... Tapi itu tidak sesuai dengan ruang!), Anda hanya perlu untuk menentukan struktur direktori baru untuk masing-masing rasa.

Dalam contoh saya baru saja menggunakan ada dua rasa: devel dan prod. Kemudian, kita dapat mendefinisikan dua struktur direktori baru sehingga kita dapat mendefinisikan sumber daya yang kita inginkan:

struktur

Ini bekerja dengan jenis sumber daya lain seperti strings.xml, integers.xml, arrays.xml, dll.

Konfigurasikan Pengaturan Penandatanganan

Untuk mengonfigurasi konfigurasi penandatanganan secara manual untuk tipe build rilis Anda menggunakan konfigurasi build Gradle:

1. Buat keystore. Keystore adalah file biner yang berisi sekumpulan kunci privat. Anda harus menyimpan keystore di tempat yang aman dan terlindungi. 2. Buat kunci pribadi. Kunci pribadi mewakili entitas yang akan diidentifikasi dengan aplikasi, seperti orang atau perusahaan. 3. Tambahkan konfigurasi penandatanganan ke file build.gradle tingkat modul:

android {
...
defaultConfig {...}
signingConfigs {
    release {
        storeFile file("myreleasekey.keystore")
        storePassword "password"
        keyAlias "MyReleaseKey"
        keyPassword "password"
    }
}
buildTypes {
    release {
        ...
        signingConfig signingConfigs.release
    }
}

}

Buat APK yang ditandatangani:

Untuk membuat APK yang ditandatangani, pilih Build> Generate Signed APK dari menu utama. Paket di app / build / apk / app-release.apk sekarang ditandatangani dengan kunci rilis Anda.

ref: https://developer.android.com/studio/build/build-variants.html#signinghttp://blog.brainattica.com/how-to-work-with-flavours-on-android/

A-Droid Tech
sumber
7

Tampaknya Anda perlu memuat ulang proyek Anda setelah menambahkan rasa baru build.gradle. Setelah itu, Anda akan melihat 4 build Variants dalam tampilan Build Variants (Anda mengaksesnya dari tepi kiri jendela).

Mengenai direktori sumber tambahan, sepertinya Anda harus membuatnya dengan tangan: src/flavor1/javadan src/flavor2/java. Anda akan melihat bahwa mengubah cita rasa dalam tampilan "Build Variants" akan mengubah direktori sumber yang sedang aktif (direktori berwarna biru ketika itu adalah direktori sumber aktif )

Akhirnya, "gradle akan membuat sourceSet baru untuk rasa baru Anda" berarti gradle akan membuat objek android.sourceSets.flavor1dan android.sourceSets.flavor2dan Anda dapat menggunakannya dalam skrip build.gradle Anda. Tapi objek-objek itu dibuat secara dinamis, itu sebabnya Anda tidak melihatnya di build.gradle(Saya sarankan Anda membaca ini: http://www.gradle.org/docs/current/userguide/tutorial_using_tasks.html Khususnya 6.6: itu menjelaskan pembuatan tugas dinamis. Skrip gradle adalah skrip groovy, jadi saya sarankan Anda untuk terbiasa dengan groovy)

ben75
sumber
2
Saya pikir catatan impor adalah Build VariantsView, saya tidak memperhatikannya.
Chris.Jenkins
2

Saya memiliki masalah yang sama ketika saya memigrasikan proyek saya ke Gradle. Masalahnya adalah build tidak menemukan folder sumber daya yang tepat. Saya memperbaikinya dengan menambahkan ini di bawah elemen android di build.gradle:

sourceSets {
        main {
            res.srcDirs = ['myProject/res']
        }
    }
Tomer
sumber
0

Sesuatu yang penting dan menghalangi saya untuk sementara waktu adalah bahwa nama rasa yang harus cocok dengan paket sebagai lawan dari paket yang didefinisikan di dalam definisi rasa secara bertahap. Sebagai contoh:

src/flavor1/java/com/foo/A.java

akan cocok

productFlavors {
  flavor1 {
    packageName 'com.android.studio.test.foobar'
  }
}

tapi

src/foobar/java/com/foo/A.java tidak akan digunakan untuk build flavor1.

bitrock
sumber
0

Dalam gradle:

Untuk Jenis Bangun, Anda hanya perlu:

buildTypes {
   release{
    //proguard, signing etc.
   }
   debug {
    //development
   }
  }
}

Dan kemudian untuk rasa Anda menambahkan yang Anda butuhkan

productFlavors {
    pro {
        applicationIdSuffix '.paid'
        buildConfigField 'boolean', 'PRO', 'true'
    }
    free {
        applicationIdSuffix '.free'
        buildConfigField 'boolean', 'PRO', 'false'
    }
}
TouchBoarder
sumber