diff --git a/README.md b/README.md index 686cd0e..62ae0f7 100644 --- a/README.md +++ b/README.md @@ -37,9 +37,9 @@ There are two modes * Immediate - User will be blocked until download and installation is finished, restart is triggered automatically -#### Set update to immediate mode +#### Start the update process ```Kotlin - inAppUpdateManager.setImmediateUpdate() + inAppUpdateManager.startUpdate(updateType) ``` diff --git a/app/build.gradle b/app/build.gradle index a3254c2..cf1b428 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -24,7 +24,7 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - implementation 'com.google.android.material:material:1.1.0-alpha06' + implementation 'com.google.android.material:material:1.1.0-alpha07' implementation 'androidx.core:core-ktx:1.0.2' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'io.reactivex.rxjava2:rxjava:2.2.9' diff --git a/app/src/main/java/at/allaboutapps/inappupdaterdemo/MainActivity.kt b/app/src/main/java/at/allaboutapps/inappupdaterdemo/MainActivity.kt index f7e0bf9..a6a42df 100644 --- a/app/src/main/java/at/allaboutapps/inappupdaterdemo/MainActivity.kt +++ b/app/src/main/java/at/allaboutapps/inappupdaterdemo/MainActivity.kt @@ -3,9 +3,10 @@ package at.allaboutapps.inappupdaterdemo import android.os.Bundle import android.view.View import androidx.appcompat.app.AppCompatActivity +import at.allaboutapps.inappupdater.InAppUpdateManager +import at.allaboutapps.inappupdater.InAppUpdateStatus import io.reactivex.disposables.Disposables import kotlinx.android.synthetic.main.activity_main.* -import at.allaboutapps.inappupdater.* class MainActivity : AppCompatActivity() { @@ -19,24 +20,21 @@ class MainActivity : AppCompatActivity() { tvPackageName.text = packageName tvCurrentVersionCode.text = BuildConfig.VERSION_CODE.toString() - initInAppUpdate() btUpdate.setOnClickListener { - - - if (updateTypeGroup.checkedButtonId == R.id.btImmediate) { - inAppUpdateManager.setImmediateUpdate() - } else { - inAppUpdateManager.setFlexibleUpdate() - } - inAppUpdateManager.startUpdate() + inAppUpdateManager.startUpdate(getSelectedUpdateType()) } + btRestart.setOnClickListener { inAppUpdateManager.completeUpdate() } } + @InAppUpdateManager.InAppUpdateType + private fun getSelectedUpdateType() = + if (updateTypeGroup.checkedButtonId == R.id.btImmediate) InAppUpdateManager.UPDATE_TYPE_IMMEDIATE else InAppUpdateManager.UPDATE_TYPE_FLEXIBLE + private fun initInAppUpdate() { inAppUpdateManager = InAppUpdateManager(this) inAppUpdateStatusDisposable = inAppUpdateManager.observeInAppUpdateStatus() diff --git a/inappupdater/build.gradle b/inappupdater/build.gradle index 21572f9..5fa1d13 100644 --- a/inappupdater/build.gradle +++ b/inappupdater/build.gradle @@ -97,7 +97,8 @@ dependencies { implementation 'io.reactivex.rxjava2:rxjava:2.2.9' - implementation 'com.google.android.play:core:1.6.0' + implementation 'com.google.android.play:core:1.6.1' + implementation 'com.android.support:support-annotations:28.0.0' testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test.ext:junit:1.1.1' diff --git a/inappupdater/src/main/java/at/allaboutapps/inappupdater/InAppUpdateManager.kt b/inappupdater/src/main/java/at/allaboutapps/inappupdater/InAppUpdateManager.kt index 2ea3d51..1843ac1 100644 --- a/inappupdater/src/main/java/at/allaboutapps/inappupdater/InAppUpdateManager.kt +++ b/inappupdater/src/main/java/at/allaboutapps/inappupdater/InAppUpdateManager.kt @@ -1,13 +1,16 @@ package at.allaboutapps.inappupdater import android.app.Activity +import androidx.annotation.IntDef import com.google.android.play.core.appupdate.AppUpdateManager import com.google.android.play.core.appupdate.AppUpdateManagerFactory import com.google.android.play.core.install.InstallState 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 import io.reactivex.Observable +import io.reactivex.disposables.Disposables /** * InAppUpdateManager handles the in app update process @@ -19,13 +22,13 @@ class InAppUpdateManager(private val activity: Activity) { companion object { const val REQUEST_CODE_IN_APP_UPDATE = 1230 + const val UPDATE_TYPE_FLEXIBLE = AppUpdateType.FLEXIBLE + const val UPDATE_TYPE_IMMEDIATE = AppUpdateType.IMMEDIATE } - private var updateType = AppUpdateType.FLEXIBLE - private val appUpdateManager: AppUpdateManager = AppUpdateManagerFactory.create(activity) - private val currentInAppUpdateStatus = InAppUpdateStatus() + private var currentInAppUpdateStatus = InAppUpdateStatus() /** * Observe the status of an in app update process @@ -37,36 +40,52 @@ class InAppUpdateManager(private val activity: Activity) { val updateStateListener = InstallStateUpdatedListener { state -> if (currentInAppUpdateStatus.appUpdateState?.installStatus() != state.installStatus()) { - currentInAppUpdateStatus.appUpdateState = state + currentInAppUpdateStatus = currentInAppUpdateStatus.copy(appUpdateState = state) emitter.onNext(currentInAppUpdateStatus) + + if (state.installStatus() == InstallStatus.DOWNLOADED) { + emitter.onComplete() + } } } - - appUpdateManager.unregisterListener(updateStateListener) + // register listener appUpdateManager.registerListener(updateStateListener) + // unregister listener on dispose + emitter.setDisposable(Disposables.fromAction { appUpdateManager.unregisterListener(updateStateListener) }) + + appUpdateManager.appUpdateInfo.addOnSuccessListener { appUpdateInfo -> - currentInAppUpdateStatus.appUpdateInfo = appUpdateInfo + currentInAppUpdateStatus = currentInAppUpdateStatus.copy(appUpdateInfo = appUpdateInfo) + // if there already is an update progress in progress we just setup it to resume if (appUpdateInfo.updateAvailability() == UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS) { //set state if app gets reopened with an update in progress - currentInAppUpdateStatus.appUpdateState = - InstallState(appUpdateInfo.installStatus(), 0, activity.packageName) + currentInAppUpdateStatus = currentInAppUpdateStatus.copy( + appUpdateState = InstallState( + appUpdateInfo.installStatus(), + 0, + activity.packageName + ) + ) } emitter.onNext(currentInAppUpdateStatus) } } } + /** * Starts an in app update process + * + * @param updateType set the type of the in app update */ - fun startUpdate() { + fun startUpdate(@InAppUpdateType updateType: Int = AppUpdateType.FLEXIBLE) { //to be save //refetch the update status before starting the update process appUpdateManager.appUpdateInfo.addOnSuccessListener { appUpdateInfo -> - currentInAppUpdateStatus.appUpdateInfo = appUpdateInfo + currentInAppUpdateStatus = currentInAppUpdateStatus.copy(appUpdateInfo = appUpdateInfo) appUpdateManager.startUpdateFlowForResult( currentInAppUpdateStatus.appUpdateInfo, @@ -85,12 +104,7 @@ class InAppUpdateManager(private val activity: Activity) { } - fun setFlexibleUpdate() { - updateType = AppUpdateType.FLEXIBLE - } - - fun setImmediateUpdate() { - updateType = AppUpdateType.IMMEDIATE - } - + @Retention(AnnotationRetention.SOURCE) + @IntDef(UPDATE_TYPE_FLEXIBLE, UPDATE_TYPE_IMMEDIATE) + annotation class InAppUpdateType } \ No newline at end of file diff --git a/inappupdater/src/main/java/at/allaboutapps/inappupdater/InAppUpdateStatus.kt b/inappupdater/src/main/java/at/allaboutapps/inappupdater/InAppUpdateStatus.kt index 520429f..0657db7 100644 --- a/inappupdater/src/main/java/at/allaboutapps/inappupdater/InAppUpdateStatus.kt +++ b/inappupdater/src/main/java/at/allaboutapps/inappupdater/InAppUpdateStatus.kt @@ -5,17 +5,20 @@ import com.google.android.play.core.install.InstallState import com.google.android.play.core.install.model.InstallStatus import com.google.android.play.core.install.model.UpdateAvailability +const val NO_UPDATE = -1 + /** * This class is just a wrapper for AppupdateInfo and InstallState * Used by InAppUpdateManager */ -class InAppUpdateStatus { - var appUpdateInfo: AppUpdateInfo? = null - var appUpdateState: InstallState? = null +data class InAppUpdateStatus( + val appUpdateInfo: AppUpdateInfo? = null, + val appUpdateState: InstallState? = null +) { val availableVersionCode: Int - get() = appUpdateInfo?.availableVersionCode() ?: -1 + get() = appUpdateInfo?.availableVersionCode() ?: NO_UPDATE /** * Checks if an update is in progress */