Android In-app update API -> Immediate update problem - android

Started to experiment with In-app updates. Everything seems to work prefect.
But... when entering some edge cases, like for example, canceling the process of update in the process of downloading the update, the API for some reason stops working as intended.
Example: I start my activity and the first thing in onResume(), I do this:
//In app update code. Only works for Android 5.0 and above.
if (Build.VERSION.SDK_INT >= 21) {
AppUpdateManager appUpdateManager = AppUpdateManagerFactory.create(this);
Task<AppUpdateInfo> appUpdateInfoTask = appUpdateManager.getAppUpdateInfo();
appUpdateInfoTask.addOnSuccessListener(appUpdateInfo -> {
if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE) {
try {
appUpdateManager.startUpdateFlowForResult(appUpdateInfo, AppUpdateType.IMMEDIATE, this, 1333);
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
} else if (appUpdateInfo.updateAvailability() == UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS) {
// If an in-app update is already running, resume the update.
try {
appUpdateManager.startUpdateFlowForResult(appUpdateInfo, AppUpdateType.IMMEDIATE,this, 1333);
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
}
});
}
When I click on Update button and the screen for updating appears, I immediately cancel the update. It returns with onActivityResult the request code (1333) and result code (STATUS_UNKNOWN = 0) . I call finish() in that if statement, because this is a critical update that has to be updated.
The problem is now, when entering the app for the second time, onActivityResult is fired again, without showing any dialog from in-app update API and just returning the request/result code in onActivityResult callback.
Anyone with a similar problem?

looks like there is open bug for the same issue. https://issuetracker.google.com/issues/133092990 . As per comment its Play-store issue and will be released in next few weeks.

Related

Firebase authorisation

mAuth?.createUserWithEmailAndPassword(email, password)
?.addOnCompleteListener { task ->
if (task.isSuccessful) {
val user = User(fullName, age, email)
FirebaseDatabase.getInstance().getReference("user")
.child(FirebaseAuth.getInstance().currentUser!!.uid)
.setValue(user).addOnCompleteListener { childTask ->
if (childTask.isSuccessful) {
findNavController().navigate(R.id.action_registrationWindow_to_loginWindow)
showToast("User has been registered successfully")
} else {
showToast("Failed to register! Try again!")
}
progressBar.visibility = View.GONE
}
} else {
showToast("Failed to register! Try again!")
}
}
progressBar.visibility = View.GONE
I'm trying to check in the second addOnCompleteListener the condition of operation, but the second block of addOnCompleteListener isn't called. And I don't have any mistakes, the user is added to database, but block isn't called.
Is it redirecting to different fragment though? according to your logic, it may not show if it is redirecting to different screen before displaying toast, I would also suggest you try use Log instead of Toast and check in the Logcat for any errors you might have missed out,or in general debug using the Logcat as toasts can mess up when there is threads and may not show, also if you are testing on an emulator sometimes Toasts don't show, check on a real device and see if you still face the problem

Android how to catch if Intent launched with registerForActivityResult crashes

I am launching another app through registerForActivityResult (I guess the question makes sense with the deprecated startActivityForResult as well, but I couldn't find a solution for that either). I can easily handle the result when the called app returns either with success or failure. But can I "catch" the exception of the called app when it crashes, and return control to the caller app?
My code:
[...]
val request = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
when (result.resultCode) {
Activity.RESULT_OK -> {
// Success, yay! Continue with data analysis
}
Activity.RESULT_CANCELED -> {
// Something bad happened! Do something about it
}
else -> {
// Something else unexpected happened! Log it, I suppose.
}
}
}
[...]
private fun startAnotherActivity(activity: MyActivity, intent: Intent, request: ActivityResultLauncher<Intent>): Boolean {
return try {
activity.withPermissions.checkSelfPermission(Manifest.permission.CAMERA) {
request.launch(intent)
}
true
} catch (e: ActivityNotFoundException) {
//This is of course catching if the other app is not present, but it's not going to catch anything if the called app crashes
} catch (e: Exception) {
//This is of course not catching if the other app crashes
}
}
So, is there a way to notice if another app crashes (for whatever reason) and not return to the Home screen?
Note: I don't know if it's relevant, but both apps, because of design requirements, have the <category android:name="android.intent.category.DEFAULT" /> tag in the intent-filter tag used to call them in the Manifest. Because actually, there's another app which is calling my app and my app is calling the third app, in chain, and only the first app appears in the tray, by design.

In App Update not showing Update Screen untill I open playstore and see update button in Android

I implement In-App Update feature in my android application but it not working untill i go to playstore app and view update button.
Please suggest me some solution.
Thanks
public void ImmidateUpdate()
{
AppUpdateManager appUpdateManager = AppUpdateManagerFactory.create(getActivity());
// Returns an intent object that you use to check for an update.
Task<AppUpdateInfo> appUpdateInfoTask = appUpdateManager.getAppUpdateInfo();
// Checks that the platform will allow the specified type of update.
appUpdateInfoTask.addOnSuccessListener(appUpdateInfo -> {
if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE)
{
if(appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE))
{
try {
appUpdateManager.startUpdateFlowForResult(
// Pass the intent that is returned by 'getAppUpdateInfo()'.
appUpdateInfo,
// Or 'AppUpdateType.FLEXIBLE' for flexible updates.
AppUpdateType.IMMEDIATE,
// The current activity making the update request.
getActivity(),
// Include a request code to later monitor this update request.
1210);
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
}
}
});
}
Set the priority using the Google Play Developer API as described in the Play Developer API documentation. In-app update priority should be specified in the Edit.tracks resource passed in the Edit.tracks: update method.
please refer to the documntation

