안드로이드 앱을 실행할 때 해당 앱에 대한 업데이트 정보를 플레이스토어에서 가져와 업데이트 가능 여부를 판단하고 앱 내부에서 즉시 혹은 유연한 업데이트를 통해 사용자가 플레이스토어를 접속하지 않더라도 Play Core라이브러리를 사용해 UX흐름을 지원할 수 있는 기능입니다.
dependencies {
. . .
implementation 'com.google.android.play:core:1.10.2'
}
[즉시업데이트 기준 설명]
val appUpdateManager = AppUpdateManagerFactory.create(context)
// Returns an intent object that you use to check for an update.
val appUpdateInfoTask = appUpdateManager.appUpdateInfo
// Checks that the platform will allow the specified type of update.
appUpdateInfoTask.addOnSuccessListener { appUpdateInfo ->
if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE
// This example applies an immediate update. To apply a flexible update
// instead, pass in AppUpdateType.FLEXIBLE
&& appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)
) {
// Request the update.
}
}
appUpdateManager 인스턴스의 업데이트 정보를 불러오고 리스너로 업데이트 가능여부를 체크합니다. 이때 업데이트 조건을 설정할 수 있습니다. IMMEDIATE
, FLEXIBLE
혹은 (appUpdateInfo.clientVersionStalenessDays() ?: -1) >= DAYS_FOR_FLEXIBLE_UPDATE
스토어에 업데이트가 제공된 이후의 일 수도 가능합니다.
플레이스토어에 출시되면 출시 트랙마다 아래와 같이 릴리즈 정보가 생성이 됩니다.
{
"releases": [{
"versionCodes": ["88"],
"inAppUpdatePriority": 5,
"status": "completed"
}]
}
inAppUpdatePriority
의 경우 0부터 5까지 존재하며 높을수록 높은 우선순위를 의미합니다. 디폴트 값은 0으로 지정되어 있습니다.
Google Developer API 를 통해 값을 변경할 수 있다고 공식문서에 설명되어 있습니다.(아직 적용 x)
appUpdateManager.startUpdateFlowForResult(
appUpdateInfo,
IMMEDIATE,
this,
REQUEST_CODE_UPDATE
)
Request the update 부분에 업데이트 정보를 넣어주고 업데이트를 요청합니다.
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == REQUEST_CODE_UPDATE) {
if (resultCode != Activity.RESULT_OK) {
Toast.makeText(this, "업데이트가 취소 되었습니다.", Toast.LENGTH_SHORT).show()
val appUpdateInfoTask: Task<AppUpdateInfo> = appUpdateManager.appUpdateInfo
appUpdateInfoTask.addOnSuccessListener { appUpdateInfo ->
if (appUpdateInfo.updateAvailability() === UpdateAvailability.UPDATE_AVAILABLE) {
if(appUpdateInfo.isUpdateTypeAllowed(IMMEDIATE)){
val dialog = ContentDialog(
this,
"업데이트 알림",
"필수 업데이트가 있습니다.\n최적의 사용 환경을 위해 최신 버전으로 업데이트 해주세요."
)
dialog.apply {
addFirstButton("확인") {
dialog.dismiss()
// 업데이트를 다시 요청한다.
requestUpdate(appUpdateInfo)
}
addSecondButton("나가기"){
dialog.dismiss()
finish()
}
}.show()
}
}
}
}
}
}
onActivityResult 메소드에서 해당하는 리퀘스트 코드를 전달받고 결과에 따른 분기처리를 해줍니다.
유의사항으로 즉시 업데이트의 경우 사용자가 앱을 닫거나 종료하더라도 추가 사용자 확인 없이 업데이트가 백그라운드에서 계속 다운로드되고 설치되어야 합니다. 그 과정에서 앱이 포그라운드로 돌아왔을 때 업데이트가 중단되었는지(DEVELOPER_TRIGGERED_UPDATE_IN_PROGRES
상태인지) 확인해야하며 중단되었다면 다시 시작하는 로직을 아래와 같이 추가해주어야 합니다.
override fun onResume() {
super.onResume()
// 업데이트 진행 중 확인
appUpdateManager
.appUpdateInfo
.addOnSuccessListener{appUpdateInfo: AppUpdateInfo->
if (appUpdateInfo.updateAvailability()
== UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS
) {
// If an in-app update is already running, resume the update.
requestUpdate(appUpdateInfo)
}
}
}
테스트는 개발자 콘솔의 내부앱 공유를 이용하면 편합니다.