Mendownload modul dengan Library Play Core

Dengan Pengiriman Dinamis Google Play, aplikasi Anda dapat mendownload modul fitur dinamis secara on demand ke perangkat yang menjalankan Android 5.0 (API level 21) dan yang lebih tinggi. Aplikasi Anda hanya perlu memanggil API di Library Play Core untuk mendownload dan menginstal modul tersebut jika diperlukan, dan Google Play Store hanya mengirimkan kode dan resource yang diperlukan untuk modul tersebut ke perangkat. Anda juga dapat menggunakan API ini untuk mendownload modul on demand untuk Aplikasi Instan Android.

Untuk mempelajari cara menambahkan modul fitur dinamis untuk pertama kalinya ke project dan mengonfigurasinya agar tersedia secara on demand, baca Membuat modul fitur dinamis.

Selain itu, setelah Anda membaca panduan ini, lihat penerapan API dengan mencoba aplikasi contoh Play Core API dan pelajari cara mendukung update dalam aplikasi.

Terakhir, sebelum memublikasikan aplikasi, uji app bundle Anda untuk memverifikasi bahwa fungsionalitas on demand aplikasi Anda berfungsi sebagaimana mestinya.

Menyertakan Library Play Core di project Anda

Sebelum dapat mulai menggunakan Library Play Core, Anda harus mengimpornya terlebih dahulu ke modul aplikasi sebagai dependensi Gradle, seperti yang ditunjukkan di bawah:

    // In your app’s build.gradle file:
    ...
    dependencies {
        // This dependency is downloaded from the Google’s Maven repository.
        // So, make sure you also include that repository in your project's build.gradle file.
        implementation 'com.google.android.play:core:1.6.4'
        ...
    }
    

Meminta modul on demand

Jika aplikasi Anda perlu menggunakan modul fitur dinamis, aplikasi dapat memintanya saat berada di latar depan melalui class SplitInstallManager. Saat membuat permintaan, aplikasi Anda perlu menentukan nama modul seperti yang ditetapkan oleh elemen split dalam manifes modul target. Saat Anda membuat modul fitur dinamis menggunakan Android Studio, sistem build akan menggunakan Nama modul yang Anda sediakan untuk memasukkan properti ini ke dalam manifes modul pada waktu kompilasi. Untuk informasi selengkapnya, baca Manifes modul fitur dinamis.

Misalnya, pertimbangkan aplikasi yang memiliki modul on demand untuk mengambil dan mengirim pesan gambar menggunakan kamera perangkat, dan modul on demand ini menentukan split="pictureMessages" dalam manifesnya. Contoh berikut menggunakan SplitInstallManager untuk meminta modul pictureMessages (beserta modul tambahan untuk beberapa filter promosi):

Kotlin

    // Creates an instance of SplitInstallManager.
    val splitInstallManager = SplitInstallManagerFactory.create(context)

    // Creates a request to install a module.
    val request =
        SplitInstallRequest
            .newBuilder()
            // You can download multiple on demand modules per
            // request by invoking the following method for each
            // module you want to install.
            .addModule("pictureMessages")
            .addModule("promotionalFilters")
            .build()

    splitInstallManager
        // Submits the request to install the module through the
        // asynchronous startInstall() task. Your app needs to be
        // in the foreground to submit the request.
        .startInstall(request)
        // You should also be able to gracefully handle
        // request state changes and errors. To learn more, go to
        // the section about how to Monitor the request state.
        .addOnSuccessListener { sessionId -> ... }
        .addOnFailureListener { exception ->  ... }
    

Java

    // Creates an instance of SplitInstallManager.
    SplitInstallManager splitInstallManager =
        SplitInstallManagerFactory.create(context);

    // Creates a request to install a module.
    SplitInstallRequest request =
        SplitInstallRequest
            .newBuilder()
            // You can download multiple on demand modules per
            // request by invoking the following method for each
            // module you want to install.
            .addModule("pictureMessages")
            .addModule("promotionalFilters")
            .build();

    splitInstallManager
        // Submits the request to install the module through the
        // asynchronous startInstall() task. Your app needs to be
        // in the foreground to submit the request.
        .startInstall(request)
        // You should also be able to gracefully handle
        // request state changes and errors. To learn more, go to
        // the section about how to Monitor the request state.
        .addOnSuccessListener(sessionId -> { ... })
        .addOnFailureListener(exception -> { ... });
    

Saat aplikasi Anda meminta modul on demand, Library Play Core akan menggunakan strategi “fire-and-forget”. Artinya, aplikasi akan mengirim permintaan untuk mendownload modul ke platform, tetapi tidak memantau apakah penginstalan berhasil atau tidak. Untuk memindahkan perjalanan pengguna setelah penginstalan atau menangani error dengan baik, pastikan Anda memantau status permintaan.

Catatan: Anda dapat meminta modul fitur dinamis yang sudah terinstal di perangkat. API secara instan menganggap permintaan sebagai selesai jika mendeteksi bahwa modul sudah terinstal. Selain itu, setelah modul terinstal, Google Play akan mengupdate-nya secara otomatis. Artinya, saat Anda mengupload app bundle versi baru, platform akan mengupdate semua APK yang terinstal milik aplikasi Anda. Untuk informasi selengkapnya, baca Mengelola update aplikasi.

