In-App Updates Android

Easily check and update your android app

Yudi Setiawan
Nusanet Developers
5 min readSep 28, 2019

--

Pengenalan

Android App Bundle merupakan revolusi baru bagi Android Developer untuk membuat aplikasi kita menjadi lebih efektif dan efisien. Android App Bundle diperkenalkan ke publik pada acara Google I/O 18.

Android App Bundle dibuat dengan sebaik mungkin untuk Android Developer agar aplikasi yang kita kembangkan memiliki ukuran yang kecil karena Android App Bundle ada melakukan pemisahan paket-paket didalam aplikasi kita seperti pada gambar berikut.

https://developer.android.com/guide/app-bundle

Adapun fitur-fitur yang terdapat pada Android App Bundle ini bisa kita baca pada website official-nya langsung.

Diantara fitur-fitur tersebut ada salah satu fitur yang akan kita bahas pada tulisan kali ini yaitu, In-App Updates.

In-App Updates merupakan fitur dari pustaka Play Core yang memungkinkan kita untuk melakukan pengecekan dan pembaharuan aplikasi kita ke Play Store dalam aplikasi yang sedang kita kembangkan. Jadi, dikarenakan proses pembaharuannya dilakukan didalam aplikasi maka, kita sebagai developer tidak perlu khawatir terhadap versi app yang pengguna gunakan karena si pengguna akan selalu mendapatkan pemberitahuannya ketika tersedia versi terbaru di Play Store. Hhhmmm… walaupun sebenarnya dari Play Store-nya sendiri memiliki fitur auto-update tapi, kita sebagai developer tidak mungkin memaksa si pengguna untuk menghidupkan auto-update tersebut. Jadi, langkah yang bisa kita ambil agar pengguna kita selalu menggunakan versi app yang terbaru adalah dengan menggunakan In-App Updates.

Contoh Pemakaian

Untuk contoh pemakaian kali ini saya harap kita semua sudah memiliki akun developer console di Play Store karena untuk pengetesannya kita perlu upload aplikasi kita di Play Store. Contoh aplikasi yang akan kita buat pada artikel sangatlah sederhana yaitu cuma menampilkan tulisan hello world. Sengaja contoh aplikasinya saya buat yang sederhana agar tulisan ini menjadi tidak terlalu panjang.

Buat Projek

Kita buat projek baru di Android Studio.

Buat projek baru di Android Studio

Setup build.gradle

Kita tambahkan dependency berikut didalam file build.gradle(app).

dependencies {
...
implementation 'com.google.android.play:core:1.6.3'
...
}

Silakan lakukan sync untuk mengunduh paket-paket dependency-nya.

Publish App

Selanjutnya, kita publish app kita ke Play Store tapi pilih ke Play Store dengan version code 2 dan version name 2.0. Sengaja kita upload versi 2 agar nantinya pas ngetes dilokal kita pasang yang lebih rendah.

Play Store

Tambahkan Fitur In-App Updates

Langkah selanjutnya adalah kita tambahkan fitur In-App Updates pada aplikasi kita. Fitur In-App Updates ini sebenarnya ada tipe-nya untuk pembaharuan app-nya yaitu, AppUpdateType.IMMEDIATE dan AppUpdateType.FLEXIBLE . Perbedaannya adalah AppUpdateType.IMMEDIATE akan menahan UI app kita sehingga pengguna harus menunggu pembaharuan-nya selesai untuk bisa menggunakan app-nya sedangkan, AppUpdateType.FLEXIBLE tidak akan menahan UI app kita sehingga si pengguna masih bisa tetap menggunakan app-nya walaupun proses pembaharuannya sedang berjalan.

In-App Updates: Immediate

Untuk contoh AppUpdateType.IMMEDIATE kita buat coding-nya seperti berikut.

import android.app.Activity
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.google.android.play.core.appupdate.AppUpdateManager
import com.google.android.play.core.appupdate.AppUpdateManagerFactory
import com.google.android.play.core.install.model.AppUpdateType
import com.google.android.play.core.install.model.UpdateAvailability

class MainActivity : AppCompatActivity() {

private lateinit var appUpdateManager: AppUpdateManager

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

appUpdateManager = AppUpdateManagerFactory.create(this)
val appUpdateInfoTask = appUpdateManager.appUpdateInfo
appUpdateInfoTask.addOnSuccessListener {
if (it.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE
&& it.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)
) {
appUpdateManager.startUpdateFlowForResult(
it,
AppUpdateType.FLEXIBLE,
this,
999
)
} else {
// TODO: do something in here if update not available
}
}
}

