instal seluler bazel

7/0.9/2.5. Lihat sumber Nightly {/3/}

Pengembangan iteratif yang cepat untuk Android

Halaman ini menjelaskan cara bazel mobile-install mempercepat pengembangan iteratif untuk Android. Panduan ini menjelaskan manfaat pendekatan ini dibandingkan tantangan metode penginstalan aplikasi tradisional.

Ringkasan

Untuk menginstal perubahan kecil ke aplikasi Android dengan sangat cepat, lakukan hal berikut:

  1. Temukan aturan android_binary untuk aplikasi yang ingin Anda instal.
  2. Nonaktifkan Proguard dengan menghapus atribut proguard_specs.
  3. Tetapkan atribut multidex ke native.
  4. Tetapkan atribut dex_shards ke 10.
  5. Hubungkan perangkat yang menjalankan ART (bukan Dalvik) melalui USB dan aktifkan proses debug USB di perangkat tersebut.
  6. Jalankan bazel mobile-install :your_target. Startup aplikasi akan sedikit lebih lambat dari biasanya.
  7. Edit kode atau resource Android.
  8. Jalankan bazel mobile-install --incremental :your_target.
  9. Nikmati tanpa perlu menunggu banyak.

Beberapa opsi command line untuk Bazel yang mungkin berguna:

  • --adb memberi tahu Bazel biner adb mana yang akan digunakan
  • --adb_arg dapat digunakan untuk menambahkan argumen tambahan ke command line adb. Salah satu penerapannya yang berguna adalah memilih perangkat tempat Anda ingin menginstal jika ada beberapa perangkat yang terhubung ke workstation Anda: bazel mobile-install --adb_arg=-s --adb_arg=<SERIAL> :your_target
  • --start_app otomatis memulai aplikasi

Jika ragu, lihat contoh atau hubungi kami.

Pengantar

Salah satu atribut terpenting dari toolchain developer adalah kecepatan: ada perbedaan antara mengubah kode dan melihatnya berjalan dalam satu detik serta harus menunggu beberapa menit, terkadang berjam-jam, sebelum Anda mendapatkan masukan apakah perubahan tersebut memberikan hasil yang diharapkan.

Sayangnya, toolchain Android tradisional untuk membuat .apk memerlukan banyak langkah monolitik dan berurutan, dan semua itu harus dilakukan untuk membuat aplikasi Android. Di Google, menunggu lima menit untuk membuat perubahan baris tunggal bukanlah hal yang aneh pada project yang lebih besar seperti Google Maps.

bazel mobile-install mempercepat pengembangan iteratif untuk Android dengan menggunakan kombinasi pruning perubahan, sharding pekerjaan, dan manipulasi cerdas internal Android, tanpa mengubah kode aplikasi Anda.

Masalah pada penginstalan aplikasi tradisional

Membangun aplikasi Android memiliki beberapa masalah, termasuk:

  • Dexing. Secara default, "dx" dipanggil sekali dalam build dan tidak mengetahui cara menggunakan kembali pekerjaan dari build sebelumnya: metode ini melakukan dexes setiap metode lagi, meskipun hanya ada satu metode yang diubah.

  • Mengupload data ke perangkat. adb tidak menggunakan bandwidth penuh koneksi USB 2.0, dan aplikasi yang lebih besar dapat memerlukan banyak waktu untuk diupload. Seluruh aplikasi diupload, meskipun hanya bagian kecil yang berubah, misalnya, resource atau satu metode, sehingga hal ini dapat menjadi bottleneck utama.

  • Kompilasi ke kode native. Android L memperkenalkan ART, sebuah runtime Android baru, yang mengompilasi aplikasi terlebih dahulu, bukan mengompilasinya tepat waktu seperti Dalvik. Hal ini membuat aplikasi jauh lebih cepat dengan mengorbankan waktu penginstalan yang lebih lama. Ini adalah kompromi yang baik bagi pengguna karena mereka biasanya menginstal aplikasi sekali dan menggunakannya berkali-kali, tetapi menghasilkan pengembangan yang lebih lambat karena aplikasi diinstal berkali-kali dan setiap versi dijalankan paling banyak dalam beberapa kali.

