Yazılım işlevlerini kullanıcıyı yormadan yaptırabilmek çoğu zaman olumlu geri bildirim almanızı sağlar.
Bu makale Android’de in-app update yapısını uygulayarak kullanıcıların kolay bir şekilde uygulamayı güncellemelerini örnekleyecektir.
Uygulamanızda güncellemeleri görüntülemek için iki yöntem bulunmaktadır.
1- Flexible
Kullanıcıya uygulamayı güncellemek isteyip istemediğini pop-up pencere görüntüsüyle sorar. Kullanıcı güncellemeyi kabul ederse arka planda indirme işlemini yapar. Örneğin, kullanıcıları uygulamanızın yeni bir özelliği denemeye teşvik etmek isteyebilirsiniz.
2- Immediate
Immediate, kullanıcının projeyi kullanmaya devam edebilmesi için uygulamayı güncellemesi gerektiren durumlarda uygulanır. Immediate, uygulamanızın temel işlevlerinde kritik durumlar olduğunda kullanılır. Örneğin, güvenlik zafiyetinin önlenmesi.
Güncellemeyi Başlatma Durumları
Hangi durumlarda güncellemeyi başlatmamız gerektiğini anlatan 2 tane sinyal bulunmaktadır.
- Priority: Google Play Developer API’si, her güncellemenin önceliğini belirlemenize olanak tanır. Örneğin, güncelleme önceliğini ayarlamak için küçük UI iyileştirmeleri, performans iyileştirmeleri ve kritik güvenlik güncellemesi gibi stratejiler belirleyebilirsiniz. Google Play, önceliği belirlemek için 0 ile 5 arasında bir tamsayı değeri kullanır. 0 varsayılan ve 5 en yüksek önceliktir.
- Staleness: Kullanıcının bir güncellemeden en son haberdar edilmesinden bu yana ne kadar zaman geçtiğini de kontrol etmek isteyebilirsiniz. Örneğin, kullanıcı güncellemenin yayınlanmasından sonraki 30 gün içinde uygulamayı güncellememişse Flexible tetiklenir ve 90 günden uzun olmuşsa Immediate
In-app update yapısını projemizde kullanalım.
1-Proje Ayarları
Android Studio Ide ile oluşturduğum projemin app dizinin altındaki build.gradle dosyasını açıyoruz. Dependencies kod bloklarının arasına aşağıdaki kodları yerleştirerek Google Play Core kütüphanesini yüklüyoruz.
1 |
implementation 'com.google.android.play:app-update:2.0.0' |
2- In-app update uygulama
Uygulamayı kolaylaştırmak için ihtiyacımız olan her şeyi ayrı bir dosyada (InAppUpdate.kt) oluşturacağım ve ardından güncellemeleri kontrol etmek istediğimiz Activity sınıfında kullanacağız.
Benim oluşturduğum dosya ismi InAppUpdate.kt’dir.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
import android.app.Activity import android.content.Intent import android.graphics.Color import android.util.Log import androidx.appcompat.app.AppCompatActivity import com.google.android.material.snackbar.Snackbar import com.google.android.play.core.appupdate.* import com.google.android.play.core.install.* import com.google.android.play.core.install.model.* class InAppUpdate(activity: Activity) : InstallStateUpdatedListener { private var appUpdateManager: AppUpdateManager private val MY_REQUEST_CODE = 500 private var parentActivity: Activity = activity private var currentType = AppUpdateType.FLEXIBLE init { appUpdateManager = AppUpdateManagerFactory.create(parentActivity) appUpdateManager.appUpdateInfo.addOnSuccessListener { info -> //Güncelleme olup olmadığını kontrol ediyoruz if (info.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE) { //Priority 5 ise kritik bir durum olduğu için Immediate güncellemeyi tetikliyoruz. //Priority 4,3,2,1 ise Staleness değerine göre Immediate veya Flexible güncelleme yapacağımı kontrol ediyoruz if (info.updatePriority() == 5) { // Priority: 5 (Immediate update) if (info.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)) { startUpdate(info, AppUpdateType.IMMEDIATE) } } else if (info.updatePriority() == 4) { // Priority: 4 val clientVersionStalenessDays = info.clientVersionStalenessDays() if (clientVersionStalenessDays != null && clientVersionStalenessDays >= 5 && info.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)) { startUpdate(info, AppUpdateType.IMMEDIATE) } else if (clientVersionStalenessDays != null && clientVersionStalenessDays >= 3 && info.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)) { startUpdate(info, AppUpdateType.FLEXIBLE) } } else if (info.updatePriority() == 3) { // Priority: 3 val clientVersionStalenessDays = info.clientVersionStalenessDays() if (clientVersionStalenessDays != null && clientVersionStalenessDays >= 30 && info.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)) { startUpdate(info, AppUpdateType.IMMEDIATE) } else if (clientVersionStalenessDays != null && clientVersionStalenessDays >= 15 && info.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)) { startUpdate(info, AppUpdateType.FLEXIBLE) } } else if (info.updatePriority() == 2) { // Priority: 2 val clientVersionStalenessDays = info.clientVersionStalenessDays() if (clientVersionStalenessDays != null && clientVersionStalenessDays >= 90 && info.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)) { startUpdate(info, AppUpdateType.IMMEDIATE) } else if (clientVersionStalenessDays != null && clientVersionStalenessDays >= 30 && info.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)) { startUpdate(info, AppUpdateType.FLEXIBLE) } } else if (info.updatePriority() == 1) { // Priority: 1 startUpdate(info, AppUpdateType.FLEXIBLE) } else { // Priority: 0 // Uygulama içi güncellemeyi gösterme } } else { // Güncelleme olmadığı durum } } appUpdateManager.registerListener(this) } private fun startUpdate(info: AppUpdateInfo, type: Int) { appUpdateManager.startUpdateFlowForResult(info, type, parentActivity, MY_REQUEST_CODE) currentType = type } fun onResume() { appUpdateManager.appUpdateInfo.addOnSuccessListener { info -> if (currentType == AppUpdateType.FLEXIBLE) { //Güncelleme indirilmiş ancak yüklenmemişse, güncellemeyi tamamlaması için kullanıcıyı bilgilendirme if (info.installStatus() == InstallStatus.DOWNLOADED) flexibleUpdateDownloadCompleted() } else if (currentType == AppUpdateType.IMMEDIATE) { if (info.updateAvailability() == UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS) { startUpdate(info, AppUpdateType.IMMEDIATE) } } } } fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { if (requestCode == MY_REQUEST_CODE) { if (resultCode != AppCompatActivity.RESULT_OK) { //Güncelleme iptal edilirse veya başarısız olursa güncellemenin yeniden başlatılmasını talep edebilirsiniz. Log.e("ERROR", "Güncelleme başarısız! $resultCode") } } } //Flexible güncellemenin yapıldığını anlatan uyarı private fun flexibleUpdateDownloadCompleted() { Snackbar.make( parentActivity.findViewById(R.id.activity_main_layout), "Bir güncelleme indirildi.", Snackbar.LENGTH_INDEFINITE ).apply { setAction("RESTART") { appUpdateManager.completeUpdate() } setActionTextColor(Color.WHITE) show() } } fun onDestroy() { appUpdateManager.unregisterListener(this) } override fun onStateUpdate(state: InstallState) { if (state.installStatus() == InstallStatus.DOWNLOADED) { flexibleUpdateDownloadCompleted() } } } |
InAppUpdate.kt dosyasını Activity sınıfında kullanalım.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
class MainActivity : AppCompatActivity() { private lateinit var inAppUpdate: InAppUpdate override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) inAppUpdate = InAppUpdate(this) } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) inAppUpdate.onActivityResult(requestCode,resultCode, data) } override fun onResume() { super.onResume() inAppUpdate.onResume() } override fun onDestroy() { super.onDestroy() inAppUpdate.onDestroy() } } |
Kaynaklar
1- https://developer.android.com/guide/playcore/in-app-updates
2- https://proandroiddev.com/in-app-update-d83bb484797f