Untuk mendapatkan akses langsung ke kode dan resource modul, aplikasi Anda perlu mengaktifkan SplitCompat. Perhatikan bahwa SplitCompat tidak diperlukan untuk Aplikasi Instan Android— karena selalu memiliki akses langsung ke modul fitur.

Menunda penginstalan modul on demand

Jika tidak menginginkan aplikasi untuk segera mendownload dan menginstal modul on demand, Anda dapat menunda penginstalan saat aplikasi berada di latar belakang. Misalnya, jika Anda ingin melakukan pramuat beberapa materi promosi untuk peluncuran aplikasi Anda nanti.

Anda dapat menentukan modul yang akan didownload nanti menggunakan metode deferredInstall(), seperti yang ditunjukkan di bawah ini. Selain itu, tidak seperti SplitInstallManager.startInstall(), aplikasi Anda tidak perlu berada di latar depan untuk memulai permintaan penginstalan tertunda.

Kotlin

    // Requests an on demand module to be downloaded when the app enters
    // the background. You can specify more than one module at a time.
    splitInstallManager.deferredInstall(listOf("promotionalFilters"))
    

Java

    // Requests an on demand module to be downloaded when the app enters
    // the background. You can specify more than one module at a time.
    splitInstallManager.deferredInstall(Arrays.asList("promotionalFilters"));
    

Permintaan untuk menunda penginstalan adalah upaya terbaik dan tidak dapat dilacak progresnya. Jadi, sebelum mencoba mengakses modul yang telah Anda tentukan untuk penginstalan tertunda, sebaiknya Anda memeriksa apakah modul telah diinstal. Jika Anda perlu segera menyediakan modul, gunakan SplitInstallManager.startInstall() untuk memintanya, seperti yang ditunjukkan di bagian sebelumnya.

Memantau status permintaan

Agar dapat memperbarui status progres, mengaktifkan intent setelah penginstalan, atau menangani error permintaan dengan baik, Anda perlu memproses perubahan status dari tugas SplitInstallManager.startInstall() asinkron. Sebelum Anda dapat mulai menerima update untuk permintaan penginstalan, daftarkan pemroses dan dapatkan ID sesi untuk meminta, seperti yang ditunjukkan di bawah ini.

Kotlin

    // Initializes a variable to later track the session ID for a given request.
    var mySessionId = 0

    // Creates a listener for request status updates.
    val listener = SplitInstallStateUpdatedListener { state ->
        if (state.sessionId() == mySessionId) {
          // Read the status of the request to handle the state update.
        }
    }

    // Registers the listener.
    splitInstallManager.registerListener(listener)

    ...

    splitInstallManager
        .startInstall(request)
        // When the platform accepts your request to download
        // an on demand module, it binds it to the following session ID.
        // You use this ID to track further status updates for the request.
        .addOnSuccessListener { sessionId -> mySessionId = sessionId }
        // You should also add the following listener to handle any errors
        // processing the request.
        .addOnFailureListener { exception ->
            // Handle request errors.
        }

    // When your app no longer requires further updates, unregister the listener.
    splitInstallManager.unregisterListener(listener)
    

Java

    // Initializes a variable to later track the session ID for a given request.
    int mySessionId = 0;

    // Creates a listener for request status updates.
    SplitInstallStateUpdatedListener listener = state -> {
        if (state.sessionId() == mySessionId) {
          // Read the status of the request to handle the state update.
        }
    };

    // Registers the listener.
    splitInstallManager.registerListener(listener);

    ...

    splitInstallManager
        .startInstall(request)
        // When the platform accepts your request to download
        // an on demand module, it binds it to the following session ID.
        // You use this ID to track further status updates for the request.
        .addOnSuccessListener(sessionId -> { mySessionId = sessionId; })
        // You should also add the following listener to handle any errors
        // processing the request.
        .addOnFailureListener(exception -> {
            // Handle request errors.
        });

    // When your app no longer requires further updates, unregister the listener.
    splitInstallManager.unregisterListener(listener);
    

Menangani error permintaan

Anda harus menangani kegagalan mendownload atau menginstal modul dengan baik menggunakan addOnFailureListener(), seperti yang ditunjukkan di bawah:

Kotlin

    splitInstallManager
        .startInstall(request)
        .addOnFailureListener { exception ->
            when ((exception as SplitInstallException).errorCode) {
                SplitInstallErrorCode.NETWORK_ERROR -> {
                    // Display a message that requests the user to establish a
                    // network connection.
                }
                SplitInstallErrorCode.ACTIVE_SESSIONS_LIMIT_EXCEEDED -> checkForActiveDownloads()
                ...
            }
        }

    fun checkForActiveDownloads() {
        splitInstallManager
            // Returns a SplitInstallSessionState object for each active session as a List.
            .sessionStates
            .addOnCompleteListener { task ->
                if (task.isSuccessful) {
                    // Check for active sessions.
                    for (state in task.result) {
                        if (state.status() == SplitInstallSessionStatus.DOWNLOADING) {
                            // Cancel the request, or request a deferred installation.
                        }
                    }
                }
            }
    }
    