Pendekatan bazel mobile-install

bazel mobile-installmembuat peningkatan berikut:

  • dexing yang di-sharding. Setelah membuat kode Java aplikasi, Bazel melakukan sharding file class menjadi bagian-bagian yang berukuran kira-kira sama dan memanggil dx secara terpisah. dx tidak dipanggil pada shard yang tidak berubah sejak build terakhir.

  • Transfer file inkremental. Resource Android, file .dex, dan library native akan dihapus dari .apk utama dan disimpan di direktori instal seluler yang terpisah. Hal ini memungkinkan Anda mengupdate kode dan resource Android secara independen tanpa menginstal ulang seluruh aplikasi. Oleh karena itu, mentransfer file memerlukan waktu lebih sedikit dan hanya file .dex yang telah berubah dikompilasi ulang di perangkat.

  • Memuat bagian aplikasi dari luar .apk. Aplikasi stub kecil dimasukkan ke dalam .apk yang memuat resource Android, kode Java, dan kode native dari direktori penginstalan seluler di perangkat, lalu mentransfer kontrol ke aplikasi yang sebenarnya. Semua ini transparan pada aplikasi, kecuali dalam beberapa kasus sudut yang dijelaskan di bawah ini.

Dexing dengan Shard

Sharded dexing cukup mudah: setelah file .jar dibuat, alat akan membaginya menjadi file .jar terpisah yang kira-kira sama ukurannya, lalu memanggil dx pada file yang telah diubah sejak build sebelumnya. Logika yang menentukan shard mana yang akan di-dex tidak spesifik untuk Android: logika ini hanya menggunakan algoritma pemangkasan perubahan umum Bazel.

Versi pertama algoritme sharding hanya mengurutkan file .class berdasarkan abjad, lalu memotong daftar menjadi bagian-bagian yang berukuran sama, tetapi cara ini terbukti kurang optimal: jika class ditambahkan atau dihapus (bahkan yang bertingkat atau anonim), hal ini akan menyebabkan semua class menurut abjad setelah bergeser satu, sehingga menghasilkan dexing shard tersebut lagi. Oleh karena itu, diputuskan untuk melakukan sharding paket Java, bukan class individual. Tentu saja, hal ini masih menghasilkan dexing banyak shard jika paket baru ditambahkan atau dihapus, tetapi hal ini jauh lebih jarang daripada menambahkan atau menghapus satu class.

Jumlah shard dikontrol oleh file BUILD (menggunakan atribut android_binary.dex_shards). Dalam kondisi ideal, Bazel akan otomatis menentukan jumlah shard terbaik, tetapi saat ini Bazel harus mengetahui rangkaian tindakan (misalnya, perintah yang harus dijalankan selama build) sebelum menjalankan salah satunya, sehingga tidak dapat menentukan jumlah shard yang optimal karena tidak mengetahui jumlah class Java yang pada akhirnya akan ada dalam aplikasi. Secara umum, semakin banyak shard, semakin cepat proses build dan penginstalannya menjadi lebih lambat. Nilai terbaik biasanya antara 10 dan 50 sharding.

Transfer file inkremental

Setelah membuat aplikasi, langkah berikutnya adalah menginstalnya, sebaiknya dengan upaya seminimal mungkin. Penginstalan terdiri dari langkah-langkah berikut:

  1. Menginstal .apk (biasanya menggunakan adb install)
  2. Mengupload file .dex, resource Android, dan library native ke direktori penginstalan seluler

Tidak banyak inkrementalitas di langkah pertama: aplikasi sudah diinstal atau tidak. Bazel saat ini mengandalkan pengguna untuk menunjukkan apakah ia harus melakukan langkah ini melalui opsi command line --incremental karena tidak dapat menentukan dalam semua kasus jika diperlukan.

Pada langkah kedua, file aplikasi dari build akan dibandingkan dengan file manifes di perangkat yang mencantumkan file aplikasi mana yang ada di perangkat dan checksumnya. Semua file baru akan diupload ke perangkat, file yang berubah akan diperbarui, dan file apa pun yang telah dihapus akan dihapus dari perangkat. Jika manifes tidak ada, diasumsikan bahwa setiap file perlu diupload.

