instal seluler bazel

Laporkan masalah Lihat sumber

Pengembangan iterasi yang cepat untuk Android

Halaman ini menjelaskan cara bazel mobile-install membuat pengembangan iteratif untuk Android jauh lebih cepat. Bagian ini menjelaskan manfaat pendekatan ini dibandingkan tantangan metode penginstalan aplikasi tradisional.

Ringkasan

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

  1. Temukan aturan android_binary dari aplikasi yang ingin diinstal.
  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. Tidak perlu menunggu lama.

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 aplikasi yang berguna dari hal ini adalah memilih perangkat yang ingin digunakan jika Anda memiliki beberapa perangkat yang terhubung ke workstation: 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 banyak perbedaan antara mengubah kode dan melihatnya dijalankan dalam satu detik dan harus menunggu beberapa menit, terkadang berjam-jam, sebelum Anda mendapatkan masukan tentang apakah perubahan yang Anda lakukan sesuai dengan harapan.

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

bazel mobile-install membuat pengembangan berulang untuk Android jauh lebih cepat dengan menggunakan kombinasi pemangkasan perubahan, sharding pekerjaan, dan manipulasi cerdas internal Android, semuanya tanpa mengubah kode aplikasi Anda.

Masalah terkait penginstalan aplikasi tradisional

Membuat aplikasi Android memiliki beberapa masalah, termasuk:

  • Men-dexing. Secara default, "dx" dipanggil tepat satu kali dalam build dan tidak tahu cara menggunakan kembali pekerjaan dari build sebelumnya: melakukan dexes ke setiap metode lagi, meskipun hanya satu metode yang diubah.

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

  • Kompilasi ke kode native. Android L memperkenalkan ART, yakni runtime Android baru, yang mengompilasi aplikasi terlebih dahulu, bukan mengompilasinya secara tepat waktu seperti Dalvik. Hal ini membuat aplikasi jauh lebih cepat dengan mengorbankan waktu penginstalan yang lebih lama. Hal ini merupakan konsekuensi yang bagus bagi pengguna karena mereka biasanya menginstal aplikasi sekali dan menggunakannya berkali-kali, tetapi menyebabkan pengembangan yang lebih lambat ketika aplikasi diinstal berkali-kali dan setiap versi dijalankan paling sering beberapa kali.

Pendekatan bazel mobile-install

bazel mobile-installmelakukan peningkatan berikut:

  • Dexing shard. Setelah membuat kode Java aplikasi, Bazel akan melakukan sharding file class menjadi bagian yang kira-kira berukuran 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 Android dihapus dari .apk utama dan disimpan dalam direktori penginstalan seluler yang terpisah. Hal ini memungkinkan update kode dan resource Android secara independen tanpa menginstal ulang seluruh aplikasi. Dengan demikian, proses transfer file memerlukan waktu lebih sedikit dan hanya file .dex yang telah berubah yang 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 sebenarnya. Semua ini transparan pada aplikasi, kecuali dalam beberapa kasus pojok yang dijelaskan di bawah.

Dexing Sharded

Sharded dexing cukup mudah dilakukan: setelah file .jar dibuat, alat akan melakukan sharding ke dalam file .jar terpisah yang berukuran kurang lebih sama, lalu memanggil dx pada file yang telah diubah sejak build sebelumnya. Logika yang menentukan shard mana ke dex tidak khusus untuk Android: logika ini hanya menggunakan algoritma pruning perubahan umum dari Bazel.

Versi pertama algoritma sharding hanya mengurutkan file .class menurut abjad, lalu membagi daftar tersebut menjadi beberapa bagian yang berukuran sama, tetapi cara ini ternyata kurang optimal: jika class ditambahkan atau dihapus (bahkan class bertingkat atau anonim), semua class secara alfabetis akan berubah satu demi satu, sehingga terjadi dexing pada shard tersebut kembali. Oleh karena itu, kami memutuskan untuk melakukan sharding paket Java, bukan class individual. Tentu saja, hal ini masih menyebabkan 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 secara otomatis menentukan jumlah shard terbaik, tetapi Bazel saat ini harus mengetahui serangkaian tindakan (misalnya, perintah yang harus dieksekusi selama build) sebelum mengeksekusinya, sehingga tidak dapat menentukan jumlah shard optimal karena tidak mengetahui jumlah class Java yang pada akhirnya akan ada di aplikasi. Secara umum, semakin banyak sharding yang ada, semakin cepat build dan penginstalan akan bekerja untuk aplikasi. {i>Sweet spot<i} biasanya antara 10 dan 50 shard.

Pentransferan file inkremental

Setelah mem-build aplikasi, langkah berikutnya adalah menginstalnya, sebaiknya dengan upaya yang paling sedikit. Penginstalan terdiri dari langkah-langkah berikut:

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

Tidak ada banyak inkrementalitas pada langkah pertama: aplikasi telah diinstal atau belum. Saat ini Bazel mengandalkan pengguna untuk menunjukkan apakah langkah ini harus dilakukan melalui opsi command line --incremental karena tidak dapat menentukan di semua kasus apakah diperlukan.

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

Perlu diingat bahwa Anda dapat mengakali algoritma penginstalan inkremental dengan mengubah file di perangkat, tetapi bukan checksum di manifes. Hal ini bisa dilindungi dengan menghitung checksum file di perangkat, tetapi hal ini dianggap tidak sebanding 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 terjadi.

Pemuatan yang sebenarnya diterapkan dengan membuat subclass BaseDexClassLoader dan merupakan teknik yang terdokumentasi dengan baik. Hal ini terjadi sebelum class aplikasi dimuat, sehingga class aplikasi apa pun yang berada dalam apk dapat ditempatkan di 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 berada dalam .apk. Artinya, perubahan pada class tersebut akan memerlukan penginstalan ulang penuh.

Hal ini dilakukan dengan mengganti class Application yang ditentukan dalam AndroidManifest.xml dengan aplikasi stub. Tindakan ini mengambil kontrol kapan aplikasi dimulai, dan menyesuaikan loader class dan pengelola resource secara tepat pada saat 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 dapat 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 aplikasi itu sendiri ke aplikasi sebenarnya dalam framework Android.

Hasil

Performa

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

Angka berikut dihitung untuk beberapa produk Google:

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

Batasan

Trik yang dilakukan aplikasi stub tidak berfungsi di setiap kasus. Kasus berikut menyoroti tempat yang tidak berfungsi seperti yang diharapkan:

  • Saat Context ditransmisikan ke class Application di ContentProvider#onCreate(). Metode ini dipanggil selama startup aplikasi sebelum memiliki kesempatan untuk mengganti instance class Application sehingga ContentProvider akan tetap mereferensikan aplikasi stub, bukan yang sebenarnya. Dapat dikatakan, ini bukan bug karena Anda tidak diharapkan untuk menurunkan Context seperti ini, tetapi hal ini tampaknya 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 ke beberapa file .dex dalam kasus tertentu, misalnya, ketika anotasi Java digunakan dengan cara yang tertentu. Selama aplikasi Anda tidak menggelitik bug tersebut, aplikasi tersebut juga akan berfungsi dengan Dalvik (namun, perlu diperhatikan bahwa dukungan untuk versi Android lama bukanlah fokus kami)