Java

    splitInstallManager
        .startInstall(request)
        .addOnFailureListener(exception -> {
            switch (((SplitInstallException) exception).getErrorCode()) {
                case SplitInstallErrorCode.NETWORK_ERROR:
                    // Display a message that requests the user to establish a
                    // network connection.
                    break;
                case SplitInstallErrorCode.ACTIVE_SESSIONS_LIMIT_EXCEEDED:
                    checkForActiveDownloads();
                ...
        });

    void checkForActiveDownloads() {
        splitInstallManager
            // Returns a SplitInstallSessionState object for each active session as a List.
            .getSessionStates()
            .addOnCompleteListener( task -> {
                if (task.isSuccessful()) {
                    // Check for active sessions.
                    for (SplitInstallSessionState state : task.getResult()) {
                        if (state.status() == SplitInstallSessionStatus.DOWNLOADING) {
                            // Cancel the request, or request a deferred installation.
                        }
                    }
                }
            });
    }
    

Tabel di bawah menjelaskan status error yang mungkin perlu ditangani oleh aplikasi Anda:

Kode error Deskripsi Tindakan yang disarankan
ACTIVE_SESSIONS_LIMIT_EXCEEDED Permintaan ditolak karena terdapat setidaknya satu permintaan yang ada yang sedang didownload. Periksa apakah ada permintaan apa pun yang masih didownload, seperti yang ditunjukkan pada contoh di atas.
MODULE_UNAVAILABLE Google Play tidak dapat menemukan modul yang diminta berdasarkan versi aplikasi yang terinstal saat ini, perangkat, dan akun Google Play pengguna. Jika pengguna tidak memiliki akses ke modul, beri tahu mereka.
INVALID_REQUEST Google Play menerima permintaan, tetapi permintaan tidak valid. Verifikasi bahwa informasi yang disertakan dalam permintaan sudah lengkap dan akurat.
SESSION_NOT_FOUND Sesi untuk ID sesi yang diberikan tidak ditemukan. Jika Anda mencoba memantau status permintaan berdasarkan ID sesinya, pastikan ID sesi sudah benar.
API_NOT_AVAILABLE Play Core Library tidak didukung di perangkat saat ini. Artinya, perangkat tidak dapat mendownload dan menginstal fitur on demand. Untuk perangkat yang menjalankan Android 4.4 (API level 20) atau lebih rendah, Anda harus menyertakan modul fitur dinamis pada waktu penginstalan menggunakan properti manifes dist:fusing. Untuk mempelajari lebih lanjut, baca Manifes modul fitur dinamis.
ACCESS_DENIED Aplikasi tidak dapat mendaftarkan permintaan karena izin tidak memadai. Hal ini biasanya terjadi saat aplikasi berada di latar belakang. Coba permintaan saat aplikasi kembali ke latar depan.
NETWORK_ERROR Permintaan gagal karena error jaringan. Minta pengguna untuk membuat koneksi jaringan atau beralih ke jaringan lain.
INCOMPATIBLE_WITH_EXISTING_SESSION Permintaan berisi satu atau beberapa modul yang telah diminta tetapi belum diinstal. Buat permintaan baru yang tidak menyertakan modul yang telah diminta oleh aplikasi Anda, atau tunggu semua modul yang saat ini diminta untuk menyelesaikan penginstalan sebelum mencoba kembali permintaan tersebut.

Perlu diingat, meminta modul yang telah diinstal tidak menyelesaikan error.

SERVICE_DIED Layanan yang bertanggung jawab untuk menangani permintaan sudah tidak berlaku. Coba lagi permintaan tersebut.

Kode error ini ditampilkan sebagai update ke SplitInstallStateUpdatedListener dengan status FAILED dan ID sesi -1.

Jika pengguna meminta untuk mendownload modul on demand dan terjadi error, pertimbangkan untuk menampilkan dialog yang memberikan dua opsi kepada pengguna: Coba lagi (yang mencoba mengajukan permintaan lagi) dan Batal (yang mengabaikan permintaan tersebut). Untuk dukungan tambahan, Anda juga harus menyediakan link Bantuan yang mengarahkan pengguna ke Pusat Bantuan Google Play.

Menangani perubahan status

Setelah Anda mendaftarkan pemroses dan mencatat ID sesi untuk permintaan Anda, gunakan StateUpdatedListener.onStateUpdate() untuk menangani perubahan status, seperti yang ditunjukkan di bawah ini.

Kotlin

    override fun onStateUpdate(state : SplitInstallSessionState) {
        if (state.status() == SplitInstallSessionStatus.FAILED
            && state.errorCode() == SplitInstallErrorCode.SERVICE_DIES) {
           // Retry the request.
           return
        }
        if (state.sessionId() == mySessionId) {
            when (state.status()) {
                SplitInstallSessionStatus.DOWNLOADING -> {
                  val totalBytes = state.totalBytesToDownload()
                  val progress = state.bytesDownloaded()
                  // Update progress bar.
                }
                SplitInstallSessionStatus.INSTALLED -> {

                  // After a module is installed, you can start accessing its content or
                  // fire an intent to start an activity in the installed module.
                  // For other use cases, see access code and resources from installed modules.

                  // If the request is an on demand module for an Android Instant App
                  // running on Android 8.0 (API level 26) or higher, you need to
                  // update the app context using the SplitInstallHelper API.
                }
            }
        }
    }
    

Java

    @Override
    public void onStateUpdate(SplitInstallSessionState state) {
        if (state.status() == SplitInstallSessionStatus.FAILED
            && state.errorCode() == SplitInstallErrorCode.SERVICE_DIES) {
           // Retry the request.
           return;
        }
        if (state.sessionId() == mySessionId) {
            switch (state.status()) {
                case SplitInstallSessionStatus.DOWNLOADING:
                  int totalBytes = state.totalBytesToDownload();
                  int progress = state.bytesDownloaded();
                  // Update progress bar.
                  break;

                case SplitInstallSessionStatus.INSTALLED:

                  // After a module is installed, you can start accessing its content or
                  // fire an intent to start an activity in the installed module.
                  // For other use cases, see access code and resources from installed modules.

                  // If the request is an on demand module for an Android Instant App
                  // running on Android 8.0 (API level 26) or higher, you need to
                  // update the app context using the SplitInstallHelper API.
            }
        }
    }
    

Status yang memungkinkan untuk permintaan penginstalan Anda dijelaskan dalam tabel di bawah ini.

Status permintaan Deskripsi Tindakan yang disarankan
MENUNGGU KEPUTUSAN Permintaan telah diterima dan download akan segera dimulai. Menginisialisasi komponen UI, seperti status progres, untuk memberikan masukan kepada pengguna mengenai download.
REQUIRES_USER_CONFIRMATION Proses download ini memerlukan konfirmasi pengguna. Hal ini kemungkinan besar disebabkan karena ukuran download yang lebih besar dari 10 MB. Minta pengguna untuk menerima permintaan download. Untuk mempelajari lebih lanjut, buka bagian tentang cara mendapatkan konfirmasi pengguna.
MENDOWNLOAD Proses download sedang berlangsung. Jika Anda menyediakan status progres untuk download, gunakan metode SplitInstallSessionState.bytesDownloaded() dan SplitInstallSessionState.totalBytesToDownload() untuk mengupdate UI (lihat contoh kode di atas tabel ini).
DIDOWNLOAD Perangkat telah mendownload modul, tetapi penginstalan belum dimulai. Aplikasi harus mengaktifkan SplitCompat agar memiliki akses langsung ke modul yang didownload dan terhindar dari status ini. Jika tidak, transisi download ke INSTALLED, dan akses aplikasi ke kode dan resource-nya, akan terjadi hanya pada waktu tertentu setelah aplikasi memasuki latar belakang.
MENGINSTAL Perangkat saat ini sedang menginstal modul. Memperbarui status progres. Status ini biasanya singkat.
TERINSTAL Modul diinstal di perangkat. Kode akses dan resource dalam modul untuk melanjutkan perjalanan pengguna.

Jika modul ditujukan untuk Aplikasi Instan Android yang berjalan di Android 8.0 (API level 26) atau yang lebih tinggi, Anda harus menggunakan splitInstallHelper untuk mengupdate komponen aplikasi dengan modul baru.

GAGAL Permintaan gagal sebelum modul diinstal di perangkat. Minta pengguna untuk mencoba kembali permintaan atau membatalkannya.
MEMBATALKAN Perangkat sedang dalam proses membatalkan permintaan. Untuk mempelajari lebih lanjut, buka bagian tentang cara membatalkan permintaan penginstalan.
DIBATALKAN Permintaan telah dibatalkan.

Mendapatkan konfirmasi pengguna

Dalam beberapa kasus, Google Play mungkin memerlukan konfirmasi pengguna sebelum memenuhi permintaan download. Misalnya, jika permintaan memerlukan download yang besar dan perangkat menggunakan data seluler. Dalam kasus semacam itu, status laporan permintaan REQUIRES_USER_CONFIRMATION dan aplikasi Anda perlu mendapatkan konfirmasi pengguna sebelum perangkat dapat mendownload dan menginstal modul yang diminta. Untuk mendapatkan konfirmasi, aplikasi Anda akan meminta pengguna seperti berikut:

Kotlin

    override fun onSessionStateUpdate(state: SplitInstallSessionState) {
        if (state.status() == SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION) {
            // Displays a dialog for the user to either “Download”
            // or “Cancel” the request.
            splitInstallManager.startConfirmationDialogForResult(
              state,
              /* activity = */ this,
              // You use this request code to later retrieve the user's decision.
              /* requestCode = */ MY_REQUEST_CODE)
        }
        ...
     }
    

Java

    @Override void onSessionStateUpdate(SplitInstallSessionState state) {
        if (state.status() == SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION) {
            // Displays a dialog for the user to either “Download”
            // or “Cancel” the request.
            splitInstallManager.startConfirmationDialogForResult(
              state,
              /* activity = */ this,
              // You use this request code to later retrieve the user's decision.
              /* requestCode = */ MY_REQUEST_CODE);
        }
        ...
     }
    

Status permintaan akan diperbarui bergantung pada respons pengguna:

  • Jika pengguna memilih “Download”, status permintaan akan berubah menjadi PENDING dan download akan dimulai.
  • Jika pengguna memilih “Batal”, status permintaan akan berubah menjadi CANCELED.
  • Jika pengguna tidak memilih apa pun sebelum dialog ditutup, status permintaan tetap menjadi REQUIRES_USER_CONFIRMATION. Aplikasi Anda dapat meminta pengguna kembali untuk menyelesaikan permintaan.

Untuk menerima callback dengan respons pengguna, gunakan onActivityResult(), seperti yang ditunjukkan di bawah ini.

Kotlin

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
      if (requestCode == MY_REQUEST_CODE) {
        // Handle the user's decision. For example, if the user selects "Cancel",
        // you may want to disable certain functionality that depends on the module.
      }
    }
    

