Google Play mewajibkan APK terkompresi yang didownload pengguna tidak boleh lebih dari 100 MB. Bagi sebagian besar aplikasi, ini berarti ada banyak ruang untuk semua kode dan aset aplikasi. Namun, beberapa aplikasi memerlukan lebih banyak ruang untuk grafis high-fidelity, file media, atau aset besar lainnya. Sebelumnya, jika ukuran download terkompresi aplikasi Anda melebihi 100 MB, Anda harus meng-hosting dan mendownload sendiri resource tambahan saat pengguna membuka aplikasi. Meng-hosting dan menayangkan file tambahan dapat memerlukan biaya, dan pengalaman pengguna sering kali kurang ideal. Agar proses ini memudahkan Anda dan lebih menarik bagi pengguna, Google Play memungkinkan Anda melampirkan dua file ekspansi besar yang melengkapi APK.
Google Play akan meng-hosting file ekspansi untuk aplikasi Anda dan menayangkannya ke perangkat secara gratis. File ekspansi disimpan ke lokasi penyimpanan bersama perangkat tersebut ( kartu SD atau partisi USB yang dapat dipasang; juga dikenal sebagai penyimpanan "eksternal") tempat aplikasi dapat mengaksesnya. Pada sebagian besar perangkat, Google Play mendownload file ekspansi sekaligus mendownload APK, sehingga aplikasi Anda memiliki semua yang diperlukan saat pengguna membukanya untuk pertama kali. Namun, dalam beberapa kasus, aplikasi Anda harus mendownload file dari Google Play saat aplikasi dimulai.
Jika Anda tidak ingin menggunakan file ekspansi dan ukuran download terkompresi aplikasi Anda lebih besar dari 100 MB, sebaiknya upload aplikasi menggunakan Android App Bundle yang memungkinkan ukuran download terkompresi hingga 200 MB. Selain itu, karena penggunaan app bundle berarti menyerahkan pembuatan dan penandatanganan APK kepada Google Play, pengguna akan mendownload APK yang dioptimalkan hanya dengan kode dan resource yang diperlukan untuk menjalankan aplikasi Anda. Anda tidak perlu membuat, menandatangani, dan mengelola beberapa APK atau file ekspansi, dan pengguna akan mendapatkan hasil download yang lebih kecil dan lebih optimal.
Ringkasan
Setiap kali mengupload APK menggunakan Konsol Google Play, Anda memiliki opsi untuk menambahkan satu atau dua file ekspansi ke APK. Setiap file dapat berukuran hingga 2 GB dan dapat berupa format apa pun yang Anda pilih, tetapi sebaiknya gunakan file terkompresi untuk menghemat bandwidth selama proses download. Secara konsep, setiap file ekspansi memainkan peran yang berbeda:
- File ekspansi utama adalah file ekspansi utama untuk resource tambahan yang diperlukan oleh aplikasi Anda.
- File ekspansi patch bersifat opsional dan ditujukan untuk update kecil pada file ekspansi utama.
Meskipun Anda dapat menggunakan dua file perluasan dengan cara apa pun, sebaiknya file perluasan utama mengirimkan aset utama dan harus jarang diperbarui (jika memang diperbarui); file perluasan patch harus lebih kecil dan berfungsi sebagai “pembawa patch”, yang diperbarui dengan setiap rilis utama atau jika diperlukan.
Akan tetapi, meskipun update aplikasi hanya memerlukan file perluasan patch baru, Anda tetap harus
mengupload APK baru dengan versionCode
yang telah diupdate dalam manifes. (
Konsol Play tidak mengizinkan Anda mengupload file ekspansi ke APK yang sudah ada.)
Catatan: File ekspansi patch secara semantik sama dengan file ekspansi utama—Anda dapat menggunakan setiap file dengan cara apa pun yang Anda inginkan.
Format nama file
Setiap file ekspansi yang Anda upload dapat berupa format apa pun yang Anda pilih (ZIP, PDF, MP4, dll.). Anda juga dapat menggunakan alat JOBB untuk merangkum dan mengenkripsi kumpulan file resource dan patch berikutnya untuk kumpulan tersebut. Terlepas dari jenis file, Google Play menganggapnya sebagai blob biner opaque dan mengganti nama filenya menggunakan skema berikut:
[main|patch].<expansion-version>.<package-name>.obb
Ada tiga komponen untuk skema ini:
main
ataupatch
- Menentukan apakah file adalah file ekspansi utama atau patch. Hanya boleh ada satu file utama dan satu file patch untuk setiap APK.
<expansion-version>
- Ini adalah integer yang cocok dengan kode versi APK yang mana perluasan
pertama dikaitkan (sesuai dengan nilai
android:versionCode
aplikasi)."Pertama" ditekankan karena meskipun Konsol Play memungkinkan Anda untuk menggunakan kembali file ekspansi yang diupload dengan APK baru, nama file ekspansi tidak berubah—Konsol ini mempertahankan versi yang diterapkan saat Anda pertama kali mengupload file.
<package-name>
- Nama paket bergaya Java aplikasi Anda.
Misalnya, anggap versi APK Anda adalah 314159 dan nama paket Anda adalah com.example.app. Jika Anda mengupload file ekspansi utama, nama file akan diubah menjadi:
main.314159.com.example.app.obb
Lokasi penyimpanan
Saat Google Play mendownload file ekspansi ke perangkat, Google Play akan menyimpannya ke lokasi penyimpanan bersama sistem. Untuk memastikan perilaku yang benar, Anda tidak boleh menghapus, memindahkan, atau mengganti nama file ekspansi. Jika aplikasi Anda harus melakukan download dari Google Play, Anda harus menyimpan file tersebut ke lokasi yang sama persis.
Metode getObbDir()
akan menampilkan lokasi spesifik
untuk file ekspansi Anda dalam bentuk berikut:
<shared-storage>/Android/obb/<package-name>/
<shared-storage>
adalah jalur ke ruang penyimpanan bersama, yang tersedia darigetExternalStorageDirectory()
.<package-name>
adalah nama paket bergaya Java aplikasi, yang tersedia darigetPackageName()
.
Untuk setiap aplikasi, tidak pernah ada lebih dari dua file ekspansi dalam direktori ini.
Salah satunya adalah file ekspansi utama dan file lainnya adalah file ekspansi patch (jika perlu). Versi
sebelumnya akan ditimpa saat Anda mengupdate aplikasi dengan file ekspansi baru. Sejak Android
4.4 (API level 19), aplikasi dapat membaca file ekspansi OBB
tanpa izin
penyimpanan eksternal. Namun, beberapa implementasi Android 6.0 (API level 23) dan yang lebih baru masih memerlukan
izin, sehingga Anda harus menyatakan izin
READ_EXTERNAL_STORAGE
di manifes aplikasi dan meminta izin pada
runtime seperti berikut:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Untuk Android versi 6 dan yang lebih baru, izin penyimpanan eksternal perlu diminta pada runtime. Namun, beberapa implementasi Android tidak memerlukan izin untuk membaca file OBB. Cuplikan kode berikut menunjukkan cara memeriksa akses baca sebelum meminta izin penyimpanan eksternal:
Kotlin
val obb = File(obb_filename) var open_failed = false try { BufferedReader(FileReader(obb)).also { br -> ReadObbFile(br) } } catch (e: IOException) { open_failed = true } if (open_failed) { // request READ_EXTERNAL_STORAGE permission before reading OBB file ReadObbFileWithPermission() }
Java
File obb = new File(obb_filename); boolean open_failed = false; try { BufferedReader br = new BufferedReader(new FileReader(obb)); open_failed = false; ReadObbFile(br); } catch (IOException e) { open_failed = true; } if (open_failed) { // request READ_EXTERNAL_STORAGE permission before reading OBB file ReadObbFileWithPermission(); }
Jika Anda harus mengekstrak isi file ekspansi, jangan hapus
file ekspansi OBB
setelahnya dan jangan simpan data yang tidak diekstrak
dalam direktori yang sama. Anda harus menyimpan file yang belum diekstrak dalam direktori
yang ditentukan oleh getExternalFilesDir()
. Namun,
jika memungkinkan, sebaiknya gunakan format file ekspansi yang memungkinkan Anda membaca langsung dari
file, bukan mengharuskan Anda mengekstrak data. Misalnya, kami telah menyediakan project library
yang disebut Library Zip Ekspansi APK yang membaca data Anda langsung
dari file ZIP.
Perhatian: Tidak seperti file APK, file apa pun yang disimpan di penyimpanan bersama dapat dibaca oleh pengguna dan aplikasi lain.
Tips: Jika mengemas file media ke ZIP, Anda dapat menggunakan panggilan pemutaran
media pada file dengan kontrol offset dan durasi (misalnya MediaPlayer.setDataSource()
dan
SoundPool.load()
) tanpa
perlu mengekstrak ZIP Anda. Agar hal ini dapat bekerja, Anda tidak boleh melakukan kompresi tambahan pada
file media saat membuat paket ZIP. Misalnya, saat menggunakan alat zip
, Anda harus menggunakan opsi -n
untuk menentukan akhiran file yang seharusnya tidak
dikompresi:
zip -n .mp4;.ogg main_expansion media_files
Proses download
Biasanya, Google Play akan mendownload dan menyimpan file ekspansi sekaligus mendownload APK ke perangkat. Namun, dalam beberapa kasus, Google Play tidak dapat mendownload file ekspansi atau pengguna mungkin telah menghapus file ekspansi yang didownload sebelumnya. Untuk menangani situasi ini, aplikasi Anda harus dapat mendownload file itu sendiri saat aktivitas utama dimulai, menggunakan URL yang disediakan oleh Google Play.
Proses download dari tingkat tinggi akan terlihat seperti ini:
- Pengguna memilih untuk menginstal aplikasi dari Google Play.
- Jika Google Play dapat mendownload file ekspansi (yang berlaku untuk sebagian besar
perangkat), Google Play akan mendownloadnya bersama APK.
Jika Google Play tidak dapat mendownload file ekspansi, maka akan mendownload APK saja.
- Saat pengguna meluncurkan aplikasi, aplikasi Anda harus memeriksa apakah file ekspansi
sudah tersimpan di perangkat.
- Jika ya, aplikasi Anda siap digunakan.
- Jika tidak, aplikasi Anda harus mendownload file ekspansi melalui HTTP dari Google Play. Aplikasi Anda harus mengirim permintaan ke klien Google Play menggunakan layanan Pemberian Lisensi aplikasi Google Play, yang merespons dengan nama, ukuran file, dan URL untuk setiap file ekspansi. Dengan informasi ini, nantinya Anda dapat mendownload file dan menyimpannya ke lokasi penyimpanan yang tepat.
Perhatian: Penting bagi Anda untuk menyertakan kode yang diperlukan guna mendownload file perluasan dari Google Play jika file belum ada di perangkat saat aplikasi dimulai. Seperti yang telah dijelaskan di bagian berikut ini tentang Mendownload File Ekspansi, kami telah menyediakan library untuk Anda yang sangat memudahkan proses ini dan melakukan download dari layanan dengan jumlah kode minimal dari Anda.
Checklist pengembangan
Berikut adalah ringkasan tugas yang harus Anda lakukan untuk menggunakan file perluasan dengan aplikasi Anda:
- Pertama-tama tentukan apakah ukuran download terkompresi aplikasi Anda harus lebih dari 100 MB. Ruang penyimpanan sangat berharga dan Anda harus menjaga ukuran download total sekecil mungkin. Jika aplikasi Anda menggunakan lebih dari 100 MB untuk memberikan beberapa versi aset visual untuk beberapa kepadatan layar, pertimbangkan untuk memublikasikan beberapa APK di mana setiap APK hanya berisi aset yang diperlukan untuk layar yang ditargetkannya. Untuk hasil terbaik saat memublikasikan ke Google Play, upload Android App Bundle, yang mencakup semua kode dan resource terkompilasi aplikasi, tetapi serahkan pembuatan dan penandatanganan APK ke Google Play.
- Tentukan resource aplikasi mana yang akan dipisah dari APK dan paketkan dalam
file untuk digunakan sebagai file ekspansi utama.
Biasanya, Anda seharusnya hanya menggunakan file ekspansi patch kedua saat melakukan pembaruan pada file ekspansi utama. Namun, jika resource Anda melebihi batas 2 GB untuk file ekspansi utama, Anda dapat menggunakan file patch untuk sisa aset Anda.
- Kembangkan aplikasi Anda sedemikian rupa menggunakan resource dari file ekspansi di
lokasi penyimpanan bersama perangkat.
Ingat bahwa Anda tidak boleh menghapus, memindahkan, atau mengganti nama file ekspansi.
Jika aplikasi Anda tidak menuntut format tertentu, sebaiknya buat file ZIP untuk file ekspansi, lalu membacanya menggunakan Library Zip Ekspansi APK.
- Tambahkan logika ke aktivitas utama aplikasi Anda yang memeriksa apakah file perluasan
berada di perangkat saat dimulai. Jika file tidak ada di perangkat, gunakan layanan Pemberian Lisensi aplikasi Google Play untuk meminta URL
untuk file ekspansi, lalu download dan simpan file tersebut.
Untuk mengurangi jumlah kode yang harus Anda tulis dan memastikan pengalaman pengguna yang baik selama proses download, sebaiknya gunakan Library Downloader untuk mengimplementasikan perilaku download Anda.
Jika Anda membuat layanan download sendiri dan bukan menggunakan library, perhatikan bahwa Anda tidak boleh mengubah nama file ekspansi dan harus menyimpannya ke lokasi penyimpanan yang tepat.
Setelah Anda menyelesaikan pengembangan aplikasi, ikuti panduan untuk Menguji File Ekspansi Anda.
Aturan dan Batasan
Menambahkan file ekspansi APK adalah fitur yang tersedia saat Anda mengupload aplikasi menggunakan Konsol Play. Saat mengupload aplikasi untuk pertama kali atau mengupdate aplikasi yang menggunakan file ekspansi, Anda harus mengetahui aturan dan batasan berikut:
- Setiap file ekspansi tidak boleh lebih dari 2 GB.
- Untuk mendownload file ekspansi dari Google Play, pengguna harus mendapatkan aplikasi Anda dari Google Play. Google Play tidak akan memberikan URL untuk file ekspansi jika aplikasi diinstal dengan cara lain.
- Saat melakukan download dari dalam aplikasi, URL yang disediakan Google Play untuk setiap file bersifat unik untuk setiap download dan akan segera berakhir setelah diberikan ke aplikasi Anda.
- Jika mengupdate aplikasi dengan APK baru atau mengupload beberapa APK untuk aplikasi yang sama, Anda dapat memilih file perluasan yang telah diupload untuk APK sebelumnya. Nama file perluasan tidak berubah—hal ini mempertahankan versi yang diterima oleh APK ke file mana pun yang pertama kali dikaitkan.
- Jika menggunakan file ekspansi yang digabungkan dengan beberapa APK untuk
menyediakan file ekspansi yang berbeda untuk perangkat yang berbeda, Anda tetap harus mengupload APK terpisah
untuk setiap perangkat agar dapat memberikan nilai
versionCode
unik dan mendeklarasikan filter yang berbeda untuk setiap APK. - Anda tidak dapat melakukan update pada aplikasi hanya dengan mengubah file ekspansi
—Anda harus mengupload APK baru untuk mengupdate aplikasi. Jika perubahan hanya
terkait dengan aset dalam file ekspansi, Anda dapat mengupdate APK hanya dengan mengubah
versionCode
(dan mungkin jugaversionName
. - Jangan menyimpan data lain ke direktori
obb/
. Jika Anda harus mengekstrak beberapa data, simpan data tersebut ke lokasi yang ditentukan olehgetExternalFilesDir()
. - Jangan menghapus atau mengganti nama file ekspansi
.obb
(kecuali jika Anda melakukan update). Jika melakukannya, Google Play (atau aplikasi Anda) akan berulang kali mendownload file ekspansi. - Saat mengupdate file ekspansi secara manual, Anda harus menghapus file ekspansi sebelumnya.
Mendownload File Perluasan
Pada sebagian besar situasi, Google Play akan mendownload dan menyimpan file perluasan ke perangkat sekaligus menginstal atau mengupdate APK. Dengan cara ini, file ekspansi akan tersedia saat aplikasi Anda diluncurkan untuk pertama kalinya. Namun, dalam beberapa kasus, aplikasi Anda harus mendownload file ekspansi itu sendiri dengan memintanya dari URL yang disediakan untuk Anda sebagai respons dari layanan Pemberian Lisensi aplikasi Google Play.
Logika dasar yang diperlukan untuk mendownload file perluasan adalah sebagai berikut:
- Saat aplikasi Anda dimulai, cari file perluasan pada lokasi penyimpanan bersama (dalam
direktori
Android/obb/<package-name>/
).- Jika sudah terdapat file ekspansi, berarti Anda sudah siap dan aplikasi dapat dilanjutkan.
- Jika tidak terdapat file perluasan:
- Lakukan permintaan menggunakan Pemberian Lisensi aplikasi Google Play untuk mendapatkan nama, ukuran, dan URL file perluasan aplikasi Anda.
- Gunakan URL yang disediakan oleh Google Play untuk mendownload dan menyimpan
file perluasan. Anda harus menyimpan file tersebut ke lokasi penyimpanan bersama
(
Android/obb/<package-name>/
) dan menggunakan nama file persis yang diberikan berdasarkan respons Google Play.Catatan: URL yang disediakan oleh Google Play untuk file perluasan bersifat unik untuk setiap download dan akan segera berakhir setelah diberikan ke aplikasi Anda.
Jika aplikasi Anda gratis (bukan aplikasi berbayar), Anda mungkin belum pernah menggunakan layanan Pemberian Lisensi aplikasi. Layanan ini utamanya dirancang untuk membantu Anda menerapkan kebijakan pemberian lisensi untuk aplikasi Anda dan memastikan bahwa pengguna berhak menggunakan aplikasi Anda (pengguna berhak membelinya di Google Play). Untuk memfasilitasi fungsionalitas file ekspansi, layanan pemberian lisensi telah ditingkatkan untuk memberikan respons terhadap aplikasi Anda yang menyertakan URL file ekspansi aplikasi yang dihosting di Google Play. Jadi, meskipun aplikasi Anda gratis untuk pengguna, Anda harus menyertakan Library Verifikasi Lisensi (LVL) untuk menggunakan file ekspansi APK. Tentu saja, jika aplikasi Anda gratis, Anda tidak perlu menerapkan verifikasi lisensi—cukup gunakan library untuk melakukan permintaan yang menampilkan URL file ekspansi Anda.
Catatan: Baik aplikasi Anda gratis atau tidak, Google Play menampilkan URL file ekspansi hanya jika pengguna memperoleh aplikasi Anda dari Google Play.
Selain LVL, Anda memerlukan sekumpulan kode yang mendownload file ekspansi melalui koneksi HTTP dan menyimpannya ke lokasi yang tepat pada penyimpanan bersama perangkat. Saat Anda menerapkan prosedur ini ke aplikasi, ada beberapa masalah yang harus dipertimbangkan:
- Perangkat mungkin tidak memiliki cukup ruang untuk file ekspansi, jadi Anda harus memeriksa sebelum memulai download dan memberi tahu pengguna jika tidak tersedia cukup ruang.
- Proses download file harus dilakukan di layanan latar belakang untuk menghindari pemblokiran interaksi pengguna dan memungkinkan pengguna keluar dari aplikasi Anda saat proses download selesai.
- Berbagai macam error mungkin terjadi selama permintaan dan proses download yang harus Anda tangani dengan baik.
- Konektivitas jaringan dapat berubah selama download, sehingga Anda harus menangani perubahan tersebut dan jika terganggu, lanjutkan proses download tersebut jika memungkinkan.
- Meskipun proses download terjadi di latar belakang, Anda harus memberikan notifikasi yang menunjukkan progres download, memberi tahu pengguna setelah selesai, dan mengarahkan pengguna kembali ke aplikasi Anda saat dipilih.
Guna menyederhanakan pekerjaan ini untuk Anda, kami telah membuat Library Downloader, yang meminta URL file ekspansi melalui layanan pemberian lisensi, mendownload file ekspansi, melakukan semua tugas yang tercantum di atas, dan bahkan mengizinkan aktivitas untuk menjeda dan melanjutkan download. Dengan menambahkan Library Downloader dan beberapa rangkaian kode ke aplikasi Anda, hampir semua pekerjaan untuk mendownload file ekspansi sudah dikodekan untuk Anda. Oleh karena itu, demi memberikan pengalaman pengguna terbaik dengan upaya minimal atas nama Anda, sebaiknya gunakan Library Downloader untuk mendownload file ekspansi Anda. Informasi di bagian berikut menjelaskan cara mengintegrasikan library ke aplikasi Anda.
Jika ingin mengembangkan solusi Anda sendiri untuk mendownload file ekspansi menggunakan URL Google
Play, Anda harus mengikuti dokumentasi Pemberian Lisensi
aplikasi untuk melakukan permintaan lisensi, lalu mengambil nama file ekspansi,
ukuran, dan URL dari tambahan respons. Sebaiknya gunakan class APKExpansionPolicy
(disertakan dalam Library Verifikasi Lisensi) sebagai kebijakan pemberian
lisensi, yang mencatat nama file ekspansi, ukuran, dan URL dari layanan pemberian lisensi.
Tentang Library Downloader
Agar dapat menggunakan file ekspansi APK dengan aplikasi Anda dan memberikan pengalaman pengguna terbaik dengan upaya minimal atas nama Anda, sebaiknya gunakan Library Downloader yang disertakan dalam paket Library Perluasan APK Google Play. Library ini mendownload file ekspansi di layanan latar belakang, menampilkan notifikasi kepada pengguna beserta status downloadnya, menangani hilangnya konektivitas jaringan, melanjutkan download jika memungkinkan, dan banyak lagi.
Untuk menerapkan download file ekspansi menggunakan Library Downloader, yang perlu Anda lakukan adalah:
- Luaskan subclass
Service
khusus dan subclassBroadcastReceiver
yang masing-masing hanya memerlukan beberapa baris kode dari Anda. - Tambahkan beberapa logika ke aktivitas utama yang memeriksa apakah file ekspansi telah didownload dan, jika tidak, akan meminta proses download dan menampilkan UI progres.
- Implementasikan antarmuka callback dengan beberapa metode dalam aktivitas utama Anda yang menerima update terkait progres download.
Bagian berikut menjelaskan cara menyiapkan aplikasi Anda menggunakan Library Downloader.
Bersiap untuk menggunakan Library Downloader
Agar dapat menggunakan Library Downloader, Anda harus mendownload dua paket dari SDK Manager dan menambahkan library yang sesuai ke aplikasi Anda.
Pertama, buka Android SDK Manager (Tools > SDK Manager), dan di bagian Appearance & Behavior > System Settings > Android SDK, pilih tab SDK Tools untuk memilih dan mendownload:
- Paket Library Pemberian Lisensi Google Play
- Paket Library Perluasan APK Google Play
Buat modul library baru untuk Library Verifikasi Lisensi dan Library Downloader. Untuk setiap library:
- Pilih File > New > New Module.
- Di jendela Create New Module, pilih Android Library, lalu pilih Next.
- Tentukan nama aplikasi/Library seperti "Library Pemberian Lisensi Google Play" dan "Library Downloader Google Play", pilih Minimum SDK level, lalu pilih Finish.
- Pilih File > Project Structure.
- Pilih tab Properties dan di Library
Repository, masukkan library dari direktori
<sdk>/extras/google/
(play_licensing/
untuk Library Verifikasi Lisensi atauplay_apk_expansion/downloader_library/
untuk Library Downloader). - Pilih OK untuk membuat modul baru.
Catatan: Library Downloader bergantung pada Library Verifikasi Lisensi. Pastikan Anda menambahkan Library Verifikasi Lisensi ke properti project Library Downloader.
Atau, dari command line, update project Anda untuk menyertakan library:
- Ubah direktori ke direktori
<sdk>/tools/
. - Jalankan
android update project
dengan opsi--library
untuk menambahkan LVL dan Library Downloader ke project Anda. Contoh:android update project --path ~/Android/MyApp \ --library ~/android_sdk/extras/google/market_licensing \ --library ~/android_sdk/extras/google/market_apk_expansion/downloader_library
Dengan menambahkan Library Verifikasi Lisensi dan Library Downloader ke aplikasi, Anda dapat dengan cepat mengintegrasikan kemampuan untuk mendownload file ekspansi dari Google Play. Format yang Anda pilih untuk file ekspansi dan cara Anda membacanya dari penyimpanan bersama merupakan penerapan terpisah yang harus Anda pertimbangkan berdasarkan kebutuhan aplikasi Anda.
Tips: Paket Ekspansi Apk menyertakan contoh aplikasi yang menunjukkan cara menggunakan Library Downloader dalam aplikasi. Contoh aplikasi tersebut menggunakan library ketiga yang tersedia di paket Ekspansi Apk yang disebut Library Zip Ekspansi APK. Jika Anda berencana menggunakan file ZIP untuk file ekspansi, sebaiknya tambahkan juga Library Zip Perluasan APK ke aplikasi Anda. Untuk informasi selengkapnya, lihat bagian di bawah ini tentang Menggunakan Library Zip Perluasan APK.
Mendeklarasikan izin pengguna
Untuk mendownload file ekspansi, Library Downloader memerlukan beberapa izin yang harus Anda deklarasikan dalam file manifes aplikasi.
<manifest ...> <!-- Required to access Google Play Licensing --> <uses-permission android:name="com.android.vending.CHECK_LICENSE" /> <!-- Required to download files from Google Play --> <uses-permission android:name="android.permission.INTERNET" /> <!-- Required to keep CPU alive while downloading files (NOT to keep screen awake) --> <uses-permission android:name="android.permission.WAKE_LOCK" /> <!-- Required to poll the state of the network connection and respond to changes --> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- Required to check whether Wi-Fi is enabled --> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <!-- Required to read and write the expansion files on shared storage --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> ... </manifest>
Catatan: Secara default, Library Downloader memerlukan API level 4, tetapi Library Zip Perluasan APK memerlukan API level 5.
Mengimplementasikan layanan downloader
Agar dapat mendownload di latar belakang, Library Downloader menyediakan
subclass Service
-nya sendiri bernama DownloaderService
yang harus Anda perluas. Selain
mendownload file ekspansi untuk Anda, DownloaderService
juga:
- Mendaftarkan
BroadcastReceiver
yang memproses perubahan pada konektivitas jaringan perangkat (siaranCONNECTIVITY_ACTION
) untuk menjeda proses download jika diperlukan (misalnya karena kehilangan konektivitas) dan melanjutkan proses download jika memungkinkan (saat mendapatkan konektivitas). - Menjadwalkan alarm
RTC_WAKEUP
untuk mencoba kembali proses download apabila layanan dihentikan. - Membuat
Notification
kustom yang menampilkan progres download dan setiap perubahan error atau status. - Mengizinkan aplikasi secara manual menjeda dan melanjutkan proses download.
- Memverifikasi bahwa penyimpanan bersama sudah terpasang dan tersedia, bahwa file yang diperlukan belum tersedia, dan bahwa ruang penyimpanan yang cukup sudah tersedia, semuanya sebelum mendownload file ekspansi. Lalu memberi tahu pengguna jika salah satu dari pernyataan tersebut tidak benar.
Yang perlu Anda lakukan adalah membuat class di aplikasi Anda yang memperluas class DownloaderService
dan mengganti tiga metode untuk memberikan detail aplikasi tertentu:
getPublicKey()
- Metode ini harus menampilkan string yang merupakan kunci publik RSA berenkode Base64 untuk akun penerbit Anda, yang tersedia dari halaman profil di Konsol Play (lihat Menyiapkan Pemberian Lisensi).
getSALT()
- Metode ini harus menampilkan array byte acak yang digunakan
Policy
pemberian lisensi untuk membuatObfuscator
. Salt memastikan bahwa fileSharedPreferences
obfuscation tempat data lisensi Anda disimpan akan unik dan tidak dapat ditemukan. getAlarmReceiverClassName()
- Metode ini harus menampilkan nama class dari
BroadcastReceiver
di aplikasi Anda yang akan menerima alarm yang menunjukkan bahwa proses download harus dimulai ulang (yang mungkin terjadi jika layanan downloader tiba-tiba berhenti).
Misalnya, berikut adalah implementasi lengkap dari DownloaderService
:
Kotlin
// You must use the public key belonging to your publisher account const val BASE64_PUBLIC_KEY = "YourLVLKey" // You should also modify this salt val SALT = byteArrayOf( 1, 42, -12, -1, 54, 98, -100, -12, 43, 2, -8, -4, 9, 5, -106, -107, -33, 45, -1, 84 ) class SampleDownloaderService : DownloaderService() { override fun getPublicKey(): String = BASE64_PUBLIC_KEY override fun getSALT(): ByteArray = SALT override fun getAlarmReceiverClassName(): String = SampleAlarmReceiver::class.java.name }
Java
public class SampleDownloaderService extends DownloaderService { // You must use the public key belonging to your publisher account public static final String BASE64_PUBLIC_KEY = "YourLVLKey"; // You should also modify this salt public static final byte[] SALT = new byte[] { 1, 42, -12, -1, 54, 98, -100, -12, 43, 2, -8, -4, 9, 5, -106, -107, -33, 45, -1, 84 }; @Override public String getPublicKey() { return BASE64_PUBLIC_KEY; } @Override public byte[] getSALT() { return SALT; } @Override public String getAlarmReceiverClassName() { return SampleAlarmReceiver.class.getName(); } }
Pemberitahuan: Anda harus mengupdate nilai
BASE64_PUBLIC_KEY
menjadi kunci publik yang dimiliki oleh akun penerbit Anda. Anda dapat menemukan kuncinya di Konsol
Developer di bagian informasi profil. Hal ini diperlukan bahkan saat menguji
proses download Anda.
Pastikan untuk mendeklarasikan layanan dalam file manifes:
<app ...> <service android:name=".SampleDownloaderService" /> ... </app>
Mengimplementasikan penerima alarm
Untuk memantau progres download file dan memulai ulang proses download jika diperlukan, file
DownloaderService
menjadwalkan alarm RTC_WAKEUP
yang
mengirim Intent
ke BroadcastReceiver
di aplikasi
Anda. Anda harus menentukan BroadcastReceiver
untuk memanggil API
dari Library Downloader yang memeriksa status download dan memulai ulang
prosesnya jika diperlukan.
Cukup ganti metode onReceive()
untuk memanggil DownloaderClientMarshaller.startDownloadServiceIfRequired()
.
Contoh:
Kotlin
class SampleAlarmReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { try { DownloaderClientMarshaller.startDownloadServiceIfRequired( context, intent, SampleDownloaderService::class.java ) } catch (e: PackageManager.NameNotFoundException) { e.printStackTrace() } } }
Java
public class SampleAlarmReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { try { DownloaderClientMarshaller.startDownloadServiceIfRequired(context, intent, SampleDownloaderService.class); } catch (NameNotFoundException e) { e.printStackTrace(); } } }
Perhatikan bahwa ini adalah class yang harus Anda tampilkan namanya
dalam metode getAlarmReceiverClassName()
layanan Anda (lihat bagian sebelumnya).
Pastikan untuk mendeklarasikan penerima dalam file manifes Anda:
<app ...> <receiver android:name=".SampleAlarmReceiver" /> ... </app>
Memulai download
Aktivitas utama di aplikasi Anda (yang dimulai oleh ikon peluncur) bertanggung jawab untuk memverifikasi apakah file ekspansi sudah ada di perangkat dan memulai download jika belum ada.
Memulai download menggunakan Library Downloader memerlukan prosedur berikut:
- Periksa apakah file telah didownload.
Library Downloader berisi beberapa API di class
Helper
untuk membantu proses ini:getExpansionAPKFileName(Context, c, boolean mainFile, int versionCode)
doesFileExist(Context c, String fileName, long fileSize)
Misalnya, contoh aplikasi yang disediakan dalam paket Perluasan Apk memanggil metode berikut dalam metode
onCreate()
aktivitas untuk memeriksa apakah file ekspansi sudah ada di perangkat:Kotlin
fun expansionFilesDelivered(): Boolean { xAPKS.forEach { xf -> Helpers.getExpansionAPKFileName(this, xf.isBase, xf.fileVersion).also { fileName -> if (!Helpers.doesFileExist(this, fileName, xf.fileSize, false)) return false } } return true }
Java
boolean expansionFilesDelivered() { for (XAPKFile xf : xAPKS) { String fileName = Helpers.getExpansionAPKFileName(this, xf.isBase, xf.fileVersion); if (!Helpers.doesFileExist(this, fileName, xf.fileSize, false)) return false; } return true; }
Dalam hal ini, setiap objek
XAPKFile
menyimpan ukuran file dan nomor versi file ekspansi dan boolean yang diketahui, apakah merupakan file ekspansi utama atau tidak. (Lihat contoh classSampleDownloaderActivity
aplikasi untuk detailnya.)Jika metode ini menampilkan false, maka aplikasi harus memulai proses download.
- Mulai download dengan memanggil metode statis
DownloaderClientMarshaller.startDownloadServiceIfRequired(Context c, PendingIntent notificationClient, Class<?> serviceClass)
.Metode ini menggunakan parameter berikut:
context
:Context
aplikasi Anda.notificationClient
: SebuahPendingIntent
untuk memulai aktivitas utama. Parameter ini digunakan dalamNotification
yang dibuatDownloaderService
untuk menampilkan progres download. Saat pengguna memilih notifikasi, sistem akan memanggilPendingIntent
yang Anda berikan di sini dan akan membuka aktivitas yang menampilkan progres download (biasanya aktivitas yang sama yang memulai download).serviceClass
: ObjekClass
untuk penerapanDownloaderService
, diperlukan untuk memulai layanan dan memulai download jika diperlukan.
Metode ini menampilkan integer yang menunjukkan apakah download diperlukan atau tidak. Nilai yang dimungkinkan adalah:
NO_DOWNLOAD_REQUIRED
: Ditampilkan jika file sudah ada atau proses download sedang berlangsung.LVL_CHECK_REQUIRED
: Ditampilkan jika verifikasi lisensi diperlukan untuk mendapatkan URL file ekspansi.DOWNLOAD_REQUIRED
: Ditampilkan jika URL file ekspansi sudah diketahui, tetapi belum didownload.
Perilaku untuk
LVL_CHECK_REQUIRED
danDOWNLOAD_REQUIRED
pada dasarnya sama dan biasanya Anda tidak perlu mengkhawatirkannya. Dalam aktivitas utama Anda yang memanggilstartDownloadServiceIfRequired()
, cukup periksa apakah respons tersebut adalahNO_DOWNLOAD_REQUIRED
. Jika respons merupakan hal selainNO_DOWNLOAD_REQUIRED
, Library Downloader akan memulai download dan Anda harus mengupdate UI aktivitas untuk menampilkan progres download (lihat langkah berikutnya). Jika respons merupakanNO_DOWNLOAD_REQUIRED
, maka file tersebut telah tersedia dan aplikasi Anda dapat dimulai.Contoh:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Check if expansion files are available before going any further if (!expansionFilesDelivered()) { val pendingIntent = // Build an Intent to start this activity from the Notification Intent(this, MainActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP }.let { notifierIntent -> PendingIntent.getActivity( this, 0, notifierIntent, PendingIntent.FLAG_UPDATE_CURRENT ) } // Start the download service (if required) val startResult: Int = DownloaderClientMarshaller.startDownloadServiceIfRequired( this, pendingIntent, SampleDownloaderService::class.java ) // If download has started, initialize this activity to show // download progress if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) { // This is where you do set up to display the download // progress (next step) ... return } // If the download wasn't necessary, fall through to start the app } startApp() // Expansion files are available, start the app }
Java
@Override public void onCreate(Bundle savedInstanceState) { // Check if expansion files are available before going any further if (!expansionFilesDelivered()) { // Build an Intent to start this activity from the Notification Intent notifierIntent = new Intent(this, MainActivity.getClass()); notifierIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); ... PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notifierIntent, PendingIntent.FLAG_UPDATE_CURRENT); // Start the download service (if required) int startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired(this, pendingIntent, SampleDownloaderService.class); // If download has started, initialize this activity to show // download progress if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) { // This is where you do set up to display the download // progress (next step) ... return; } // If the download wasn't necessary, fall through to start the app } startApp(); // Expansion files are available, start the app }
- Saat
startDownloadServiceIfRequired()
menampilkan hal selainNO_DOWNLOAD_REQUIRED
, buat instanceIStub
dengan memanggilDownloaderClientMarshaller.CreateStub(IDownloaderClient client, Class<?> downloaderService)
.IStub
memberikan binding antara aktivitas Anda dengan layanan downloader, sehingga aktivitas Anda menerima callback terkait progres download.Agar dapat membuat instance
IStub
dengan memanggilCreateStub()
, Anda harus meneruskan penerapan antarmukaIDownloaderClient
dan implementasiDownloaderService
. Bagian berikutnya tentang Menerima progres download membahas tentang antarmukaIDownloaderClient
, yang biasanya harus Anda implementasikan di classActivity
yang dapat memungkinkan Anda mengupdate UI aktivitas saat status download berubah.Sebaiknya panggil
CreateStub()
untuk membuat instanceIStub
selama metodeonCreate()
aktivitas Anda, setelahstartDownloadServiceIfRequired()
memulai download.Misalnya, dalam contoh kode sebelumnya untuk
onCreate()
, Anda dapat merespons hasilstartDownloadServiceIfRequired()
seperti ini:Kotlin
// Start the download service (if required) val startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired( this@MainActivity, pendingIntent, SampleDownloaderService::class.java ) // If download has started, initialize activity to show progress if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) { // Instantiate a member instance of IStub downloaderClientStub = DownloaderClientMarshaller.CreateStub(this, SampleDownloaderService::class.java) // Inflate layout that shows download progress setContentView(R.layout.downloader_ui) return }
Java
// Start the download service (if required) int startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired(this, pendingIntent, SampleDownloaderService.class); // If download has started, initialize activity to show progress if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) { // Instantiate a member instance of IStub downloaderClientStub = DownloaderClientMarshaller.CreateStub(this, SampleDownloaderService.class); // Inflate layout that shows download progress setContentView(R.layout.downloader_ui); return; }
Setelah metode
onCreate()
ditampilkan, aktivitas Anda menerima panggilan keonResume()
, di mana Anda nantinya akan memanggilconnect()
diIStub
, lalu meneruskannya ke aplikasi AndaContext
. Sebaliknya, Anda harus memanggildisconnect()
dalam callbackonStop()
aktivitas Anda.Kotlin
override fun onResume() { downloaderClientStub?.connect(this) super.onResume() } override fun onStop() { downloaderClientStub?.disconnect(this) super.onStop() }
Java
@Override protected void onResume() { if (null != downloaderClientStub) { downloaderClientStub.connect(this); } super.onResume(); } @Override protected void onStop() { if (null != downloaderClientStub) { downloaderClientStub.disconnect(this); } super.onStop(); }
Dengan memanggil
connect()
diIStub
, aktivitas Anda akan diikat keDownloaderService
, memungkinkan aktivitas menerima callback terkait perubahan status download melalui antarmukaIDownloaderClient
.
Menerima progres download
Untuk menerima update terkait progres download dan untuk berinteraksi dengan DownloaderService
, Anda harus mengimplementasikan antarmuka IDownloaderClient
Library Downloader.
Biasanya, aktivitas yang Anda gunakan untuk memulai download harus mengimplementasikan antarmuka ini untuk
menampilkan progres download dan mengirim permintaan ke layanan.
Metode antarmuka yang diperlukan untuk IDownloaderClient
adalah:
onServiceConnected(Messenger m)
- Setelah membuat instance
IStub
dalam aktivitas, Anda akan menerima panggilan ke metode ini, yang akan meneruskan objekMessenger
yang terhubung dengan instanceDownloaderService
Anda. Untuk mengirim permintaan ke layanan, seperti menjeda dan melanjutkan download, Anda harus memanggilDownloaderServiceMarshaller.CreateProxy()
untuk menerima antarmukaIDownloaderService
yang terhubung ke layanan.Implementasi yang direkomendasikan akan terlihat seperti berikut:
Kotlin
private var remoteService: IDownloaderService? = null ... override fun onServiceConnected(m: Messenger) { remoteService = DownloaderServiceMarshaller.CreateProxy(m).apply { downloaderClientStub?.messenger?.also { messenger -> onClientUpdated(messenger) } } }
Java
private IDownloaderService remoteService; ... @Override public void onServiceConnected(Messenger m) { remoteService = DownloaderServiceMarshaller.CreateProxy(m); remoteService.onClientUpdated(downloaderClientStub.getMessenger()); }
Dengan objek
IDownloaderService
yang diinisialisasi, Anda dapat mengirim perintah ke layanan downloader, seperti menjeda dan melanjutkan download (requestPauseDownload()
danrequestContinueDownload()
). onDownloadStateChanged(int newState)
- Layanan download akan memanggilnya saat terjadi perubahan status download, seperti
download dimulai atau selesai.
Nilai
newState
akan menjadi salah satu dari beberapa kemungkinan nilai yang ditentukan oleh salah satu konstantaSTATE_*
classIDownloaderClient
.Untuk memberikan pesan yang berguna kepada pengguna, Anda dapat meminta string yang sesuai untuk setiap status dengan memanggil
Helpers.getDownloaderStringResourceIDFromState()
. Tindakan ini akan menampilkan ID resource untuk salah satu string yang dipaketkan dengan Library Downloader. Misalnya, string "Download dijeda karena Anda roaming" akan sesuai denganSTATE_PAUSED_ROAMING
. onDownloadProgress(DownloadProgressInfo progress)
- Layanan download memanggilnya untuk mengirimkan objek
DownloadProgressInfo
, yang menjelaskan berbagai informasi tentang progres download, meliputi perkiraan sisa waktu, kecepatan saat ini, progres keseluruhan, dan total sehingga Anda dapat mengupdate UI progres download.
Tips: Untuk contoh callback yang mengupdate UI progres
download, lihat SampleDownloaderActivity
di aplikasi contoh yang disediakan dengan
paket Perluasan APK.
Beberapa metode publik untuk antarmuka IDownloaderService
yang mungkin berguna bagi Anda di antaranya:
requestPauseDownload()
- Menjeda download.
requestContinueDownload()
- Melanjutkan download yang dijeda.
setDownloadFlags(int flags)
- Menetapkan preferensi pengguna untuk jenis jaringan yang diperbolehkan mendownload file. Implementasi
saat ini mendukung satu flag,
FLAGS_DOWNLOAD_OVER_CELLULAR
, tetapi Anda dapat menambahkan yang lain. Secara default, flag ini tidak diaktifkan, sehingga pengguna harus menggunakan Wi-Fi untuk mendownload file ekspansi. Sebaiknya berikan preferensi pengguna untuk mengaktifkan download melalui jaringan seluler. Dalam hal ini, Anda dapat memanggil:Kotlin
remoteService = DownloaderServiceMarshaller.CreateProxy(m).apply { ... setDownloadFlags(IDownloaderService.FLAGS_DOWNLOAD_OVER_CELLULAR) }
Java
remoteService .setDownloadFlags(IDownloaderService.FLAGS_DOWNLOAD_OVER_CELLULAR);
Menggunakan APKExpansionPolicy
Jika memutuskan untuk membuat layanan downloader sendiri daripada menggunakan Library Downloader
Google Play, Anda tetap harus menggunakan APKExpansionPolicy
yang disediakan dalam Library Verifikasi Lisensi. Class APKExpansionPolicy
hampir identik dengan ServerManagedPolicy
(tersedia dalam
Library Verifikasi Lisensi Google Play) tetapi menyertakan penanganan tambahan untuk tambahan respons file
ekspansi APK.
Catatan: Jika Anda menggunakan Library Downloader seperti yang dibahas di bagian sebelumnya,
library tersebut akan menjalankan semua interaksi dengan APKExpansionPolicy
, sehingga Anda tidak perlu menggunakan
class ini langsung.
Class tersebut menyertakan metode untuk membantu Anda mendapatkan informasi yang diperlukan terkait file perluasan yang tersedia:
getExpansionURLCount()
getExpansionURL(int index)
getExpansionFileName(int index)
getExpansionFileSize(int index)
Untuk informasi selengkapnya tentang cara menggunakan APKExpansionPolicy
saat Anda tidak
menggunakan Library Downloader, lihat dokumentasi untuk Menambahkan Lisensi ke Aplikasi Anda,
yang menjelaskan cara mengimplementasikan kebijakan lisensi seperti ini.
Membaca File Ekspansi
Setelah file ekspansi APK disimpan di perangkat, cara Anda membaca file
bergantung pada jenis file yang digunakan. Seperti yang dibahas dalam ringkasan,
file ekspansi dapat berupa jenis file apa pun yang Anda
inginkan, tetapi akan diganti namanya menggunakan format nama file tertentu dan disimpan ke
<shared-storage>/Android/obb/<package-name>/
.
Terlepas dari cara membaca file, Anda harus selalu memeriksa dulu apakah penyimpanan eksternal tersedia untuk dibaca atau tidak. Ada kemungkinan bahwa pengguna memiliki penyimpanan yang dipasang ke komputer melalui USB atau sebenarnya telah mengeluarkan kartu SD.
Catatan: Saat aplikasi dimulai, Anda harus selalu memeriksa apakah
ruang penyimpanan eksternal tersedia dan dapat dibaca dengan memanggil getExternalStorageState()
. Ini akan menampilkan salah satu dari beberapa kemungkinan string
yang mewakili status penyimpanan eksternal. Agar dapat dibaca oleh aplikasi
Anda, nilai yang ditampilkan harus MEDIA_MOUNTED
.
Mendapatkan nama file
Seperti yang dijelaskan dalam ringkasan, file ekspansi APK disimpan menggunakan format nama file tertentu:
[main|patch].<expansion-version>.<package-name>.obb
Untuk mendapatkan lokasi dan nama file ekspansi, Anda harus menggunakan
metode getExternalStorageDirectory()
dan getPackageName()
untuk membuat jalur ke file Anda.
Berikut adalah metode yang dapat Anda gunakan di aplikasi untuk mendapatkan array yang berisi jalur lengkap ke kedua file ekspansi Anda:
Kotlin
fun getAPKExpansionFiles(ctx: Context, mainVersion: Int, patchVersion: Int): Array<String> { val packageName = ctx.packageName val ret = mutableListOf<String>() if (Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED) { // Build the full path to the app's expansion files val root = Environment.getExternalStorageDirectory() val expPath = File(root.toString() + EXP_PATH + packageName) // Check that expansion file path exists if (expPath.exists()) { if (mainVersion > 0) { val strMainPath = "$expPath${File.separator}main.$mainVersion.$packageName.obb" val main = File(strMainPath) if (main.isFile) { ret += strMainPath } } if (patchVersion > 0) { val strPatchPath = "$expPath${File.separator}patch.$mainVersion.$packageName.obb" val main = File(strPatchPath) if (main.isFile) { ret += strPatchPath } } } } return ret.toTypedArray() }
Java
// The shared path to all app expansion files private final static String EXP_PATH = "/Android/obb/"; static String[] getAPKExpansionFiles(Context ctx, int mainVersion, int patchVersion) { String packageName = ctx.getPackageName(); Vector<String> ret = new Vector<String>(); if (Environment.getExternalStorageState() .equals(Environment.MEDIA_MOUNTED)) { // Build the full path to the app's expansion files File root = Environment.getExternalStorageDirectory(); File expPath = new File(root.toString() + EXP_PATH + packageName); // Check that expansion file path exists if (expPath.exists()) { if ( mainVersion > 0 ) { String strMainPath = expPath + File.separator + "main." + mainVersion + "." + packageName + ".obb"; File main = new File(strMainPath); if ( main.isFile() ) { ret.add(strMainPath); } } if ( patchVersion > 0 ) { String strPatchPath = expPath + File.separator + "patch." + mainVersion + "." + packageName + ".obb"; File main = new File(strPatchPath); if ( main.isFile() ) { ret.add(strPatchPath); } } } } String[] retArray = new String[ret.size()]; ret.toArray(retArray); return retArray; }
Anda dapat memanggil metode ini dengan meneruskannya ke Context
aplikasi Anda dan versi file ekspansi yang diinginkan.
Ada banyak cara untuk menentukan nomor versi file ekspansi. Salah satu cara sederhana adalah
menyimpan versi dalam file SharedPreferences
saat download dimulai, dengan
mengkueri nama file ekspansi menggunakan metode getExpansionFileName(int index)
class APKExpansionPolicy
. Kemudian, Anda bisa mendapatkan kode versi dengan membaca file SharedPreferences
saat ingin mengakses file
perluasan.
Untuk informasi selengkapnya tentang membaca dari penyimpanan bersama, lihat dokumentasi Penyimpanan Data.
Menggunakan Library Zip Perluasan APK
Paket Perluasan APK Google Market menyertakan library yang disebut dengan Library Zip Perluasan
APK (terletak di <sdk>/extras/google/google_market_apk_expansion/zip_file/
). Ini adalah library opsional yang
membantu Anda membaca file
perluasan saat disimpan sebagai file ZIP. Dengan library ini, Anda dapat dengan mudah membaca resource dari
file ekspansi ZIP sebagai sistem file virtual.
Library Zip Perluasan APK menyertakan class dan API berikut:
APKExpansionSupport
- Menyediakan beberapa metode untuk mengakses file ZIP dan nama file ekspansi:
getAPKExpansionFiles()
- Metode sama yang ditampilkan di atas yang menampilkan jalur file lengkap ke kedua file perluasan.
getAPKExpansionZipFile(Context ctx, int mainVersion, int patchVersion)
- Menampilkan
ZipResourceFile
yang merepresentasikan jumlah file utama dan file patch. Artinya, jika Anda menentukanmainVersion
danpatchVersion
, metode ini akan menampilkanZipResourceFile
yang memberikan akses baca ke semua data, dengan data file patch yang digabungkan di bagian atas file utama.
ZipResourceFile
- Merepresentasikan file ZIP di penyimpanan bersama dan menjalankan semua tugas untuk memberikan sistem file virtual
berdasarkan file ZIP Anda. Anda bisa mendapatkan instance menggunakan
APKExpansionSupport.getAPKExpansionZipFile()
atauZipResourceFile
dengan meneruskan kepadanya jalur ke file ekspansi Anda. Class ini menyertakan berbagai metode berguna, tetapi umumnya Anda tidak perlu mengakses sebagian besar metode tersebut. Beberapa metode penting adalah:getInputStream(String assetPath)
- Memberikan
InputStream
untuk membaca file dalam file ZIP.assetPath
harus menjadi jalur ke file yang diinginkan, terkait dengan root pada isi file ZIP. getAssetFileDescriptor(String assetPath)
- Memberikan
AssetFileDescriptor
untuk file di dalam file ZIP.assetPath
harus menjadi jalur ke file yang diinginkan, terkait dengan root pada isi file ZIP. Metode ini berguna untuk API Android tertentu yang memerlukanAssetFileDescriptor
, seperti beberapa APIMediaPlayer
.
APEZProvider
- Sebagian besar aplikasi tidak perlu menggunakan class ini. Class ini menentukan
ContentProvider
yang melakukan marshal pada data dari file ZIP melaluiUri
penyedia konten agar dapat memberikan akses file untuk API Android tertentu yang mengharapkan aksesUri
ke file media. Misalnya, class ini berguna jika Anda ingin memutar video denganVideoView.setVideoURI()
.
Melewatkan kompresi ZIP file media
Jika Anda menggunakan file ekspansi untuk menyimpan file media, file ZIP masih memungkinkan Anda
menggunakan panggilan pemutaran media Android yang memberikan kontrol offset dan durasi (seperti MediaPlayer.setDataSource()
dan
SoundPool.load()
). Agar
hal ini dapat bekerja, Anda tidak boleh menjalankan kompresi tambahan pada file media saat membuat paket
ZIP. Misalnya, saat menggunakan alat zip
, Anda harus menggunakan opsi
-n
untuk menentukan akhiran file yang seharusnya tidak dikompresi:
zip -n .mp4;.ogg main_expansion media_files
Membaca dari file ZIP
Saat menggunakan Library Zip Perluasan APK, membaca file dari ZIP biasanya memerlukan beberapa hal berikut:
Kotlin
// Get a ZipResourceFile representing a merger of both the main and patch files val expansionFile = APKExpansionSupport.getAPKExpansionZipFile(appContext, mainVersion, patchVersion) // Get an input stream for a known file inside the expansion file ZIPs expansionFile.getInputStream(pathToFileInsideZip).use { ... }
Java
// Get a ZipResourceFile representing a merger of both the main and patch files ZipResourceFile expansionFile = APKExpansionSupport.getAPKExpansionZipFile(appContext, mainVersion, patchVersion); // Get an input stream for a known file inside the expansion file ZIPs InputStream fileStream = expansionFile.getInputStream(pathToFileInsideZip);
Kode di atas memberikan akses ke file apa pun yang ada di file ekspansi utama atau
file ekspansi patch, dengan membaca peta gabungan semua file dari kedua file tersebut. Semua
yang Anda butuhkan untuk memberikan metode getAPKExpansionFile()
adalah android.content.Context
aplikasi dan nomor versi file ekspansi utama dan file ekspansi
patch.
Jika lebih suka membaca dari file ekspansi tertentu, Anda dapat menggunakan konstruktor ZipResourceFile
dengan jalur ke file ekspansi yang diinginkan:
Kotlin
// Get a ZipResourceFile representing a specific expansion file val expansionFile = ZipResourceFile(filePathToMyZip) // Get an input stream for a known file inside the expansion file ZIPs expansionFile.getInputStream(pathToFileInsideZip).use { ... }
Java
// Get a ZipResourceFile representing a specific expansion file ZipResourceFile expansionFile = new ZipResourceFile(filePathToMyZip); // Get an input stream for a known file inside the expansion file ZIPs InputStream fileStream = expansionFile.getInputStream(pathToFileInsideZip);
Untuk informasi selengkapnya tentang menggunakan library ini untuk file ekspansi Anda, lihat
class SampleDownloaderActivity
aplikasi contoh, yang menyertakan kode tambahan untuk
memverifikasi file yang didownload menggunakan CRC. Berhati-hatilah jika Anda menggunakan contoh ini sebagai dasar
implementasi Anda sendiri, contoh ini mewajibkan Anda mendeklarasikan ukuran byte file
perluasan Anda dalam array xAPKS
.
Menguji file ekspansi Anda
Sebelum memublikasikan aplikasi, ada dua hal yang harus diuji: Membaca file ekspansi dan mendownload filenya.
Menguji pembacaan file
Sebelum mengupload aplikasi ke Google Play, Anda harus menguji kemampuan aplikasi untuk membaca file dari penyimpanan bersama. Yang perlu Anda lakukan adalah menambahkan file tersebut ke lokasi yang sesuai di penyimpanan bersama perangkat dan meluncurkan aplikasi Anda:
- Di perangkat, buat direktori yang sesuai di penyimpanan bersama tempat Google
Play akan menyimpan file Anda.
Misalnya, jika nama paket adalah
com.example.android
, Anda harus membuat direktoriAndroid/obb/com.example.android/
di ruang penyimpanan bersama. (Sambungkan perangkat pengujian ke komputer untuk memasang penyimpanan bersama dan membuat direktori ini secara manual.) - Tambahkan file ekspansi ke direktori tersebut secara manual. Pastikan Anda mengganti nama file agar
sesuai dengan format nama file yang akan digunakan Google Play.
Misalnya, terlepas dari jenis filenya, file ekspansi utama untuk aplikasi
com.example.android
seharusnya adalahmain.0300110.com.example.android.obb
. Kode versi dapat berupa nilai apa pun yang Anda inginkan. Cukup ingat:- file ekspansi utama selalu diawali dengan
main
dan file patch diawali denganpatch
. - Nama paket selalu sama dengan nama APK tempat file dilampirkan di Google Play.
- file ekspansi utama selalu diawali dengan
- Setelah file ekspansi berada di perangkat, Anda dapat menginstal dan menjalankan aplikasi untuk menguji file ekspansi.
Berikut adalah beberapa pengingat terkait penanganan file ekspansi:
- Jangan menghapus atau mengganti nama file ekspansi
.obb
(bahkan jika Anda mengekstrak data ke lokasi lain). Jika melakukannya, Google Play (atau aplikasi Anda) akan berulang kali mendownload file ekspansi. - Jangan menyimpan data lain ke direktori
obb/
. Jika Anda harus mengekstrak beberapa data, simpan data tersebut ke lokasi yang ditentukan olehgetExternalFilesDir()
.
Menguji download file
Karena aplikasi Anda terkadang harus mendownload file ekspansi secara manual saat pertama kali dibuka, penting bagi Anda untuk menguji proses ini guna memastikan aplikasi Anda berhasil mengkueri URL, mendownload file, dan menyimpannya ke perangkat.
Untuk menguji implementasi prosedur download manual aplikasi, Anda dapat memublikasikannya ke track pengujian internal, sehingga hanya akan tersedia untuk penguji yang diizinkan. Jika semuanya berfungsi seperti yang diharapkan, aplikasi Anda akan mulai mendownload file ekspansi segera setelah aktivitas utama dimulai.
Catatan: Sebelumnya Anda dapat menguji aplikasi dengan mengupload versi "draf" yang tidak dipublikasikan. Fungsi ini tidak lagi didukung. Sebagai gantinya, Anda harus memublikasikannya ke track pengujian internal, tertutup, atau terbuka. Untuk informasi selengkapnya, lihat Aplikasi Draf Tidak Lagi Didukung.
Mengupdate Aplikasi Anda
Salah satu keuntungan besar menggunakan file ekspansi di Google Play adalah kemampuannya untuk mengupdate aplikasi tanpa mendownload ulang semua aset asli. Karena Google Play mengizinkan adanya dua file ekspansi dengan masing-masing APK, Anda dapat menggunakan file kedua sebagai "patch" yang memberikan update dan aset baru. Tindakan ini menghindari keharusan mendownload ulang file ekspansi utama yang mungkin terlalu besar dan mahal bagi pengguna.
file ekspansi patch secara teknis sama dengan file ekspansi utama dan baik sistem Android maupun Google Play tidak akan menjalankan proses patch yang sebenarnya di antara file perluasan utama dan patch. Kode aplikasi Anda harus menjalankan patch yang diperlukannya sendiri.
Jika Anda menggunakan file ZIP sebagai file ekspansi, Library Zip Ekspansi APK yang disertakan dengan paket Ekspansi APK akan menyertakan kemampuan untuk menggabungkan file patch dengan file ekspansi utama.
Catatan: Meskipun hanya perlu melakukan perubahan pada file perluasan
patch, Anda masih harus mengupdate APK agar Google Play dapat menjalankan update.
Jika Anda tidak memerlukan perubahan kode dalam aplikasi, cukup update versionCode
di dalam
manifes.
Selama Anda tidak mengubah file ekspansi utama yang terkait dengan APK di Konsol Play, pengguna yang sebelumnya menginstal aplikasi Anda tidak akan mendownload file ekspansi utama. Pengguna yang sudah ada hanya akan menerima APK terupdate dan file ekspansi patch baru (mempertahankan file ekspansi utama sebelumnya).
Berikut adalah beberapa masalah yang harus diperhatikan terkait update pada file ekspansi:
- Hanya boleh ada dua file ekspansi untuk aplikasi Anda dalam satu waktu. Satu file perluasan utama dan satu file ekspansi patch. Selama update ke file, Google Play akan menghapus versi sebelumnya (dan begitu juga aplikasi Anda saat menjalankan update manual).
- Saat menambahkan file ekspansi patch, sistem Android sebenarnya tidak akan melakukan patch pada aplikasi atau file ekspansi utama. Anda harus merancang aplikasi agar mendukung data patch. Akan tetapi, paket Perluasan APK menyertakan library untuk menggunakan file ZIP sebagai file ekspansi, yang menggabungkan data dari file patch ke file ekspansi utama, sehingga Anda dapat dengan mudah membaca semua data file ekspansi.