override fun onResume() {
appUpdateManager.appUpdateInfo
.addOnSuccessListener {
if (it.updateAvailability() == UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS) {
appUpdateManager.startUpdateFlowForResult(
it,
AppUpdateType.IMMEDIATE,
this,
999
)
}
}
super.onResume()
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 999 && resultCode == Activity.RESULT_OK) {
// TODO: do something in here if in-app updates success
} else {
// TODO: do something in here if in-app updates failure
}
}
}

Selanjutnya, untuk mengetes-nya kita perlu ubah nilai versionCode dan versionName pada file build.gradle(app).

Turunkan nilai versi code dan version name

Setup Signing Config

Untuk testing di lokal kita perlu setup signingConfig di file build.gradle(app) seperti berikut.

android {
signingConfigs {
release {
storeFile file('/Users/yudisetiawan/Downloads/Other/keystore_ysn.jks')
storePassword 'password_keystore_nya'
keyAlias = 'key_alias_nya'
keyPassword 'password_key_nya'
}
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}
}
}

Testing Update Immediate

Untuk melakukan testing di lokal kita perlu ubah build_variant-nya ke mode release.

Ubah build_variant-nya ke release

Setelah itu coba kita jalankan codingan tadi ke device. Maka, hasilnya akan menjadi seperti berikut.

In-App Updates: Flexible

Untuk contoh penggunaan In-App Updates yang mode flexible silakan ubah coding di file MainActivity menjadi seperti berikut.

package com.ysn.helloworldupdate

import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.snackbar.Snackbar
import com.google.android.play.core.appupdate.AppUpdateManager
import com.google.android.play.core.appupdate.AppUpdateManagerFactory
import com.google.android.play.core.install.InstallStateUpdatedListener
import com.google.android.play.core.install.model.AppUpdateType
import com.google.android.play.core.install.model.InstallStatus
import com.google.android.play.core.install.model.UpdateAvailability

class MainActivity : AppCompatActivity() {

private lateinit var appUpdateManager: AppUpdateManager
private lateinit var listener: InstallStateUpdatedListener

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

appUpdateManager = AppUpdateManagerFactory.create(this)
listener = InstallStateUpdatedListener { state ->
if (state.installStatus() == InstallStatus.DOWNLOADED) {
showInfoUpdateSuccess()
}
}
appUpdateManager.registerListener(listener)
val appUpdateInfoTask = appUpdateManager.appUpdateInfo
appUpdateInfoTask.addOnSuccessListener {
if (it.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE
&& it.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)
) {
appUpdateManager.startUpdateFlowForResult(
it,
AppUpdateType.FLEXIBLE,
this,
999
)
} else {
// TODO: do something in here if update not available
}
}
}

override fun onResume() {
appUpdateManager.appUpdateInfo
.addOnSuccessListener {
if (it.installStatus() == InstallStatus.DOWNLOADED) {
showInfoUpdateSuccess()
} else if (it.updateAvailability() == UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS) {
appUpdateManager.startUpdateFlowForResult(
it,
AppUpdateType.FLEXIBLE,
this,
999
)
}
}
super.onResume()
}

override fun onDestroy() {
super.onDestroy()
appUpdateManager.unregisterListener(listener)
}

private fun showInfoUpdateSuccess() {
Snackbar.make(findViewById(android.R.id.content), "Restart to update", Snackbar.LENGTH_INDEFINITE)
.setAction("Restart") {
appUpdateManager.completeUpdate()
appUpdateManager.unregisterListener(listener)
}
.show()
}

}

Testing Update Flexible

Sekarang coba kita uninstall app kita yang lama lalu kita jalankan ulang codingan yang baru saja. Maka, outputnya akan menjadi seperti berikut

Kesimpulan

Jadi, dari dua mode update tersebut bisa kita ambil kesimpulan bahwa mode AppUpdateType.IMMEDIATE melakukan proses downloading-nya dengan cara blocking UI app kita sehingga pengguna diharuskan menunggu selesai download-nya baru bisa menggunakan app-nya. Sementara untuk mode AppUpdateType.FLEXIBLE melakukan proses downloading-nya non-blocking UI sehingga ketika proses download-nya jalan si pengguna masih bisa menggunakan app-nya.

--

--