Java

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
      if (requestCode == MY_REQUEST_CODE) {
        // Handle the user's decision. For example, if the user selects "Cancel",
        // you may want to disable certain functionality that depends on the module.
      }
    }
    

Membatalkan permintaan penginstalan

Jika aplikasi Anda perlu membatalkan permintaan sebelum diinstal, aplikasi dapat memanggil metode cancelInstall() menggunakan ID sesi permintaan, seperti yang ditunjukkan di bawah ini.

Kotlin

    SplitInstallManager
        // Cancels the request for the given session ID.
        .cancelInstall(mySessionId)
    

Java

    SplitInstallManager
        // Cancels the request for the given session ID.
        .cancelInstall(mySessionId);
    

Mengakses modul dengan segera

Untuk segera mengakses kode dan resource dari modul yang didownload—yaitu, sebelum aplikasi dimulai ulang—aplikasi Anda harus mengaktifkan Library SplitCompat untuk aplikasi dan setiap aktivitas Anda dalam modul fitur dinamis yang didownload.

Namun, sebaiknya perhatikan bahwa platform memiliki pembatasan berikut dalam mengakses konten modul sebelum aplikasi dimulai ulang:

  • Platform tidak dapat menerapkan entri manifes baru yang diperkenalkan oleh modul.
  • Platform tidak dapat mengakses resource modul untuk komponen UI sistem, seperti notifikasi. Jika Anda perlu segera menggunakan resource tersebut, pertimbangkan untuk menyertakan resource tersebut dalam modul dasar aplikasi.