Unable to show Play Store in-app Update Dialog

I'm looking into In-App Updates by Play Store API. I followed the examples in the Documentations, and some other articles. But I still can't get it to show the Update Dialog provided by Play Store.
I've seen some apps do it, show a dialog to prompt the user to start the update, but using a FakeAppUpdateManager doesn't seem to do it.
Do I have to use a real release to test it out? Or is there some configuration for FakeAppUpdateManager that I need to do?
private fun checkForUpdates() {
val appUpdateManager = if (BuildConfig.DEBUG) {
FakeAppUpdateManager(this).apply {
setUpdateAvailable(UpdateAvailability.UPDATE_AVAILABLE)
setUpdatePriority(5)
}
} else {
AppUpdateManagerFactory.create(this)
}
// 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 &&
// For a flexible update, use AppUpdateType.FLEXIBLE
appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)
) {
// Create a listener to track request state updates.
val listener = { state: InstallState ->
// (Optional) Provide a download progress bar.
if (state.installStatus() == InstallStatus.DOWNLOADING) {
val bytesDownloaded = state.bytesDownloaded()
val totalBytesToDownload = state.totalBytesToDownload()
// Show update progress bar.
}
// Log state or install the update.
}
// Before starting an update, register a listener for updates.
appUpdateManager.registerListener(listener)
// Request the update.
appUpdateManager.startUpdateFlowForResult(
// Pass the intent that is returned by 'getAppUpdateInfo()'.
appUpdateInfo,
// Or 'AppUpdateType.FLEXIBLE' for flexible updates.
AppUpdateType.FLEXIBLE,
// The current activity making the update request.
this,
// Include a request code to later monitor this update request.
UPDATE_RC,
)
// When status updates are no longer needed, unregister the listener.
// appUpdateManager.unregisterListener(listener)
}
}
}
https://ibb.co/BLCKmnx
FakeAppUpdataManager is very rudimentary and will not show any UI or even invoke activity's onActivityResult based on my experience of testing and looking into decompiled code of it:
(please notice activity is not passed any further, thus no way to further do onActivityResult call by the manager)
What you can and should do though, is to check isConfirmationDialogVisible for AppUpdateType.FLEXIBLE scenario and isImmediateFlowVisible for AppUpdateType.IMMEDIATE scenario - but these dialogs/flows will never be shown on UI.
Example sequence for former:
assert(fakeAppUpdateManager.isConfirmationDialogVisible)
fakeAppUpdateManager.userAcceptsUpdate()
fakeAppUpdateManager.downloadStarts()
fakeAppUpdateManager.downloadCompletes()
assert(fakeAppUpdateManager.isInstallSplashScreenVisible)
fakeAppUpdateManager.installCompletes()
Example sequence for latter:
assert(fakeAppUpdateManager.isImmediateFlowVisible)
fakeAppUpdateManager.userAcceptsUpdate()
fakeAppUpdateManager.downloadStarts()
fakeAppUpdateManager.downloadCompletes()
assert(fakeAppUpdateManager.isInstallSplashScreenVisible)
fakeAppUpdateManager.installCompletes()

