15

I am using in-app updates for android and as per the documentation, they are using onActivityResult to handle app behaviour incase the update is interrupted.

This is my function that is called from my fragment:

private fun startImmediateUpdate(appUpdateInfo: AppUpdateInfo) {
    appUpdateManager.startUpdateFlowForResult(
        appUpdateInfo,
        AppUpdateType.IMMEDIATE,
        requireActivity(),
        Constants.CODES.APP_UPDATE_REQUEST_CODE
    )

}

This is how i am handling results in parent activity

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    when (requestCode) {
        Constants.CODES.APP_UPDATE_REQUEST_CODE -> {
            if (resultCode != RESULT_OK || resultCode == RESULT_CANCELED || resultCode == ActivityResult.RESULT_IN_APP_UPDATE_FAILED) {
                //Do whatever i want to
            }
        }
    }
    super.onActivityResult(requestCode, resultCode, data)
}

Now super.onActivityResult(requestCode, resultCode, data) is deprecated. Things are working fine for now but i am worried the app will crash if its wiped out completely

What can i do to replace onActivityResult()? I have looked into registerForActivityResult() but could not find anything that suits my usecase.

Hashir Ali
  • 191
  • 2
  • 10
  • [OnActivityResult method is deprecated, what is the alternative?](https://stackoverflow.com/q/62671106/3290339). You should go as per [Getting a result from an activity](https://developer.android.com/training/basics/intents/result) – Onik Dec 22 '20 at 13:27
  • 1
    @Onik i am not starting any activity on my own. Its a built in function used by appUpdateManager, although works in the similar fashion as startActivityForResult() , but i just want to handle the results. Not launching anything on my own. – Hashir Ali Dec 22 '20 at 13:31
  • Check this on google documentation: https://developer.android.com/training/basics/intents/result#separate. Maybe will help you – ziselos Dec 22 '20 at 13:51
  • @HashirAli Any update? – Basi Jan 21 '21 at 07:24
  • Nothing positive so far. – Hashir Ali Jan 22 '21 at 07:31
  • Please see [this tweet](https://twitter.com/ianhlake/status/1532782435447951361) by Ian Lake which helped me implement a solution that uses `registerForActivityResult`. However it's not that simple as there is no sample and the documentation is quite sparse. – Sven Jacobs Jun 23 '22 at 07:26
  • This was finally added in version `2.1.0` of the library. Please see my [updated answer](https://stackoverflow.com/a/72726406/416029). – Sven Jacobs Jun 01 '23 at 13:31

3 Answers3

10

Update (June 2023):

Since version 2.1.0 of the In-App Updates library, which was released in May 2023, an overload of startUpdateFlowForResult that accepts an IntentSenderForResultStarter was finally added.


Old answer (before version 2.1.0):

As Ian Lake mentioned there is a solution that uses IntentSenderForResultStarter.

First of all in your Activity, create a ActivityResultLauncher:

private val updateFlowResultLauncher =
    registerForActivityResult(
        ActivityResultContracts.StartIntentSenderForResult(),
    ) { result ->
        if (result.resultCode == RESULT_OK) {
            // Handle successful app update
        }
    }

Now start the update flow as follows:

fun startUpdate(
    appUpdateInfo: AppUpdateInfo,
    requestCode: Int,
) {
    val starter =
        IntentSenderForResultStarter { intent, _, fillInIntent, flagsMask, flagsValues, _, _ ->
            val request = IntentSenderRequest.Builder(intent)
                .setFillInIntent(fillInIntent)
                .setFlags(flagsValues, flagsMask)
                .build()

            updateFlowResultLauncher.launch(request)
        }

    appUpdateManager.startUpdateFlowForResult(
        appUpdateInfo,
        AppUpdateType.FLEXIBLE,
        starter,
        requestCode,
    )
}
Sven Jacobs
  • 6,278
  • 5
  • 33
  • 39
  • If you're using `Compose` this may be helpful: https://gist.github.com/tadfisher/e1bd46bfcabf92f96278bf8d25da6d0e – James Aug 26 '22 at 14:53
5

I have the same issue and I see that one possibility is to rewrite to use the startUpdateFlow call instead.

Personally, I think this is not worth doing, so I will ignore this specific deprecation warning instead and wait/hope for Android/Google to make a method where we can pass an ActivityResultLauncher instead.

Anders Ullnæss
  • 818
  • 9
  • 8
  • as of 22-DEC-21, no update from google yet they want us to target sdk 30 at min and use scopedstorage and what not – asim Dec 21 '21 at 20:05
  • 1
    This was finally added in version `2.1.0` of the library. Please see my [updated answer](https://stackoverflow.com/a/72726406/416029). – Sven Jacobs Jun 01 '23 at 13:31
-1

The New Way

    appUpdateInfoTask.addOnSuccessListener { appUpdateInfo ->
        if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE
            && (appUpdateInfo.clientVersionStalenessDays() ?: -1) >= 2
            && appUpdateInfo.updatePriority() >= updatePriority
            && appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)
        ) {
            appUpdateManager.startUpdateFlowForResult(
                appUpdateInfo,
                AppUpdateType.IMMEDIATE,
                this,
                updateCode
            )
            openActivityForResult()
        }
    }
}

private fun openActivityForResult(){
    resultUpdate.launch(Intent(this, MainActivity::class.java))
}

var resultUpdate = registerForActivityResult(ActivityResultContracts.StartActivityForResult()){ result->
    if (result.resultCode != Activity.RESULT_OK){
        Toast.makeText(
            this,
            "App Update failed, please try again on the next app launch.",
            Toast.LENGTH_SHORT
        ).show()
    }
}
  • 1
    Thanks for the suggestion. However I'm waiting for an official support of the new API with `ActivityResultLauncher` as Anders Ullnæss wrote above. – Sven Jacobs May 10 '21 at 07:34