Mengaktifkan SplitCompat

Agar aplikasi dapat segera mengakses kode dan resource dari modul yang didownload, Anda harus mengaktifkan SplitCompat hanya dengan salah satu metode yang dijelaskan di bawah.

Setelah mengaktifkan SplitCompat untuk aplikasi, Anda juga perlu mengaktifkan SplitCompat untuk setiap aktivitas dalam modul dinamis yang Anda ingin agar aplikasi memiliki akses langsung.

Mendeklarasikan SplitCompatApplication dalam manifes

Cara termudah untuk mengaktifkan SplitCompat adalah dengan mendeklarasikan SplitCompatApplication sebagai subclass Application dalam manifes aplikasi Anda, seperti yang ditunjukkan di bawah:

<application
        ...
        android:name="com.google.android.play.core.splitcompat.SplitCompatApplication">
    </application>
    

Setelah aplikasi terinstal di perangkat, Anda dapat mengakses kode dan resource dari modul fitur dinamis yang didownload secara otomatis.

Memanggil SplitCompat pada waktu proses

Anda juga dapat mengaktifkan SplitCompat dalam aktivitas atau layanan tertentu pada waktu proses. Mengaktifkan SplitCompat dengan cara ini diperlukan untuk meluncurkan aktivitas yang disertakan dalam modul fitur segera setelah penginstalan modul. Untuk melakukannya, ganti attachBaseContext seperti yang ditunjukkan di bawah ini.

Jika Anda memiliki class Application kustom, Anda tidak perlu memperluas SplitCompatApplication untuk dapat mengaktifkan SplitCompat untuk aplikasi Anda, seperti yang ditunjukkan di bawah ini:

Kotlin

    class MyApplication : SplitCompatApplication() {
        ...
    }
    

Java

    public class MyApplication extends SplitCompatApplication {
        ...
    }
    

SplitCompatApplication hanya mengganti ContextWrapper.attachBaseContext() untuk menyertakan SplitCompat.install(Context applicationContext). Jika tidak ingin class Application memperluas SplitCompatApplication, Anda dapat mengganti metode attachBaseContext() secara manual, seperti berikut:

Kotlin

    override fun attachBaseContext(base: Context) {
        super.attachBaseContext(base)
        // Emulates installation of future on demand modules using SplitCompat.
        SplitCompat.install(this)
    }
    