The InAppUpdate dialog pops up every time, even if I click the update button

I have an app published in the play store with versionCode 3, in a new version, I want to implement the in app update functionality, so in build.gradle I add:
implementation 'com.google.android.play:core:1.8.2'
And in the main activity:
public class MainActivity extends BaseActivity {
//...
private AppUpdateManager mAppUpdateManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
//....
checkForUpdate();
}
/**
* check for update
*/
private void checkForUpdate() {
// Creates instance of the manager.
mAppUpdateManager = AppUpdateManagerFactory.create(this);
mAppUpdateManager.registerListener(state -> {
if (state.installStatus() == InstallStatus.DOWNLOADED) {
// After the update is downloaded, show a notification
// and request user confirmation to restart the app.
popupSnackbarForCompleteUpdate();
}
});
// Returns an intent object that you use to check for an update.
Task<AppUpdateInfo> appUpdateInfoTask = mAppUpdateManager.getAppUpdateInfo();
// Checks that the platform will allow the specified type of update.
appUpdateInfoTask.addOnSuccessListener(appUpdateInfo -> {
if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE
//&& appUpdateInfo.clientVersionStalenessDays() != null
//&& appUpdateInfo.clientVersionStalenessDays() >= DAYS_FOR_FLEXIBLE_UPDATE
&& appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)) {
// Request the update.
try {
mAppUpdateManager.startUpdateFlowForResult(
// Pass the intent that is returned by 'getAppUpdateInfo()'.
appUpdateInfo,
// Or 'AppUpdateType.IMMEDIATE' for flexible updates.
AppUpdateType.FLEXIBLE,
// The current activity making the update request.
this,
// Include a request code to later monitor this update request.
MY_REQUEST_CODE);
} catch (IntentSender.SendIntentException e) {
Toast.makeText(this, R.string.update_failed, Toast.LENGTH_SHORT).show();
}
}
});
}
/**
* Displays the snackbar notification and call to action.
*/
private void popupSnackbarForCompleteUpdate() {
final Snackbar snackbar =
Snackbar.make(
findViewById(R.id.activity_main_layout),
R.string.an_update_has_been_just_downloaded,
Snackbar.LENGTH_INDEFINITE);
snackbar.setAction(R.string.install, view -> mAppUpdateManager.completeUpdate());
snackbar.setActionTextColor(
ContextCompat.getColor(this, R.color.color_snackbar_action_text_color));
snackbar.show();
}
}
To be able to test this functionality, I change the versionCode to a lower number than the one published in the Playstore (2 in this case and the app published with 3)When I run my app, it shows me the dialog to update the app and when I click the update button the update starts and installs without any errors, but when the app restarts, it shows me the update dialog again and the app seems to be not updated, I don't know if this is a bug in my app or i should upload the app to play store to be working correctly.
I am using a app bundle (.aab)
You need a Signed .apk for In App Update. Apps in debug mode will show you update dialog & even download new version, but app wont be installed/updated.

Categories

Resources