Perhatikan bahwa algoritma penginstalan inkremental dapat ditipu dengan mengubah file pada perangkat, tetapi tidak untuk checksum-nya di manifes. Hal ini dapat dicegah dengan menghitung checksum file di perangkat, tetapi hal ini dianggap tidak sepadan dengan peningkatan waktu penginstalan.

Aplikasi Stub

Aplikasi stub adalah tempat keajaiban untuk memuat dexes, kode native, dan resource Android dari direktori mobile-install di perangkat.

Pemuatan sebenarnya diterapkan dengan membuat subclass BaseDexClassLoader dan merupakan teknik yang didokumentasikan dengan cukup baik. Hal ini terjadi sebelum class aplikasi apa pun dimuat sehingga class aplikasi apa pun yang ada di apk dapat ditempatkan dalam direktori mobile-install di perangkat sehingga dapat diupdate tanpa adb install.

Hal ini harus terjadi sebelum salah satu class aplikasi dimuat, sehingga tidak ada class aplikasi yang perlu ada dalam .apk, yang berarti perubahan pada class tersebut akan memerlukan penginstalan ulang sepenuhnya.

Hal ini dilakukan dengan mengganti class Application yang ditentukan dalam AndroidManifest.xml dengan aplikasi stub. API ini mengontrol kapan aplikasi dimulai, serta menyesuaikan loader class dan resource manager dengan tepat pada saat yang paling awal (konstruktornya) menggunakan refleksi Java pada bagian internal framework Android.

Hal lain yang dilakukan aplikasi stub adalah menyalin library native yang diinstal oleh penginstalan seluler ke lokasi lain. Hal ini diperlukan karena linker dinamis memerlukan bit X untuk ditetapkan pada file, yang tidak mungkin dilakukan untuk lokasi mana pun yang dapat diakses oleh adb non-root.

Setelah semua hal ini selesai, aplikasi stub kemudian membuat instance class Application yang sebenarnya, mengubah semua referensi ke dirinya sendiri ke aplikasi sebenarnya dalam framework Android.

Hasil

Performa

Secara umum, bazel mobile-install menghasilkan percepatan proses build dan penginstalan aplikasi besar sebesar 4x hingga 10x setelah perubahan kecil.

Angka berikut telah dihitung untuk beberapa produk Google:

Hal ini, tentu saja, bergantung pada sifat perubahan: kompilasi ulang setelah mengubah library dasar memerlukan lebih banyak waktu.

Batasan

Trik yang dimainkan aplikasi stub mungkin tidak pada semua kasus. Kasus berikut akan menunjukkan area yang tidak berfungsi seperti yang diharapkan:

  • Saat Context ditransmisikan ke class Application di ContentProvider#onCreate(). Metode ini dipanggil selama startup aplikasi sebelum kita memiliki kesempatan untuk mengganti instance class Application, sehingga ContentProvider akan tetap mereferensikan aplikasi stub, bukan yang asli. Bisa dibilang, ini bukan bug karena Anda tidak seharusnya menghapus Context seperti ini, tetapi hal ini sepertinya terjadi di beberapa aplikasi di Google.

  • Resource yang diinstal oleh bazel mobile-install hanya tersedia dari dalam aplikasi. Jika resource diakses oleh aplikasi lain melalui PackageManager#getApplicationResources(), resource ini akan berasal dari penginstalan non-inkremental terakhir.

  • Perangkat yang tidak menjalankan ART. Meskipun aplikasi stub berfungsi dengan baik di Froyo dan setelahnya, Dalvik memiliki bug yang membuatnya berpikir bahwa aplikasi tersebut salah jika kodenya didistribusikan melalui beberapa file .dex dalam kasus tertentu, misalnya, ketika anotasi Java digunakan dengan cara tertentu. Selama tidak menghilangkan bug ini, aplikasi seharusnya berfungsi dengan Dalvik juga (perlu diperhatikan bahwa dukungan untuk versi Android lama bukanlah fokus kami)