Java

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        // Emulates installation of future on demand modules using SplitCompat.
        SplitCompat.install(this);
    }
    

Jika modul on demand Anda kompatibel dengan aplikasi instan dan aplikasi yang terinstal, Anda dapat memanggil SplitCompat secara kondisional, seperti berikut:

Kotlin

    override fun attachBaseContext(base: Context) {
        super.attachBaseContext(base)
        if (!InstantApps.isInstantApp(this)) {
            SplitCompat.install(this)
        }
    }
    

Java

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        if (!InstantApps.isInstantApp(this)) {
            SplitCompat.install(this);
        }
    }
    

Mengaktifkan SplitCompat untuk aktivitas modul

Setelah mengaktifkan SplitCompat untuk aplikasi dasar, Anda harus mengaktifkan SplitCompat untuk setiap aktivitas yang didownload aplikasi Anda dalam modul fitur dinamis. Untuk melakukannya, gunakan metode SplitCompat.installActivity(), seperti berikut:

Kotlin

    override fun attachBaseContext(base: Context) {
        super.attachBaseContext(base)
        // Emulates installation of on demand modules using SplitCompat.
        SplitCompat.installActivity(this)
    }
    

Java

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        // Emulates installation of on demand modules using SplitCompat.
        SplitCompat.installActivity(this);
    }
    

Mengakses kode dan resource dari modul yang terinstal

Selama Anda mengaktifkan SplitCompat untuk konteks aplikasi dasar dan aktivitas dalam modul fitur dinamis, setelah permintaan untuk modul on demand dilaporkan sebagai INSTALLED, Anda dapat mulai menggunakan kode dan resource-nya seolah-olah merupakan bagian dari APK dasar.

Jika Anda ingin mengakses aset atau resource yang ada dalam modul yang baru diinstal dari modul aplikasi terinstal lain, Anda harus melakukannya menggunakan konteks aplikasi. Konteks komponen yang mencoba mengakses resource belum akan diperbarui. Atau, Anda dapat membuat ulang komponen tersebut atau menginstal SplitCompat setelah modul dinamis terinstal.

Selain itu, jangan simpan cache objek ApplicationInfo android, kontennya, atau objek yang memuatnya dalam aplikasi Anda. Sebaiknya selalu ambil objek ini sesuai kebutuhan dari konteks aplikasi. Menyimpan cache objek semacam itu dapat menyebabkan aplikasi tidak bekerja saat menginstal pemisah pada versi Android yang lebih baru.

Mengakses Aplikasi Instan Android yang terinstal

Setelah modul Aplikasi Instan Android dilaporkan sebagai INSTALLED, Anda dapat mengakses kode dan resource-nya menggunakan Konteks aplikasi yang dimuat ulang. Konteks yang dibuat aplikasi Anda sebelum menginstal modul (misalnya, yang telah tersimpan dalam variabel) tidak berisi konten modul baru. Namun, konteks yang benar-benar baru berisi modul baru—hal ini dapat diperoleh, misalnya, menggunakan createPackageContext.

Kotlin

    // Generate a new context as soon as a request for a new module
    // reports as INSTALLED.
    override fun onStateUpdate(state: SplitInstallSessionState ) {
        if (state.sessionId() == mySessionId) {
            when (state.status()) {
                ...
                SplitInstallSessionStatus.INSTALLED -> {
                    val newContext = context.createPackageContext(context.packageName, 0)
                    // If you use AssetManager to access your app’s raw asset files, you’ll need
                    // to generate a new AssetManager instance from the updated context.
                    val am = newContext.assets
                }
            }
        }
    }
    

Java

    // Generate a new context as soon as a request for a new module
    // reports as INSTALLED.
    @Override
    public void onStateUpdate(SplitInstallSessionState state) {
        if (state.sessionId() == mySessionId) {
            switch (state.status()) {
                ...
                case SplitInstallSessionStatus.INSTALLED:
                    Context newContext = context.createPackageContext(context.getPackageName(), 0);
                    // If you use AssetManager to access your app’s raw asset files, you’ll need
                    // to generate a new AssetManager instance from the updated context.
                    AssetManager am = newContext.getAssets();
            }
        }
    }
    

Aplikasi Instan Android di Android 8.0 dan yang lebih tinggi

Saat meminta modul on demand untuk Aplikasi Instan Android di Android 8.0 (API level 26) dan yang lebih tinggi, setelah permintaan penginstalan dilaporkan sebagai INSTALLED, Anda perlu mengupdate aplikasi dengan konteks modul baru melalui panggilan ke SplitInstallHelper.updateAppInfo(Context context). Jika tidak, aplikasi tidak akan mengetahui kode dan resource modul. Setelah mengupdate metadata aplikasi, Anda harus memuat konten modul selama peristiwa thread utama berikutnya dengan memanggil Handler baru, seperti yang ditunjukkan di bawah:

