Saya telah menyiapkan Gradle untuk menambahkan akhiran nama paket ke aplikasi debug saya sehingga saya bisa memiliki versi rilis yang saya gunakan dan versi debug di satu ponsel. Saya merujuk ini: http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Types
File build.gradle saya terlihat seperti ini:
...
android
{
...
buildTypes
{
debug
{
packageNameSuffix ".debug"
versionNameSuffix " debug"
}
}
}
Semuanya berfungsi dengan baik sampai saya mulai menggunakan ContentProvider di aplikasi saya. Saya mendapat:
Failure [INSTALL_FAILED_CONFLICTING_PROVIDER]
Saya memahami bahwa ini terjadi karena dua aplikasi (rilis dan debug) mendaftarkan otoritas Penyedia Konten yang sama.
Saya melihat satu kemungkinan untuk menyelesaikan ini. Jika saya mengerti dengan benar, Anda harus dapat menentukan file yang berbeda untuk digunakan saat membangun. Kemudian saya harus dapat menempatkan otoritas yang berbeda dalam file sumber daya yang berbeda (dan dari otoritas set Manifes sebagai sumber daya string) dan memberi tahu Gradle untuk menggunakan sumber daya yang berbeda untuk debug build. Apakah itu mungkin? Jika ya, maka petunjuk tentang cara mencapainya akan luar biasa!
Atau mungkinkah mengubah Manifes secara langsung menggunakan Gradle? Solusi lain tentang cara menjalankan aplikasi yang sama dengan ContentProvider di satu perangkat selalu diterima.
Jawaban:
Tidak ada jawaban yang memuaskan saya, namun Liberty dekat. Jadi begini cara saya melakukannya. Pertama-tama saat saya bekerja dengan:
Tujuan saya adalah menjalankan
Debug
versi bersama denganRelease
versi pada perangkat yang sama menggunakan yang samaContentProvider
.Dalam build.gradle akhiran set aplikasi Anda untuk build Debug:
Dalam file AndroidManifest.xml set
android:authorities
properti AndaContentProvider
:Di properti kumpulan kode
AUTHORITY
yang dapat digunakan di mana pun diperlukan dalam implementasi Anda:Tip: Sebelumnya
BuildConfig.PACKAGE_NAME
Itu dia! Ini akan bekerja seperti pesona. Teruskan membaca jika Anda menggunakan SyncAdapter!
Pembaruan untuk SyncAdapter (14.11.2014)
Sekali lagi saya akan mulai dengan pengaturan saya saat ini:
Pada dasarnya, jika Anda perlu menyesuaikan beberapa nilai untuk berbagai build, Anda dapat melakukannya dari file build.gradle:
BuildConfig.java
kelasSebagai alternatif sumber daya, Anda bisa membuat direktori buildType atau ragam terpisah dan mengganti XML atau nilai di dalamnya. Namun, saya tidak akan menggunakannya dalam contoh di bawah ini.
Contoh
Dalam file build.gradle tambahkan yang berikut ini:
Anda akan melihat hasil di kelas BuildConfig.java
dan di build / generated / res / generated / debug / values / generated.xml
Di authenticator.xml Anda menggunakan sumber daya yang ditentukan dalam file build.gradle
Di syncadapter.xml Anda, gunakan sumber daya yang sama lagi dan @ string / otoritas juga
Kiat: pelengkapan otomatis (Ctrl + Spasi) tidak berfungsi untuk sumber daya yang dihasilkan ini sehingga Anda harus mengetiknya secara manual
sumber
Kiat sistem build Android baru: penggantian nama otoritas ContentProvider
Saya kira Anda semua telah mendengar tentang sistem build berbasis Android Gradle yang baru. Jujur saja, sistem build baru ini merupakan langkah maju yang besar dibandingkan dengan yang sebelumnya. Ini belum final (pada tulisan ini, versi terbaru adalah 0.4.2) tetapi Anda sudah dapat menggunakannya dengan aman di sebagian besar proyek Anda.
Saya secara pribadi telah mengalihkan sebagian besar proyek saya ke sistem build baru ini dan mengalami beberapa masalah karena kurangnya dukungan dalam beberapa situasi tertentu. Salah satunya adalah dukungan untuk penggantian nama otoritas ContentProvider
Sistem baru Android yang dibangun memungkinkan Anda menangani berbagai jenis aplikasi hanya dengan mengubah nama paket pada waktu pembuatan. Salah satu keuntungan utama dari peningkatan ini adalah Anda sekarang dapat menginstal dua versi berbeda dari aplikasi Anda pada perangkat yang sama pada waktu yang sama. Misalnya:
Dengan menggunakan konfigurasi Gradle, Anda dapat menyusun dua APK berbeda:
• APK debug dengan nama paket com.cyrilmottier.android.app.debug • APK rilis dengan nama paket com.cyrilmottier.android.app
Satu-satunya masalah adalah Anda tidak akan dapat menginstal dua APK secara bersamaan jika keduanya mengekspos ContentProvider dengan otoritas yang sama. Secara logis kita perlu mengganti nama otoritas tergantung pada jenis build saat ini… tetapi ini tidak didukung oleh sistem build Gradle (belum? ... Saya yakin ini akan segera diperbaiki). Jadi, inilah cara untuk pergi:
Pertama, kita perlu memindahkan deklarasi ContentProvider manifes Android penyedia ke jenis build yang sesuai. Untuk melakukan itu kami hanya memiliki:
src / debug / AndroidManifest.xml
src / release / AndroidManifest.xml
Pastikan untuk menghapus deklarasi ContentProvider dari AndroidManifest.xml di src / main / karena Gradle tidak tahu cara menggabungkan ContentProviders yang memiliki nama yang sama tetapi otoritas yang berbeda.
Akhirnya kita mungkin perlu mengakses otoritas dalam kode. Ini dapat dilakukan dengan mudah menggunakan file BuildConfig dan metode buildConfig:
Berkat solusi ini, Anda akan dapat menggunakan BuildConfig.PROVIDER_AUTHORITY di ProviderContract Anda dan menginstal dua versi aplikasi yang berbeda pada saat yang sama.
Asli di Google+: https://plus.google.com/u/0/118417777153109946393/posts/EATUmhntaCQ
sumber
Meskipun contoh Cyril berfungsi dengan baik jika Anda hanya memiliki beberapa jenis build, ini akan menjadi rumit dengan cepat jika Anda memiliki banyak jenis build dan / atau ragam produk karena Anda perlu mempertahankan banyak AndroidManifest.xml yang berbeda.
Proyek kami terdiri dari 3 jenis build berbeda dan 6 ragam dengan total 18 varian build, jadi kami menambahkan dukungan untuk ".res-auto" di otoritas ContentProvider, yang memperluas ke nama paket saat ini dan menghilangkan kebutuhan untuk mempertahankan AndroidManifest.xml yang berbeda
Kode contoh dapat ditemukan di sini: https://gist.github.com/cmelchior/6988275
sumber
Karena plugin versi 0.8.3 (sebenarnya 0.8.1 tetapi tidak berfungsi dengan benar) Anda dapat menentukan sumber daya dalam file build sehingga ini bisa menjadi solusi yang lebih bersih karena Anda tidak perlu membuat file string atau debug / rilis tambahan folder.
build.gradle
AndroidManifest.xml
sumber
Saya tidak tahu apakah ada yang menyebutkannya. Sebenarnya setelah plugin gradle android 0.10+, penggabungan manifes akan memberikan dukungan resmi untuk fungsi ini: http://tools.android.com/tech-docs/new-build-system/user-guide/manifest-merger
Di AndroidManifest.xml, Anda dapat menggunakan $ {packageName} seperti ini:
Dan di build.gradle Anda, Anda dapat memiliki:
Lihat contoh lengkapnya di sini: https://code.google.com/p/anymemo/source/browse/AndroidManifest.xml#152
dan di sini: https://code.google.com/p/anymemo/source/browse/build.gradle#41
sumber
Gunakan
${applicationId}
placeholder di xml danBuildConfig.APPLICATION_ID
dalam kode.Anda perlu memperluas skrip build untuk mengaktifkan placeholder di file xml selain manifes. Anda dapat menggunakan direktori sumber per varian build untuk menyediakan versi file xml yang berbeda, tetapi pemeliharaan akan menjadi sangat rumit dengan sangat cepat.
AndroidManifest.xml
Anda dapat menggunakan placeholder applicationId di luar kotak di manifes. Nyatakan penyedia Anda seperti ini:
Perhatikan
${applicationId}
sedikit. Ini diganti pada waktu build dengan applicationId sebenarnya untuk varian build yang sedang dibuat.Dalam kode
ContentProvider Anda perlu membuat string otoritas dalam kode. Itu bisa menggunakan kelas BuildConfig.
Perhatikan
BuildConfig.APPLICATION_ID
sedikit. Ini adalah kelas yang dihasilkan dengan applicationId sebenarnya untuk varian build yang sedang dibuat.res / xml / files, misalnya syncadapter.xml, accountauthenticator.xml
Jika Anda ingin menggunakan Adaptor Sinkronisasi, Anda perlu menyediakan meta-data untuk ContentProvider dan AccountManager dalam file xml di direktori res / xml /. Placeholder applicationId tidak didukung di sini. Tetapi Anda dapat memperluas sendiri skrip build untuk meretasnya.
Sekali lagi, perhatikan
${applicationId}
. Ini hanya berfungsi jika Anda menambahkan skrip gradle di bawah ini ke root modul Anda dan menerapkannya dari build.gradle.build.gradle
Terapkan skrip build tambahan dari skrip modul build.gradle. Tempat yang bagus adalah di bawah plugin gradle Android.
build-processApplicationId.gradle
Di bawah ini adalah sumber yang berfungsi untuk skrip build res / xml / placeholder. Versi terdokumentasi yang lebih baik tersedia di github . Perbaikan dan ekstensi dipersilakan.
Strings.xml
Menurut pendapat saya, tidak perlu menambahkan dukungan placeholder untuk string sumber daya. Untuk kasus penggunaan di atas setidaknya tidak diperlukan. Namun, Anda dapat dengan mudah mengubah skrip untuk tidak hanya mengganti placeholder di direktori res / xml /, tetapi juga di direktori res / values /.
sumber
Saya lebih suka campuran antara Cyril dan rciovati. Menurut saya lebih sederhana, Anda hanya memiliki dua modifikasi.
The
build.gradle
terlihat seperti:Dan
AndroidManifest.xml
:sumber
gradle.build
authenticator.xml
sync_adapter.xml
AndroidManifest.xml
Kode:
sumber
Berdasarkan sampel oleh @ChristianMelchior, inilah solusi saya, yang memperbaiki dua masalah dalam solusi sebelumnya:
solusi yang mengubah values.xml dalam direktori build menyebabkan rekondisi penuh sumber daya (termasuk aapt dari semua drawable)
karena alasan yang tidak diketahui, IntelliJ (dan mungkin Android Studio) tidak andal memproses sumber daya, menyebabkan build berisi
.res-auto
otoritas penyedia yang tidak digantiSolusi baru ini melakukan lebih banyak hal secara Gradle dengan membuat tugas baru dan memungkinkan build inkremental dengan menentukan file input dan output.
buat file (dalam contoh saya taruh di
variants
direktori), diformat seperti file xml sumber daya, yang berisi sumber daya string. Ini akan digabungkan ke dalam sumber daya aplikasi, dan kemunculan apa pun.res-auto
di nilai akan diganti dengan nama paket varian, misalnya<string name="search_provider">.res-auto.MySearchProvider</string>
tambahkan
build_extras.gradle
file dari inti ini ke proyek Anda dan referensikan dari utamabuild.gradle
dengan menambahkanapply from: './build_extras.gradle'
suatu tempat di atasandroid
blokpastikan Anda menyetel nama paket default dengan menambahkannya ke
android.defaultConfig
blokbuild.gradle
di
AndroidManifest.xml
dan file konfigurasi lainnya (sepertixml/searchable.xml
untuk penyedia penelusuran pelengkapan otomatis), rujuk penyedia (misalnya@string/search_provider
)jika Anda ingin mendapatkan nama yang sama, Anda dapat menggunakan
BuildConfig.PACKAGE_NAME
variabel, misalnyaBuildConfig.PACKAGE_NAME + ".MySearchProvider"
https://gist.github.com/paour/9189462
Pembaruan: metode ini hanya berfungsi di Android 2.2.1 dan yang lebih baru. Untuk platform sebelumnya, lihat jawaban ini , yang memiliki rangkaian masalahnya sendiri, karena penggabungan manifes baru masih sangat sulit di tepinya…
sumber
variants/res-auto-values.xml
relatif terhadap/Applications/Android Studio.app/bin/
. yaitu saya tidak mendapatkan FileNotFoundException untuk/Applications/Android Studio.app/bin/variants/res-auto-values.xml
. Saya menggunakan mac. Ini adalah solusi yang bagus, tetapi saya ingin membuatnya berfungsi di IDE untuk anggota tim lainnya.System.getProperty("user.dir")
, yang mengembalikan hasil berbeda saat dipanggil oleh build Android Studio. Solusinya adalah dengan menggunakan jalur yang berhubungan dengan direktori proyek, yang dikembalikan dengangradle.startParameter.getProjectDir()
. Lihat komentar saya di inti terkait Paour juga.Saya telah menulis posting blog dengan proyek sampel Github yang menangani masalah ini (dan masalah serupa lainnya) dengan cara yang sedikit berbeda dari Cyril.
http://brad-android.blogspot.com/2013/08/android-gradle-building-unique-build.html
sumber
Sayangnya, versi plugin android saat ini (0.4.1) tampaknya tidak memberikan solusi yang baik untuk ini. Saya belum punya waktu untuk mencoba ini, tetapi solusi yang mungkin untuk masalah ini adalah menggunakan sumber daya string
@string/provider_authority
, dan penggunaan yang di manifes:android:authority="@string/provider_authority"
. Anda kemudian memiliki ares/values/provider.xml
di folder res dari setiap jenis build yang harus menggantikan otoritas, dalam kasus Anda ini akan terjadisrc/debug/res
Saya telah mencari cara untuk membuat file xml dengan cepat, tetapi sekali lagi, tampaknya tidak ada kaitan yang bagus untuk itu di versi plugin saat ini. Saya akan merekomendasikan memasukkan permintaan fitur, saya dapat membayangkan lebih banyak orang akan mengalami masalah yang sama ini.
sumber
Jawaban dalam posting ini berhasil untuk saya.
http://www.kevinrschultz.com/blog/2014/03/23/using-android-content-providers-with-multiple-package-names/
Saya menggunakan 3 rasa berbeda jadi saya membuat 3 manifes dengan penyedia konten di setiap rasa seperti yang dikatakan kevinrschultz:
Manifes utama Anda tidak termasuk penyedia:
Dan manifes Anda dalam setiap rasa Anda termasuk penyedia.
Gratis:
Dibayar:
Lain:
sumber
Mengapa tidak menambahkan ini saja?
sumber
Solusi saya adalah menggunakan pengganti placeholder di
AndroidManifest.xml
. Ini juga menanganipackageNameSuffix
atribut sehingga Anda dapat memilikidebug
danrelease
juga build kustom lainnya di perangkat yang sama.Saya memilikinya di a
gist
jika Anda ingin melihat apakah itu berkembang nanti.Saya menemukan pendekatan yang lebih elegan daripada beberapa sumber daya dan pendekatan parsing XML.
sumber