instal seluler bazel

Laporkan masalah Lihat sumber

Pengembangan berulang yang cepat untuk Android

Halaman ini menjelaskan bagaimana bazel mobile-install membuat pengembangan berulang untuk Android menjadi jauh lebih cepat. Laporan ini menjelaskan manfaat pendekatan ini dibandingkan dengan 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.
  6. Jalankan bazel mobile-install :your_target. Memulai aplikasi akan sedikit lebih lambat dari biasanya.
  7. Edit kode atau resource Android.
  8. Jalankan bazel mobile-install --incremental :your_target.
  9. Anda 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 lain ke command line adb. Salah satu aplikasi yang berguna dari hal ini adalah memilih perangkat yang ingin Anda instal jika 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 perbedaan antara mengubah kode dan melihatnya berjalan dalam detik dan harus menunggu menit, terkadang jam, sebelum Anda mendapatkan masukan apakah perubahan Anda melakukan apa yang Anda harapkan.

Sayangnya, toolchain Android tradisional untuk membuat .apk memerlukan banyak langkah monolitik berurutan dan semuanya harus dilakukan untuk mem-build aplikasi Android. Di Google, menunggu lima menit untuk membuat perubahan satu baris adalah hal yang tidak biasa 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 kerja, dan manipulasi cerdas internal Android, tanpa mengubah kode aplikasi apa pun.

Masalah dengan penginstalan aplikasi tradisional

Membuat aplikasi Android memiliki beberapa masalah, termasuk:

  • Dexing. Secara default, "dx" dipanggil tepat satu kali dalam build dan tidak mengetahui cara menggunakan kembali pekerjaan dari build sebelumnya: dx men-dexing setiap metode lagi, meskipun hanya satu metode yang diubah.

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

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

Pendekatan bazel mobile-install

bazel mobile-installmelakukan peningkatan berikut:

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

  • Transfer file inkremental. Resource Android, file .dex, dan library native dihapus dari .apk utama dan disimpan dalam direktori penginstalan seluler terpisah. Hal ini memungkinkan Anda untuk mengupdate kode dan resource Android secara independen tanpa menginstal ulang seluruh aplikasi. Dengan demikian, mentransfer file memerlukan waktu yang lebih singkat 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 instal seluler di perangkat, lalu mentransfer kontrol ke aplikasi sebenarnya. Semua ini transparan ke aplikasi, kecuali dalam beberapa kasus pojok yang dijelaskan di bawah ini.

Dexing dengan Shard

dexing yang di-sharding cukup sederhana: setelah file .jar di-build, alat akan melakukan sharding ke file .jar terpisah dengan ukuran yang kira-kira sama, kemudian memanggil dx pada file yang telah diubah sejak build sebelumnya. Logika yang menentukan shard mana untuk dex tidak khusus untuk Android: logika ini hanya menggunakan algoritme pemangkasan perubahan umum Bazel.

Versi pertama dari algoritme sharding hanya mengurutkan file .class secara alfabetis, lalu memotong daftar menjadi bagian-bagian yang berukuran sama, tetapi hal ini terbukti kurang optimal: jika class ditambahkan atau dihapus (bahkan yang bertingkat atau anonim), hal ini akan menyebabkan semua class menurut abjad bergeser ke satu, sehingga menyebabkan shard tersebut menjadi shard lagi. Karena itu, diputuskan untuk melakukan sharding paket Java, bukan class individual. Tentu saja, tindakan ini masih menyebabkan dexing dalam banyak shard jika paket baru ditambahkan atau dihapus, tetapi 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 yang paling baik, tetapi saat ini Bazel harus mengetahui kumpulan tindakan (misalnya perintah yang akan dijalankan selama build) sebelum menjalankan salah satu di antaranya, sehingga tidak dapat menentukan jumlah shard yang optimal karena semakin cepat tidaknya semakin banyak class Java yang akan ada, dan semakin cepat shard akan semakin cepat, semakin cepat pembuatan semakin cepat, semakin cepat aplikasi semakin cepat berkembang. Ukuran yang pas biasanya antara 10 dan 50 shard.

Transfer file inkremental

Setelah mem-build 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 instal seluler

Tidak ada banyak inkrementalitas pada langkah pertama: aplikasi sudah diinstal atau tidak. Bazel saat ini mengandalkan pengguna untuk menunjukkan apakah langkah ini perlu dilakukan melalui opsi command line --incremental karena hal tersebut tidak dapat ditentukan dalam semua kasus jika diperlukan.

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

Perhatikan bahwa Anda dapat menipu algoritme penginstalan inkremental dengan mengubah file di perangkat, tetapi bukan checksum dalam manifes. Hal ini dapat diamankan 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 dex, kode native, dan resource Android dari direktori mobile-install di perangkat terjadi.

Pemuatan 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 ada dalam apk dapat ditempatkan di direktori mobile-install pada perangkat sehingga dapat diperbarui tanpa adb install.

Hal ini harus terjadi sebelum class aplikasi dimuat, sehingga tidak ada class aplikasi yang perlu berada di .apk. Artinya, perubahan pada class tersebut akan memerlukan penginstalan ulang sepenuhnya.

Hal ini dicapai dengan mengganti class Application yang ditentukan dalam AndroidManifest.xml dengan aplikasi stub. Hal ini membutuhkan kontrol saat aplikasi dimulai, dan menyesuaikan loader class serta pengelola resource dengan tepat pada saat paling awal (konstruktornya) menggunakan refleksi Java pada internal framework Android.

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

Setelah semua hal ini dilakukan, aplikasi stub kemudian membuat instance class Application aktual, dengan mengubah semua referensi ke dirinya 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:

Tentu saja, hal ini bergantung pada sifat perubahan: kompilasi ulang setelah mengubah library dasar membutuhkan waktu lebih lama.

Batasan

Trik yang dimainkan oleh aplikasi stub tidak berfungsi dalam setiap kasus. Kasus berikut menyoroti bagian yang tidak bekerja seperti yang diharapkan:

  • Saat Context ditransmisikan ke class Application di ContentProvider#onCreate(). Metode ini dipanggil selama memulai aplikasi sebelum memiliki kesempatan untuk mengganti instance class Application, oleh karena itu, ContentProvider akan tetap mereferensikan aplikasi stub, bukan yang asli. Boleh dibilang ini bukan bug karena Anda tidak seharusnya mengecilkan Context seperti ini, tetapi hal ini tampaknya terjadi di beberapa aplikasi di Google.

  • Resource yang diinstal oleh bazel mobile-install hanya tersedia dari 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 yang lebih baru, Dalvik memiliki bug yang membuat aplikasi dianggap salah jika kodenya didistribusikan ke beberapa file .dex dalam kasus tertentu, misalnya saat anotasi Java digunakan dengan cara tertentu. Selama aplikasi tidak menggelitik bug tersebut, aplikasi juga dapat berfungsi dengan Dalvik (namun, perlu diperhatikan bahwa dukungan untuk versi Android lama bukanlah fokus kami)