Kotlin

    override fun onStateUpdate(state: SplitInstallSessionState ) {
        if (state.sessionId() == mySessionId) {
            when (state.status()) {
                ...
                SplitInstallSessionStatus.INSTALLED -> {
                    // You need to perform the following only for Android Instant Apps
                    // running on Android 8.0 (API level 26) and higher.
                    if (BuildCompat.isAtLeastO()) {
                        // Updates the app’s context with the code and resources of the
                        // installed module.
                        SplitInstallHelper.updateAppInfo(context)
                        Handler().post {
                            // Loads contents from the module using AssetManager
                            val am = context.assets
                            ...
                        }
                    }
                }
            }
        }
    }
    

Java

    @Override
    public void onStateUpdate(SplitInstallSessionState state) {
        if (state.sessionId() == mySessionId) {
            switch (state.status()) {
                ...
                case SplitInstallSessionStatus.INSTALLED:
                // You need to perform the following only for Android Instant Apps
                // running on Android 8.0 (API level 26) and higher.
                if (BuildCompat.isAtLeastO()) {
                    // Updates the app’s context with the code and resources of the
                    // installed module.
                    SplitInstallHelper.updateAppInfo(context);
                    new Handler().post(new Runnable() {
                        @Override public void run() {
                            // Loads contents from the module using AssetManager
                            AssetManager am = context.getAssets();
                            ...
                        }
                    });
                }
            }
        }
    }
    

Memuat library C/C++

Jika Anda ingin memuat library C/C++ dari modul yang telah didownload oleh perangkat, gunakan SplitInstallHelper.loadLibrary(Context context, String libName), seperti yang ditunjukkan di bawah ini:

Kotlin

    override fun onStateUpdate(state: SplitInstallSessionState) {
        if (state.sessionId() == mySessionId) {
            when (state.status()) {
                SplitInstallSessionStatus.INSTALLED -> {
                    // Updates the app’s context as soon as a module is installed.
                    val newContext = context.createPackageContext(context.packageName, 0)
                    // To load C/C++ libraries from an installed module, use the following API
                    // instead of System.load().
                    SplitInstallHelper.loadLibrary(newContext, “my-cpp-lib”)
                    ...
                }
            }
        }
    }
    

Java

    public void onStateUpdate(SplitInstallSessionState state) {
        if (state.sessionId() == mySessionId) {
            switch (state.status()) {
                case SplitInstallSessionStatus.INSTALLED:
                    // Updates the app’s context as soon as a module is installed.
                    Context newContext = context.createPackageContext(context.getPackageName(), 0);
                    // To load C/C++ libraries from an installed module, use the following API
                    // instead of System.load().
                    SplitInstallHelper.loadLibrary(newContext, “my-cpp-lib”);
                    ...
            }
        }
    }
    

Mengelola modul yang terinstal

Untuk memeriksa modul fitur dinamis yang saat ini terinstal pada perangkat, Anda dapat memanggil SplitInstallManager.getInstalledModules(), yang menampilkan Set<String> dari nama modul yang terinstal, seperti yang ditampilkan di bawah ini.

Kotlin

    val installedModules: Set<String> = splitInstallManager.installedModules
    

Java

    Set<String> installedModules = splitInstallManager.getInstalledModules();
    

Meng-uninstal modul

Anda dapat meminta perangkat untuk meng-uninstal modul dengan memanggil SplitInstallManager.deferredUninstall(List<String> moduleNames), seperti yang ditunjukkan di bawah ini.

Kotlin

    // Specifies two dynamic feature modules for deferred uninstall.
    splitInstallManager.deferredUninstall(listOf("pictureMessages", "promotionalFilters"))
    

Java

    // Specifies two dynamic feature modules for deferred uninstall.
    splitInstallManager.deferredUninstall(Arrays.asList("pictureMessages", "promotionalFilters"));
    

Proses uninstal modul tidak terjadi secara langsung. Artinya, perangkat meng-uninstalnya di latar belakang sesuai kebutuhan untuk menghemat ruang penyimpanan. Anda dapat mengonfirmasi bahwa perangkat telah menghapus modul dengan memanggil SplitInstallManager.getInstalledModules() dan memeriksa hasilnya, seperti yang dijelaskan di bagian sebelumnya.

Mendownload resource bahasa tambahan

Melalui Pengiriman Dinamis, perangkat hanya mendownload kode dan resource yang diperlukan untuk menjalankan aplikasi Anda. Jadi, untuk resource bahasa, perangkat pengguna hanya mendownload resource bahasa aplikasi Anda yang cocok dengan satu atau beberapa bahasa yang saat ini dipilih di setelan perangkat.

Jika ingin aplikasi memiliki akses ke resource bahasa tambahan—misalnya, untuk mengimplementasikan alat pilih bahasa dalam aplikasi, Anda dapat menggunakan Library Play Core untuk mendownloadnya secara on demand. Prosesnya mirip dengan mendownload modul fitur dinamis, seperti yang ditunjukkan di bawah ini.

