Özellik modülleri, belirli özellikleri ve kaynakları uygulamanızın temel modülünden ayırıp uygulama paketinize dahil etmenize olanak tanır. Play Feature Delivery sayesinde kullanıcılar, örneğin uygulamanızın temel APK'sını yükledikten sonra bu bileşenleri daha sonra istek üzerine indirip yükleyebilirler.
Örneğin, resim mesajı çekme ve gönderme işlevi içeren bir kısa mesaj uygulaması olduğunu düşünelim. Ancak kullanıcıların yalnızca küçük bir yüzdesi resim mesajı gönderiyor. Resim mesajlaşmayı indirilebilir bir özellik modülü olarak eklemek mantıklı olabilir. Bu sayede, tüm kullanıcılar için ilk uygulama indirme işlemi daha küçük olur ve yalnızca resim mesajı gönderen kullanıcıların bu ek bileşeni indirmesi gerekir.
Bu tür bir modülerleştirmenin daha fazla çaba gerektirdiğini ve uygulamanızın mevcut kodunun yeniden düzenlenmesini gerektirebileceğini unutmayın. Bu nedenle, uygulamanızın hangi özelliklerinin kullanıcılara talep üzerine sunulmaktan en çok fayda sağlayacağını dikkatlice değerlendirin. İsteğe bağlı özelliklerle ilgili en iyi kullanım alanlarını ve kuralları daha iyi anlamak için İsteğe bağlı sunum için kullanıcı deneyimi ile ilgili en iyi uygulamalar başlıklı makaleyi inceleyin.
İsteğe bağlı yayınlama gibi gelişmiş yayınlama seçeneklerini etkinleştirmeden uygulama özelliklerini zaman içinde kademeli olarak modüler hale getirmek istiyorsanız bunun yerine yükleme sırasında yayınlamayı yapılandırın.
Bu sayfa, uygulama projenize özellik modülü eklemenize ve isteğe bağlı teslimat için yapılandırmanıza yardımcı olur. Başlamadan önce Android Studio 3.5 veya sonraki bir sürümü ve Android Gradle eklentisi 3.5.0 veya sonraki bir sürümü kullandığınızdan emin olun.
Talep üzerine teslimat için yeni bir modül yapılandırma
Yeni bir özellik modülü oluşturmanın en kolay yolu Android Studio 3.5 veya sonraki sürümleri kullanmaktır. Özellik modülleri yapıları gereği temel uygulama modülüne bağımlı olduklarından yalnızca mevcut uygulama projelerine eklenebilirler.
Android Studio'yu kullanarak uygulama projenize bir özellik modülü eklemek için aşağıdaki adımları uygulayın:
- Henüz yapmadıysanız uygulama projenizi IDE'de açın.
- Menü çubuğundan Dosya > Yeni > Yeni Modül'ü seçin.
- Create New Module (Yeni Modül Oluştur) iletişim kutusunda Dynamic Feature Module'ü (Dinamik Özellik Modülü) seçip Next'i (İleri) tıklayın.
- Yeni modülünüzü yapılandırın bölümünde aşağıdakileri tamamlayın:
- Açılır menüden uygulama projeniz için Base application module'ü seçin.
- Modül adı belirtin. IDE, Gradle ayarları dosyanızda modülü bir Gradle alt projesi olarak tanımlamak için bu adı kullanır. Uygulama paketinizi oluşturduğunuzda Gradle,
<manifest split>
özelliğini özellik modülünün manifestine yerleştirmek için alt proje adının son öğesini kullanır. - Modülün paket adını belirtin. Android Studio, varsayılan olarak temel modülün kök paket adını ve önceki adımda belirttiğiniz modül adını birleştiren bir paket adı önerir.
- Modülün desteklemesini istediğiniz minimum API düzeyini seçin. Bu değer, temel modülün değeriyle eşleşmelidir.
- İleri'yi tıklayın.
Modül İndirme Seçenekleri bölümünde aşağıdakileri tamamlayın:
En fazla 50 karakter kullanarak Modül başlığını belirtin. Platform, örneğin kullanıcının modülü indirmek isteyip istemediğini onaylarken modülü kullanıcılara tanımlamak için bu başlığı kullanır. Bu nedenle, uygulamanızın temel modülü, çevirebileceğiniz bir dize kaynağı olarak modül başlığını içermelidir. Android Studio'yu kullanarak modülü oluşturduğunuzda IDE, dize kaynağını sizin için temel modüle ekler ve özellik modülünün manifestine aşağıdaki girişi yerleştirir:
<dist:module ... dist:title="@string/feature_title"> </dist:module>
Yükleme zamanında dahil etme bölümündeki açılır menüden Modülü yükleme zamanında dahil etme'yi seçin. Android Studio, seçiminizi yansıtmak için modülün manifest dosyasına aşağıdakileri ekler:
<dist:module ... > <dist:delivery> <dist:on-demand/> </dist:delivery> </dist:module>
Bu modülün Android 4.4 (API düzeyi 20) ve önceki sürümlerin yüklü olduğu cihazlarda kullanılabilmesini ve çoklu APK'lara dahil edilmesini istiyorsanız Fusing'in yanındaki kutuyu işaretleyin. Bu sayede, bu modül için isteğe bağlı davranışı etkinleştirebilir ve birleştirme işlemini devre dışı bırakarak bölünmüş APK'ların indirilmesini ve yüklenmesini desteklemeyen cihazlardan kaldırabilirsiniz. Android Studio, seçiminizi yansıtmak için modülün manifest dosyasına aşağıdakileri ekler:
<dist:module ...> <dist:fusing dist:include="true | false" /> </dist:module>
Son'u tıklayın.
Android Studio modülünüzü oluşturmayı tamamladıktan sonra Project (Proje) bölmesinden içeriğini kendiniz inceleyin (menü çubuğundan View > Tool Windows > Project'i (Görünüm > Araç Pencereleri > Proje) seçin). Varsayılan kod, kaynaklar ve düzen, standart uygulama modülündekilere benzer olmalıdır.
Ardından, Play Feature Delivery kitaplığını kullanarak isteğe bağlı yükleme işlevini uygulamanız gerekir.
Play Feature Delivery Kitaplığı'nı projenize dahil etme
Başlamadan önce projenize Play Feature Delivery Library'yi eklemeniz gerekir.
İsteğe bağlı modül isteğinde bulunma
Uygulamanızın bir özellik modülünü kullanması gerektiğinde, SplitInstallManager
sınıfı aracılığıyla ön plandayken modül isteğinde bulunabilir. Uygulamanız, istekte bulunurken hedef modülün manifest dosyasındaki split
öğesi tarafından tanımlanan modülün adını belirtmelidir. Android Studio'yu kullanarak bir özellik modülü oluşturduğunuzda derleme sistemi, bu özelliği derleme zamanında modülün manifest dosyasına yerleştirmek için sağladığınız Modül adını kullanır.
Daha fazla bilgi için özellik modülü manifestleri hakkında bilgi edinin.
Örneğin, cihazın kamerasını kullanarak resim mesajları yakalayıp göndermek için isteğe bağlı bir modülü olan bir uygulamayı ele alalım. Bu isteğe bağlı modül, manifestinde split="pictureMessages"
belirtiyor. Aşağıdaki örnekte, SplitInstallManager
kullanılarak pictureMessages
modülü (bazı promosyon filtreleri için ek bir modülle birlikte) isteniyor:
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 -> { ... });
Uygulamanız isteğe bağlı bir modül talep ettiğinde Play Feature Delivery Kitaplığı "gönder ve unut" stratejisini kullanır. Yani, modülü indirme isteğini platforma gönderir ancak yüklemenin başarılı olup olmadığını izlemez. Yüklemeden sonra kullanıcı yolculuğunu ilerletmek veya hataları sorunsuz bir şekilde ele almak için istek durumunu izlediğinizden emin olun.
Not: Cihazda zaten yüklü olan bir özellik modülü istenebilir. API, modülün zaten yüklü olduğunu algılarsa isteği anında tamamlanmış olarak kabul eder. Ayrıca, bir modül yüklendikten sonra Google Play bu modülü otomatik olarak güncel tutar. Yani uygulama paketinizin yeni bir sürümünü yüklediğinizde platform, uygulamanıza ait tüm yüklü APK'ları günceller. Daha fazla bilgi için Uygulama güncellemelerini yönetme başlıklı makaleyi inceleyin.
Modülün koduna ve kaynaklarına erişebilmek için uygulamanızın SplitCompat'i etkinleştirmesi gerekir. SplitCompat'in Android hazır uygulamaları için gerekli olmadığını unutmayın.
İsteğe bağlı modüllerin yüklenmesini erteleme
Uygulamanızın isteğe bağlı bir modülü hemen indirip yüklemesi gerekmiyorsa, yükleme işlemini uygulama arka plandayken gerçekleştirilecek şekilde erteleyebilirsiniz. Örneğin, uygulamanızın daha sonra yapılacak lansmanı için birtakım tanıtım malzemelerini önceden yüklemek isteyebilirsiniz.
Aşağıda gösterildiği gibi deferredInstall()
yöntemini kullanarak daha sonra indirilecek bir modül belirtebilirsiniz. Ayrıca, SplitInstallManager.startInstall()
'dan farklı olarak, uygulamanızın ertelenmiş yükleme isteği başlatmak için ön planda olması gerekmez.
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"));
Ertelenmiş yükleme istekleri en iyi çabayla işlenir ve ilerleme durumları izlenemez. Bu nedenle, ertelenmiş yükleme için belirttiğiniz bir modüle erişmeye çalışmadan önce modülün yüklendiğinden emin olmanız gerekir. Modülün hemen kullanılabilir olması gerekiyorsa önceki bölümde gösterildiği gibi SplitInstallManager.startInstall()
kullanarak isteğinizi gönderin.
İstek durumunu izleme
Bir ilerleme çubuğunu güncelleyebilmek, yükleme işleminden sonra bir amaç başlatabilmek veya istek hatasını sorunsuz bir şekilde işleyebilmek için eşzamansız SplitInstallManager.startInstall()
görevinden gelen durum güncellemelerini dinlemeniz gerekir.
Yükleme isteğinizle ilgili güncellemeleri almaya başlamadan önce bir dinleyici kaydedin ve istek için oturum kimliğini alın.
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);
İstek hatalarını işleme
Özellik modüllerinin isteğe bağlı olarak yüklenmesinin bazen başarısız olabileceğini unutmayın. Uygulama yükleme işlemi de her zaman başarılı olmaz. Yükleme başarısızlığı; cihazda yeterli depolama alanı olmaması, ağ bağlantısının olmaması veya kullanıcının Google Play Store'da oturum açmamış olması gibi sorunlardan kaynaklanabilir. Bu durumları kullanıcı açısından sorunsuz bir şekilde ele alma önerileri için talep üzerine teslimatla ilgili kullanıcı deneyimi yönergelerimize göz atın.
Kod açısından, aşağıdaki örnekte gösterildiği gibi addOnFailureListener()
kullanarak bir modülün indirilmesi veya yüklenmesiyle ilgili hataları ele almanız gerekir:
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. } } } }); }
Aşağıdaki tabloda, uygulamanızın ele alması gerekebilecek hata durumları açıklanmaktadır:
Hata kodu | Açıklama | Önerilen işlem |
---|---|---|
ACTIVE_SESSIONS_LIMIT_EXCEEDED | Şu anda indirilen en az bir istek olduğundan istek reddedildi. | Yukarıdaki örnekte gösterildiği gibi, hâlâ indirilen isteklerin olup olmadığını kontrol edin. |
MODULE_UNAVAILABLE | Google Play, uygulamanın, cihazın ve kullanıcının Google Play hesabının yüklü sürümüne göre istenen modülü bulamıyor. | Kullanıcının modüle erişimi yoksa kullanıcıyı bilgilendirin. |
INVALID_REQUEST | Google Play isteği aldı ancak istek geçerli değil. | İstekte yer alan bilgilerin eksiksiz ve doğru olduğunu doğrulayın. |
SESSION_NOT_FOUND | Belirli bir oturum kimliği için oturum bulunamadı. | Bir isteğin durumunu oturum kimliğine göre izlemeye çalışıyorsanız oturum kimliğinin doğru olduğundan emin olun. |
API_NOT_AVAILABLE | Play Feature Delivery Library, mevcut cihazda desteklenmiyor. Yani cihaz, isteğe bağlı özellikleri indirip yükleyemez. | Android 4.4 (API seviyesi 20) veya daha eski sürümleri çalıştıran cihazlarda, dist:fusing manifest özelliğini kullanarak yükleme sırasında özellik modüllerini eklemeniz gerekir. Daha fazla bilgi edinmek için özellik modülü manifestosu hakkında bilgi edinin.
|
NETWORK_ERROR | Bir ağ hatası nedeniyle istek başarısız oldu. | Kullanıcıdan ağ bağlantısı oluşturmasını veya farklı bir ağa geçmesini isteyin. |
ACCESS_DENIED | Uygulama, yetersiz izinler nedeniyle isteği kaydedemiyor. | Bu durum genellikle uygulama arka plandayken ortaya çıkar. Uygulama ön plana döndüğünde isteği tekrar deneyin. |
INCOMPATIBLE_WITH_EXISTING_SESSION | İstek, daha önce istenmiş ancak henüz yüklenmemiş bir veya daha fazla modül içeriyor. | Uygulamanızın daha önce istediği modülleri içermeyen yeni bir istek oluşturun veya isteği yeniden denemeden önce şu anda istenen tüm modüllerin yüklenmesinin tamamlanmasını bekleyin.
Daha önce yüklenmiş bir modülün istenmesinin hataya neden olmadığını unutmayın. |
SERVICE_DIED | İsteği işlemekten sorumlu hizmet sonlandırıldı. | İsteği yeniden deneyin.
|
INSUFFICIENT_STORAGE | Cihazda, özellik modülünü yüklemek için yeterli boş depolama alanı yok. | Kullanıcıya bu özelliği yüklemek için yeterli depolama alanına sahip olmadığını bildirin. |
SPLITCOMPAT_VERIFICATION_ERROR, SPLITCOMPAT_EMULATION_ERROR, SPLITCOMPAT_COPY_ERROR | SplitCompat, özellik modülünü yükleyemedi. | Bu hatalar, bir sonraki uygulama yeniden başlatma işleminden sonra otomatik olarak çözülür. |
PLAY_STORE_NOT_FOUND | Play Store uygulaması cihaza yüklenmemiştir. | Kullanıcıya bu özelliği indirmek için Play Store uygulamasının gerekli olduğunu bildirin. |
APP_NOT_OWNED | Uygulama, Google Play tarafından yüklenmediği için özellik indirilemiyor. Bu hata yalnızca ertelenmiş yüklemelerde ortaya çıkabilir. | Kullanıcının uygulamayı Google Play'den edinmesini istiyorsanız gerekli kullanıcı onayını alabilen startInstall() öğesini kullanın. |
INTERNAL_ERROR | Play Store'da dahili bir hata oluştu. | İsteği yeniden deneyin. |
Kullanıcı, isteğe bağlı bir modülün indirilmesini isterse ve bir hata oluşursa kullanıcıya iki seçenek sunan bir iletişim kutusu göstermeyi düşünebilirsiniz: Tekrar dene (isteği tekrar dener) ve İptal (isteği bırakır). Ek destek için kullanıcıları Google Play Yardım Merkezi'ne yönlendiren bir Yardım bağlantısı da sağlamanız gerekir.
Durum güncellemelerini işleme
Bir dinleyiciyi kaydettikten ve isteğinizin oturum kimliğini kaydettikten sonra,
durum değişikliklerini işlemek için StateUpdatedListener.onStateUpdate()
kullanın.
Kotlin
override fun onStateUpdate(state : SplitInstallSessionState) { if (state.status() == SplitInstallSessionStatus.FAILED && state.errorCode() == SplitInstallErrorCode.SERVICE_DIED) { // 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. } } }
Yükleme isteğinizin olası durumları aşağıdaki tabloda açıklanmıştır.
İstek durumu | Açıklama | Önerilen işlem |
---|---|---|
BEKLEMEDE | İstek kabul edildi ve indirme işlemi kısa süre içinde başlayacak. | İndirme işlemiyle ilgili kullanıcı geri bildirimi sağlamak için ilerleme çubuğu gibi kullanıcı arayüzü bileşenlerini başlatın. |
REQUIRES_USER_CONFIRMATION | İndirme için kullanıcı onayı gerekiyor. Bu durum en sık olarak uygulamanın Google Play üzerinden yüklenmemesi halinde görülür. | Kullanıcıdan, Google Play üzerinden özellik indirme işlemini onaylamasını isteyin. Daha fazla bilgi için kullanıcı onayı alma ile ilgili bölüme gidin. |
İNDİRME | İndirme işlemi devam ediyor. | İndirme işlemi için ilerleme çubuğu sağlıyorsanız kullanıcı arayüzünü güncellemek üzere SplitInstallSessionState.bytesDownloaded() ve SplitInstallSessionState.totalBytesToDownload() yöntemlerini kullanın (bu tablonun üzerindeki kod örneğine bakın). |
İNDİRİLENLER | Cihaz modülü indirmiş ancak kurulum henüz başlamamıştır. | Uygulamaların, indirilen modüllere erişebilmesi ve bu durumu görmemesi için SplitCompat'i etkinleştirmesi gerekir. Özellik modülünün koduna ve kaynaklarına erişmek için bu gereklidir. |
YÜKLENİYOR | Cihaz şu anda modülü yüklüyor. | İlerleme çubuğunu güncelleyin. Bu durum genellikle kısa sürer. |
YÜKLENDİ | Modül cihaza yüklenir. | Kullanıcı yolculuğuna devam etmek için modüldeki erişim koduna ve kaynağa
erişin.
Modül, Android 8.0 (API düzeyi 26) veya sonraki sürümlerde çalışan bir Android Anında Uygulaması içinse |
SIÇTI | İstek, modül cihaza yüklenmeden önce başarısız oldu. | Kullanıcıdan isteği yeniden denemesini veya iptal etmesini isteyin. |
İPTAL ETME | Cihaz, isteği iptal etme sürecindedir. | Daha fazla bilgi edinmek için yükleme isteğini iptal etme ile ilgili bölüme gidin. |
İPTAL EDİLDİ | İstek iptal edildi. |
Kullanıcı onayı alma
Bazı durumlarda Google Play, indirme isteğini karşılamadan önce kullanıcı onayı isteyebilir. Örneğin, uygulamanız Google Play tarafından yüklenmemişse veya mobil veri üzerinden büyük bir indirme işlemi yapmaya çalışıyorsanız. Bu gibi durumlarda, istek durumu REQUIRES_USER_CONFIRMATION
olarak bildirilir ve cihazın istekteki modülleri indirip yükleyebilmesi için uygulamanızın kullanıcı onayı alması gerekir. Onay almak için uygulamanız kullanıcıya aşağıdaki istemi göstermelidir:
Kotlin
override fun onSessionStateUpdate(state: SplitInstallSessionState) { if (state.status() == SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION) { // Displays a confirmation for the user to confirm the request. splitInstallManager.startConfirmationDialogForResult( state, // an activity result launcher registered via registerForActivityResult activityResultLauncher) } ... }
Java
@Override void onSessionStateUpdate(SplitInstallSessionState state) { if (state.status() == SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION) { // Displays a confirmation for the user to confirm the request. splitInstallManager.startConfirmationDialogForResult( state, // an activity result launcher registered via registerForActivityResult activityResultLauncher); } ... }
Yerleşik ActivityResultContracts.StartIntentSenderForResult
sözleşmesini kullanarak bir etkinlik sonucu başlatıcı kaydedebilirsiniz. Activity Result APIs başlıklı makaleyi inceleyin.
İsteğin durumu, kullanıcı yanıtına bağlı olarak güncellenir:
- Kullanıcı onayı kabul ederse istek durumu
PENDING
olarak değişir ve indirme işlemi devam eder. - Kullanıcı onayı reddederse istek durumu
CANCELED
olarak değişir. - Kullanıcı, iletişim kutusu kapatılmadan önce seçim yapmazsa istek durumu
REQUIRES_USER_CONFIRMATION
olarak kalır. Uygulamanız, isteği tamamlaması için kullanıcıya tekrar istem gönderebilir.
Kullanıcının yanıtıyla geri arama almak için ActivityResultCallback'i aşağıda gösterildiği gibi geçersiz kılabilirsiniz.
Kotlin
registerForActivityResult(StartIntentSenderForResult()) { result: ActivityResult -> { // 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
registerForActivityResult( new ActivityResultContracts.StartIntentSenderForResult(), new ActivityResultCallback<ActivityResult>() { @Override public void onActivityResult(ActivityResult result) { // Handle the user's decision. For example, if the user selects "Cancel", // you may want to disable certain functionality that depends on the module. } });
Yükleme isteğini iptal etme
Uygulamanızın yüklenmeden önce bir isteği iptal etmesi gerekiyorsa aşağıdaki örnekte gösterildiği gibi isteğin oturum kimliğini kullanarak cancelInstall()
yöntemini çağırabilir.
Kotlin
splitInstallManager // Cancels the request for the given session ID. .cancelInstall(mySessionId)
Java
splitInstallManager // Cancels the request for the given session ID. .cancelInstall(mySessionId);
Modüllere erişme
İndirilen bir modüldeki kod ve kaynaklara erişmek için uygulamanızın, hem uygulamanız hem de uygulamanızın indirdiği özellik modüllerindeki her etkinlik için SplitCompat Kitaplığı'nı etkinleştirmesi gerekir.
Ancak, modülün indirilmesinden sonra bir süre (bazı durumlarda günler) boyunca platformda modül içeriklerine erişimle ilgili aşağıdaki kısıtlamalar olduğunu unutmayın:
- Platform, modül tarafından sunulan yeni manifest girişlerini uygulayamaz.
- Platform, bildirimler gibi sistem kullanıcı arayüzü bileşenleri için modülün kaynaklarına erişemiyor. Bu tür kaynakları hemen kullanmanız gerekiyorsa uygulamanızın temel modülüne eklemeyi düşünebilirsiniz.
SplitCompat'i etkinleştirme
Uygulamanızın indirilen bir modüldeki kod ve kaynaklara erişebilmesi için SplitCompat'i yalnızca aşağıdaki bölümlerde açıklanan yöntemlerden birini kullanarak etkinleştirmeniz gerekir.
Uygulamanız için SplitCompat'i etkinleştirdikten sonra, uygulamanızın erişmesini istediğiniz özellik modüllerindeki her etkinlik için de SplitCompat'i etkinleştirmeniz gerekir.
Manifest dosyasında SplitCompatApplication'ı beyan edin
SplitCompat'i etkinleştirmenin en basit yolu, aşağıdaki örnekte gösterildiği gibi uygulamanızın manifest dosyasında SplitCompatApplication
öğesini Application
alt sınıfı olarak bildirmektir:
<application
...
android:name="com.google.android.play.core.splitcompat.SplitCompatApplication">
</application>
Uygulama bir cihaza yüklendikten sonra, indirilen özellik modüllerindeki kod ve kaynaklara otomatik olarak erişebilirsiniz.
Çalışma zamanında SplitCompat'i çağırma
Ayrıca, SplitCompat'i çalışma zamanında belirli etkinliklerde veya hizmetlerde de etkinleştirebilirsiniz.
Bu şekilde SplitCompat'i etkinleştirmek, özellik modüllerinde yer alan etkinliklerin başlatılması için gereklidir. Bunu yapmak için aşağıda gösterildiği gibi attachBaseContext
değerini geçersiz kılın.
Özel bir Application sınıfınız varsa SplitCompat'i uygulamanızda etkinleştirmek için aşağıdaki örnekte gösterildiği gibi SplitCompatApplication
sınıfını genişletin:
Kotlin
class MyApplication : SplitCompatApplication() { ... }
Java
public class MyApplication extends SplitCompatApplication { ... }
SplitCompatApplication
, SplitCompat.install(Context applicationContext)
'yi dahil etmek için ContextWrapper.attachBaseContext()
'yi geçersiz kılar. Application
sınıfınızın SplitCompatApplication
genişletilmesini istemiyorsanız attachBaseContext()
yöntemini aşağıdaki gibi manuel olarak geçersiz kılabilirsiniz:
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); }
İsteğe bağlı modülünüz hem anlık uygulamalar hem de yüklü uygulamalarla uyumluysa SplitCompat'i aşağıdaki gibi koşullu olarak çağırabilirsiniz:
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); } }
Modül etkinlikleri için SplitCompat'i etkinleştirme
Temel uygulamanız için SplitCompat'i etkinleştirdikten sonra, uygulamanızın bir özellik modülünde indirdiği her etkinlik için SplitCompat'i etkinleştirmeniz gerekir. Bunu yapmak için aşağıdaki SplitCompat.installActivity()
yöntemini kullanın:
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); }
Özellik modüllerinde tanımlanan bileşenlere erişme
Özellik modülünde tanımlanan bir etkinliği başlatma
SplitCompat'i etkinleştirdikten sonra, özellik modüllerinde tanımlanan etkinlikleri startActivity()
kullanarak başlatabilirsiniz.
Kotlin
startActivity(Intent() .setClassName("com.package", "com.package.module.MyActivity") .setFlags(...))
Java
startActivity(new Intent() .setClassName("com.package", "com.package.module.MyActivity") .setFlags(...));
setClassName
işlevinin ilk parametresi uygulamanın paket adı, ikinci parametresi ise etkinliğin tam sınıf adıdır.
İsteğe bağlı olarak indirdiğiniz bir özellik modülünde etkinliğiniz olduğunda etkinlikte SplitCompat'i etkinleştirmeniz gerekir.
Özellik modülünde tanımlanan bir hizmeti başlatma
SplitCompat'i etkinleştirdikten sonra startService()
kullanarak özellik modüllerinde tanımlanan hizmetleri başlatabilirsiniz.
Kotlin
startService(Intent() .setClassName("com.package", "com.package.module.MyService") .setFlags(...))
Java
startService(new Intent() .setClassName("com.package", "com.package.module.MyService") .setFlags(...));
Bir özellik modülünde tanımlanan bileşeni dışa aktarma
Dışa aktarılan Android bileşenlerini isteğe bağlı modüllere dahil etmemelisiniz.
Derleme sistemi, tüm modüllerin manifest girişlerini temel modülde birleştirir; isteğe bağlı bir modül, dışa aktarılmış bir bileşen içeriyorsa modül yüklenmeden önce bile erişilebilir ve başka bir uygulamadan çağrıldığında eksik kod nedeniyle kilitlenmeye neden olabilir.
Bu, yalnızca uygulama tarafından erişilen dahili bileşenler için sorun teşkil etmez. Bu nedenle uygulama, bileşene erişmeden önce modülün yüklü olup olmadığını kontrol edebilir.
Dışa aktarılmış bir bileşene ihtiyacınız varsa ve içeriğinin isteğe bağlı bir modülde olmasını istiyorsanız proxy kalıbı uygulayabilirsiniz.
Bunu, tabana dışa aktarılmış bir proxy bileşeni ekleyerek yapabilirsiniz. Proxy bileşeni, erişildiğinde içeriği içeren modülün varlığını kontrol edebilir. Modül varsa proxy bileşeni, Intent
aracılığıyla modüldeki dahili bileşeni başlatabilir ve arayan uygulamadan gelen amaç bilgisini iletebilir. Modül yoksa bileşen, modülü indirebilir veya arayan uygulamaya uygun bir hata mesajı döndürebilir.
Yüklü modüllerden kod ve kaynaklara erişme
Temel uygulama bağlamınız ve özellik modülünüzdeki etkinlikler için SplitCompat'i etkinleştirirseniz, isteğe bağlı modül yüklendikten sonra özellik modülündeki kod ve kaynakları temel APK'nın bir parçasıymış gibi kullanabilirsiniz.
Farklı bir modüldeki koda erişme
Bir modülden temel koda erişme
Temel modülünüzün içindeki kod, diğer modüller tarafından doğrudan kullanılabilir. Herhangi bir özel işlem yapmanız gerekmez. İhtiyacınız olan sınıfları içe aktarıp kullanmanız yeterlidir.
Başka bir modülden modül koduna erişme
Bir modülün içindeki bir nesneye veya sınıfa başka bir modülden doğrudan statik olarak erişilemez ancak yansıtma kullanılarak dolaylı olarak erişilebilir.
Yansıtmanın performans maliyetleri nedeniyle bu durumun ne sıklıkta gerçekleştiğine dikkat etmeniz gerekir. Karmaşık kullanım alanlarında, uygulama ömrü boyunca tek bir yansıtma çağrısı yapılmasını sağlamak için Dagger 2 gibi bağımlılık ekleme çerçevelerini kullanın.
Nesne oluşturulduktan sonraki etkileşimleri basitleştirmek için temel modülde bir arayüz ve bu arayüzün işlev modülündeki uygulamasını tanımlamanız önerilir. Örneğin:
Kotlin
// In the base module interface MyInterface { fun hello(): String } // In the feature module object MyInterfaceImpl : MyInterface { override fun hello() = "Hello" } // In the base module, where we want to access the feature module code val stringFromModule = (Class.forName("com.package.module.MyInterfaceImpl") .kotlin.objectInstance as MyInterface).hello();
Java
// In the base module public interface MyInterface { String hello(); } // In the feature module public class MyInterfaceImpl implements MyInterface { @Override public String hello() { return "Hello"; } } // In the base module, where we want to access the feature module code String stringFromModule = ((MyInterface) Class.forName("com.package.module.MyInterfaceImpl").getConstructor().newInstance()).hello();
Farklı bir modüldeki kaynaklara ve öğelere erişme
Bir modül yüklendikten sonra, modüldeki kaynaklara ve öğelere standart şekilde erişebilirsiniz. Ancak iki uyarı vardır:
- Farklı bir modülden bir kaynağa erişiyorsanız modülün kaynak tanımlayıcıya erişimi olmaz ancak kaynağa adıyla erişilebilir. Kaynağa referans vermek için kullanılacak paketin, kaynağın tanımlandığı modülün paketi olduğunu unutmayın.
- Uygulamanızın farklı bir yüklü modülünden yeni yüklenen bir modüldeki öğelere veya kaynaklara erişmek istiyorsanız bunu uygulama bağlamını kullanarak yapmanız gerekir. Kaynaklara erişmeye çalışan bileşenin bağlamı henüz güncellenmeyecek. Alternatif olarak, özellik modülü yüklendikten sonra bu bileşeni yeniden oluşturabilir (ör. Activity.recreate() çağrısı yapma) veya SplitCompat'i yeniden yükleyebilirsiniz.
İsteğe bağlı yayın kullanarak bir uygulamaya yerel kod yükleme
Özellik modüllerinin isteğe bağlı teslimini kullanırken tüm yerel kitaplıklarınızı yüklemek için ReLinker'ı kullanmanızı öneririz. ReLinker, bir özellik modülü yüklendikten sonra yerel kitaplıkların yüklenmesiyle ilgili sorunu düzeltir. ReLinker hakkında daha fazla bilgiyi Android JNI İpuçları'nda bulabilirsiniz.
İsteğe bağlı bir modülden yerel kod yükleme
Bir bölünme yüklendikten sonra, yerel kodunun ReLinker aracılığıyla yüklenmesini öneririz. Anlık uygulamalar için bu özel yöntemi kullanmanız gerekir.
Yerel kodunuzu yüklemek için System.loadLibrary()
kullanıyorsanız ve yerel kitaplığınızın modüldeki başka bir kitaplığa bağımlılığı varsa önce bu diğer kitaplığı manuel olarak yüklemeniz gerekir.
ReLinker kullanıyorsanız eşdeğer işlem Relinker.recursively().loadLibrary()
olur.
İsteğe bağlı bir modülde tanımlanan bir kitaplığı yüklemek için yerel kodda dlopen()
kullanıyorsanız bu, göreli kitaplık yollarıyla çalışmaz.
En iyi çözüm, kitaplığın mutlak yolunu Java kodundan ClassLoader.findLibrary()
aracılığıyla alıp dlopen()
çağrınızda kullanmaktır.
Bu işlemi yerel kodu girmeden önce yapın veya yerel kodunuzdan Java'ya bir JNI çağrısı kullanın.
Yüklü Android Hazır Uygulamalarına erişme
Bir Android hazır uygulama modülü INSTALLED
olarak bildirildikten sonra, yenilenmiş bir uygulama Context kullanarak koduna ve kaynaklarına erişebilirsiniz. Uygulamanızın bir modül yüklenmeden önce oluşturduğu bir bağlam (örneğin, bir değişkende zaten depolanmış olan) yeni modülün içeriğini içermez. Ancak yeni bir bağlam bunu yapabilir. Yeni bağlamı örneğin createPackageContext
kullanarak elde edebilirsiniz.
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(); } } }
Android 8.0 ve sonraki sürümlerde Android Hazır Uygulamalar
Android 8.0 (API düzeyi 26) ve sonraki sürümlerdeki bir Android anlık uygulaması için isteğe bağlı modül isteğinde bulunurken yükleme isteği INSTALLED
olarak bildirildikten sonra, SplitInstallHelper.updateAppInfo(Context context)
çağrısı yaparak uygulamayı yeni modülün bağlamıyla güncellemeniz gerekir.
Aksi takdirde, uygulama henüz modülün kodunu ve kaynaklarını bilmiyordur. Uygulamanın meta verilerini güncelledikten sonra, modülün içeriklerini bir sonraki ana iş parçacığı etkinliği sırasında aşağıdaki örnekte gösterildiği gibi yeni bir Handler
çağırarak yüklemeniz gerekir:
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(); ... } }); } } } }
C/C++ kitaplıklarını yükleme
Cihazın hazır uygulamada daha önce indirdiği bir modülden C/C++ kitaplıklarını yüklemek istiyorsanız aşağıdaki gibi SplitInstallHelper.loadLibrary(Context context, String libName)
kullanın:
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”); ... } } }
Bilinen sınırlamalar
- İsteğe bağlı bir modüldeki kaynaklara veya öğelere erişen bir etkinlikte Android WebView kullanılamaz. Bunun nedeni, Android API düzeyi 28 ve önceki sürümlerde WebView ile SplitCompat arasındaki uyumsuzluktur.
- Uygulamanızda Android
ApplicationInfo
nesnelerini, içeriklerini veya bunları içeren nesneleri önbelleğe alamazsınız. Bu nesneleri her zaman gerektiğinde bir uygulama bağlamından getirmeniz gerekir. Bu tür nesnelerin önbelleğe alınması, bir özellik modülü yüklenirken uygulamanın çökmesine neden olabilir.
Yüklü modülleri yönetme
Cihazda şu anda hangi özellik modüllerinin yüklü olduğunu kontrol etmek için aşağıdaki örnekte gösterildiği gibi, yüklü modüllerin adlarının Set<String>
değerini döndüren SplitInstallManager.getInstalledModules()
işlevini çağırabilirsiniz.
Kotlin
val installedModules: Set<String> = splitInstallManager.installedModules
Java
Set<String> installedModules = splitInstallManager.getInstalledModules();
Modülleri kaldırma
Aşağıda gösterildiği gibi SplitInstallManager.deferredUninstall(List<String> moduleNames)
'ı çağırarak cihazın modülleri kaldırmasını isteyebilirsiniz.
Kotlin
// Specifies two feature modules for deferred uninstall. splitInstallManager.deferredUninstall(listOf("pictureMessages", "promotionalFilters"))
Java
// Specifies two feature modules for deferred uninstall. splitInstallManager.deferredUninstall(Arrays.asList("pictureMessages", "promotionalFilters"));
Modül yükleme kaldırma işlemleri hemen gerçekleşmez. Yani cihaz, depolama alanından tasarruf etmek için gerektiğinde bu uygulamaların yüklemesini arka planda kaldırır.
Önceki bölümde açıklandığı gibi SplitInstallManager.getInstalledModules()
öğesini çağırıp sonucu inceleyerek cihazın bir modülü sildiğini onaylayabilirsiniz.
Ek dil kaynaklarını indirme
Uygulama paketleri sayesinde cihazlar, uygulamanızı çalıştırmak için gereken kod ve kaynakları indirir. Bu nedenle, dil kaynakları için kullanıcının cihazı yalnızca cihaz ayarlarında seçili olan bir veya daha fazla dille eşleşen uygulama dil kaynaklarınızı indirir.
Uygulamanızın ek dil kaynaklarına erişmesini istiyorsanız (ör. uygulama içi dil seçici uygulamak için) Play Feature Delivery Kitaplığı'nı kullanarak bunları isteğe bağlı olarak indirebilirsiniz. Bu işlem, aşağıda gösterildiği gibi bir özellik modülünü indirmeye benzer.
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);
İstek, bir özellik modülü isteğiymiş gibi işlenir. Yani, istek durumunu normalde yaptığınız gibi izleyebilirsiniz.
Uygulamanızın ek dil kaynaklarına hemen ihtiyacı yoksa yükleme işlemini uygulama arka plandayken gerçekleştirilecek şekilde erteleyebilirsiniz (aşağıda gösterildiği gibi).
Kotlin
splitInstallManager.deferredLanguageInstall( Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)))
Java
splitInstallManager.deferredLanguageInstall( Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)));
İndirilen dil kaynaklarına erişme
İndirilen dil kaynaklarına erişmek için uygulamanızın, bu kaynaklara erişim gerektiren her etkinliğin attachBaseContext()
yöntemi içinde SplitCompat.installActivity()
yöntemini aşağıdaki örnekte gösterildiği gibi çalıştırması gerekir.
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); }
Uygulamanızın indirdiği dil kaynaklarını kullanmak istediğiniz her etkinlik için temel bağlamı güncelleyin ve Configuration
aracılığıyla yeni bir yerel ayar belirleyin:
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); }
Bu değişikliklerin geçerli olması için yeni dil yüklendikten ve kullanıma hazır hâle geldikten sonra etkinliğinizi yeniden oluşturmanız gerekir. Activity#recreate()
yöntemini kullanabilirsiniz.
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(); ... }
Ek dil kaynaklarını kaldırma
Özellik modüllerine benzer şekilde, ek kaynakları istediğiniz zaman kaldırabilirsiniz. Kaldırma isteğinde bulunmadan önce, şu anda hangi dillerin yüklü olduğunu belirlemeniz gerekebilir.
Kotlin
val installedLanguages: Set<String> = splitInstallManager.installedLanguages
Java
Set<String> installedLanguages = splitInstallManager.getInstalledLanguages();
Ardından, aşağıdaki resimde gösterildiği gibi deferredLanguageUninstall()
yöntemini kullanarak hangi dilleri kaldıracağınıza karar verebilirsiniz.
Kotlin
splitInstallManager.deferredLanguageUninstall( Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)))
Java
splitInstallManager.deferredLanguageUninstall( Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)));
Modül yüklemelerini yerel olarak test etme
Play Feature Delivery Library, Play Store'a bağlanmadan uygulamanızın aşağıdaki işlemleri yapabilme özelliğini yerel olarak test etmenize olanak tanır:
- Modül yüklemelerini isteyin ve izleyin.
- Yükleme hatalarını giderme
SplitCompat
simgesini kullanarak modüllere erişin.
Bu sayfada, uygulamanızın bölünmüş APK'larını test cihazınıza nasıl dağıtacağınız açıklanmaktadır. Böylece Play Özellik Dağıtımı, Play Store'dan modül isteme, indirme ve yükleme işlemlerini simüle etmek için bu APK'ları otomatik olarak kullanır.
Uygulamanızın mantığında herhangi bir değişiklik yapmanız gerekmez ancak aşağıdaki koşulları karşılamanız gerekir:
bundletool
'ın en son sürümünü indirip yükleyin. Uygulamanızın paketinden yeni bir yüklenebilir APK grubu oluşturmak içinbundletool
gerekir.
APK grubu oluşturma
Henüz yapmadıysanız uygulamanızın bölünmüş APK'larını aşağıdaki şekilde oluşturun:
- Aşağıdaki yöntemlerden birini kullanarak uygulamanız için bir uygulama paketi oluşturun:
- Android App Bundle oluşturmak ve imzalamak için Android Studio'yu ve Gradle için Android eklentisini kullanın.
- Uygulama paketinizi komut satırından oluşturun.
Aşağıdaki komutu kullanarak tüm cihaz yapılandırmaları için APK grubu oluşturmak üzere
bundletool
kullanın:bundletool build-apks --local-testing --bundle my_app.aab --output my_app.apks
--local-testing
işareti, Play Store'a bağlanmadan özellik modüllerinin yüklenmesini test etmek için Play Feature Delivery Kitaplığı'nın yerel split APK'ları kullanmasını sağlayan, APK'larınızın manifestlerindeki meta verileri içerir.
Uygulamanızı cihaza dağıtma
--local-testing
işaretini kullanarak bir APK grubu oluşturduktan sonra,
uygulamanızın temel sürümünü yüklemek ve ek APK'ları cihazınızın yerel depolama alanına aktarmak için bundletool
işaretini kullanın. Aşağıdaki komutla her iki işlemi de yapabilirsiniz:
bundletool install-apks --apks my_app.apks
Artık uygulamanızı başlattığınızda ve bir özellik modülünü indirip yüklemek için kullanıcı akışını tamamladığınızda Play Feature Delivery Kitaplığı, bundletool
cihazın yerel depolama alanına aktarılan APK'ları kullanır.
Ağ hatası simülasyonu
Play Özellik Dağıtımı Kitaplığı, Play Store'dan modül yüklemelerini simüle etmek için SplitInstallManager
yerine FakeSplitInstallManager
adlı bir alternatif kullanarak modül isteğinde bulunur. bundletool
ile --local-testing
işaretini kullanarak bir APK grubu oluşturup bunları test cihazınıza dağıttığınızda, Play Feature Delivery Library'ye uygulamanızın API çağrılarını SplitInstallManager
yerine FakeSplitInstallManager
'yi çağıracak şekilde otomatik olarak değiştirmesini söyleyen meta veriler eklenir.
FakeSplitInstallManager
, uygulamanız bir sonraki modül yükleme isteğinde bulunduğunda ağ hatasını simüle etmek için etkinleştirebileceğiniz bir boole işareti içerir. Testlerinizde FakeSplitInstallManager
erişmek için aşağıdaki örnekte gösterildiği gibi FakeSplitInstallManagerFactory
kullanarak bir örneğini alabilirsiniz:
Kotlin
// Creates an instance of FakeSplitInstallManager with the app's context. val fakeSplitInstallManager = FakeSplitInstallManagerFactory.create(context) // Tells Play Feature Delivery Library to force the next module request to // result in a network error. fakeSplitInstallManager.setShouldNetworkError(true)
Java
// Creates an instance of FakeSplitInstallManager with the app's context. FakeSplitInstallManager fakeSplitInstallManager = FakeSplitInstallManagerFactory.create(context); // Tells Play Feature Delivery Library to force the next module request to // result in a network error. fakeSplitInstallManager.setShouldNetworkError(true);