Kotlin

    // Captures the user’s preferred language and persists it
    // through the app’s SharedPreferences.
    sharedPrefs.edit().putString(LANGUAGE_SELECTION, "fr").apply()
    ...

    // Creates a request to download and install additional language resources.
    val request = SplitInstallRequest.newBuilder()
            // Uses the addLanguage() method to include French language resources in the request.
            // Note that country codes are ignored. That is, if your app
            // includes resources for “fr-FR” and “fr-CA”, resources for both
            // country codes are downloaded when requesting resources for "fr".
            .addLanguage(Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)))
            .build()

    // Submits the request to install the additional language resources.
    splitInstallManager.startInstall(request)
    

Java

    // Captures the user’s preferred language and persists it
    // through the app’s SharedPreferences.
    sharedPrefs.edit().putString(LANGUAGE_SELECTION, "fr").apply();
    ...

    // Creates a request to download and install additional language resources.
    SplitInstallRequest request =
        SplitInstallRequest.newBuilder()
            // Uses the addLanguage() method to include French language resources in the request.
            // Note that country codes are ignored. That is, if your app
            // includes resources for “fr-FR” and “fr-CA”, resources for both
            // country codes are downloaded when requesting resources for "fr".
            .addLanguage(Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)))
            .build();

    // Submits the request to install the additional language resources.
    splitInstallManager.startInstall(request);
    

Permintaan ditangani sama seperti permintaan untuk modul fitur dinamis. Artinya, Anda dapat memantau status permintaan seperti yang biasa Anda lakukan.

Jika aplikasi Anda tidak memerlukan resource bahasa tambahan dengan segera, Anda dapat menunda penginstalan saat aplikasi berada di latar belakang, seperti yang ditunjukkan di bawah ini.

Kotlin

    splitInstallManager.deferredLanguageInstall(
        Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)))
    

Java

    splitInstallManager.deferredLanguageInstall(
        Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)));
    

Mengakses resource bahasa yang didownload

Untuk mendapatkan akses langsung ke resource bahasa yang didownload, aplikasi Anda harus menjalankan metode SplitCompat.installActivity() dalam metode attachBaseContext() dari setiap aktivitas yang memerlukan akses ke resource tersebut, seperti yang ditunjukkan di bawah ini.

Kotlin

    override fun attachBaseContext(base: Context) {
      super.attachBaseContext(base)
      SplitCompat.installActivity(this)
    }
    

Java

    @Override
    protected void attachBaseContext(Context base) {
      super.attachBaseContext(base);
      SplitCompat.installActivity(this);
    }
    

Untuk setiap aktivitas yang Anda ingin untuk menggunakan resource bahasa yang telah didownload oleh aplikasi Anda, perbarui konteks dasarnya dan tetapkan lokal baru melalui Configuration:

Kotlin

    override fun attachBaseContext(base: Context) {
      val configuration = Configuration()
      configuration.setLocale(Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)))
      val context = base.createConfigurationContext(configuration)
      super.attachBaseContext(context)
      SplitCompat.install(this)
    }
    

Java

    @Override
    protected void attachBaseContext(Context base) {
      Configuration configuration = new Configuration();
      configuration.setLocale(Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)));
      Context context = base.createConfigurationContext(configuration);
      super.attachBaseContext(context);
      SplitCompat.install(this);
    }
    

Agar dapat perubahan ini dapat berpengaruh, Anda harus membuat ulang aktivitas setelah bahasa baru diinstal dan siap digunakan. Anda dapat menggunakan metode Activity#recreate().

Kotlin

    when (state.status()) {
      SplitInstallSessionStatus.INSTALLED -> {
          // Recreates the activity to load resources for the new language
          // preference.
          activity.recreate()
      }
      ...
    }
    

Java

    switch (state.status()) {
      case SplitInstallSessionStatus.INSTALLED:
          // Recreates the activity to load resources for the new language
          // preference.
          activity.recreate();
      ...
    }
    

Meng-uninstal resource bahasa tambahan

Seperti halnya modul fitur dinamis, Anda dapat meng-uninstal resource tambahan kapan saja. Sebelum meminta uninstal, Anda mungkin perlu menentukan bahasa yang terinstal saat ini, seperti berikut.

Kotlin

    val installedLanguages: Set<String> = splitInstallManager.installedLanguages
    

Java

    Set<String> installedLanguages = splitInstallManager.getInstalledLanguages();
    

Kemudian Anda dapat menentukan bahasa yang ingin di-uninstal menggunakan metode deferredLanguageUninstall(), seperti yang ditunjukkan di bawah ini.

Kotlin

    splitInstallManager.deferredLanguageUninstall(
        Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)))
    

Java

    splitInstallManager.deferredLanguageUninstall(
        Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)));
    

Referensi lainnya

Untuk mempelajari penggunaan Library Play Core lebih lanjut, coba referensi berikut.

Contoh

  • Contoh PlayCore API, menunjukkan penggunaan PlayCore API untuk meminta dan mendownload fitur-fitur dinamis.
  • Contoh pemuatan kode dinamis, yang menunjukkan tiga pendekatan berbeda untuk mengakses kode dengan aman dari modul fitur dinamis yang diinstal.

Codelab

  • Modul on demand, yang membantu Anda membuat aplkasi yang mendownload dan menginstal fitur dinamis on demand.

Postingan blog

Video