Lets say my Android App version 0.1 is installed currently on the User's phone. Everytime they launch my App I want to check if there is a different version available in the Android Market let's say this version is 0.2. If there is a mismatch between these two version I want to show a dialog box prompting the user to Upgrade the App.
I totally understand there exists a notification procedure from Android Market itself to the users but as far as my Analytics data is concerned it is not very effective in reminding users to upgrade to the new version of the App.
Any insight would be very helpful. Thanks StackOverflowers, you guys rock!
You can use https://appupgrade.dev/ service to force update you mobile apps. You need to create new version for your app versions you want to update in the app upgrade service and select whether you want to force it or just want to let users know that new version is available. See the response has force update true.
If you seriously want to make a notification from your app to ask them to update (so that everyone gets the notification, whatever their Google play settings are, then you will have to make a web service which returns the number of the newest version. You can then compare that inside your app and post a notification.
Click on the app that you want the information and go to Statistics on the left menu. Now, you have a graph on your page. You can select the type of stats you want to see on the top in the middle, keep "Installs on active devices" selected. Right below that, you have another dropdown on "Android version".
Developers can force users to update, say with a full-screen blocking message, force-install the update in the background and restart the app when the download has completed or create their own custom update flows. Android developers can now force users to update their apps.
As of 2019 the best way for updating your app is to use In-app updates provided by Play Core library (1.5.0+). It works for Lollipop and newer, but let's be fair, Kit-Kat is less than 7% as of today and soon will be gone forever. You can safely run this code on Kit-Kat without version checks, it won't crash.
Official documentation: https://developer.android.com/guide/app-bundle/in-app-updates
There are two types of In-app updates: Flexible and Immediate
Flexible will ask you nicely in a dialog window:
whereas Immediate will require you to update the app in order to continue using it with full-screen message (this page can be dismissed):
Important: for now, you can't choose which type of update to roll out in your App Release section on Developer Play Console. But apparently, they will give us that option soon. From what I've tested, currently, we're getting both types available in onSuccessListener
.
So let's implement both types in our code.
In module build.gradle
add the following dependency:
dependencies { implementation 'com.google.android.play:core:1.6.1'//for new version updater }
In MainActivity.class
:
private static final int REQ_CODE_VERSION_UPDATE = 530; private AppUpdateManager appUpdateManager; private InstallStateUpdatedListener installStateUpdatedListener; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); checkForAppUpdate(); } @Override protected void onResume() { super.onResume(); checkNewAppVersionState(); } @Override public void onActivityResult(int requestCode, final int resultCode, Intent intent) { super.onActivityResult(requestCode, resultCode, intent); switch (requestCode) { case REQ_CODE_VERSION_UPDATE: if (resultCode != RESULT_OK) { //RESULT_OK / RESULT_CANCELED / RESULT_IN_APP_UPDATE_FAILED L.d("Update flow failed! Result code: " + resultCode); // If the update is cancelled or fails, // you can request to start the update again. unregisterInstallStateUpdListener(); } break; } } @Override protected void onDestroy() { unregisterInstallStateUpdListener(); super.onDestroy(); } private void checkForAppUpdate() { // Creates instance of the manager. appUpdateManager = AppUpdateManagerFactory.create(AppCustom.getAppContext()); // Returns an intent object that you use to check for an update. Task<AppUpdateInfo> appUpdateInfoTask = appUpdateManager.getAppUpdateInfo(); // Create a listener to track request state updates. installStateUpdatedListener = new InstallStateUpdatedListener() { @Override public void onStateUpdate(InstallState installState) { // Show module progress, log state, or install the update. if (installState.installStatus() == InstallStatus.DOWNLOADED) // After the update is downloaded, show a notification // and request user confirmation to restart the app. popupSnackbarForCompleteUpdateAndUnregister(); } }; // Checks that the platform will allow the specified type of update. appUpdateInfoTask.addOnSuccessListener(appUpdateInfo -> { if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE) { // Request the update. if (appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)) { // Before starting an update, register a listener for updates. appUpdateManager.registerListener(installStateUpdatedListener); // Start an update. startAppUpdateFlexible(appUpdateInfo); } else if (appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE) ) { // Start an update. startAppUpdateImmediate(appUpdateInfo); } } }); } private void startAppUpdateImmediate(AppUpdateInfo appUpdateInfo) { try { appUpdateManager.startUpdateFlowForResult( appUpdateInfo, AppUpdateType.IMMEDIATE, // The current activity making the update request. this, // Include a request code to later monitor this update request. MainActivity.REQ_CODE_VERSION_UPDATE); } catch (IntentSender.SendIntentException e) { e.printStackTrace(); } } private void startAppUpdateFlexible(AppUpdateInfo appUpdateInfo) { try { appUpdateManager.startUpdateFlowForResult( appUpdateInfo, AppUpdateType.FLEXIBLE, // The current activity making the update request. this, // Include a request code to later monitor this update request. MainActivity.REQ_CODE_VERSION_UPDATE); } catch (IntentSender.SendIntentException e) { e.printStackTrace(); unregisterInstallStateUpdListener(); } } /** * Displays the snackbar notification and call to action. * Needed only for Flexible app update */ private void popupSnackbarForCompleteUpdateAndUnregister() { Snackbar snackbar = Snackbar.make(drawerLayout, getString(R.string.update_downloaded), Snackbar.LENGTH_INDEFINITE); snackbar.setAction(R.string.restart, new View.OnClickListener() { @Override public void onClick(View view) { appUpdateManager.completeUpdate(); } }); snackbar.setActionTextColor(getResources().getColor(R.color.action_color)); snackbar.show(); unregisterInstallStateUpdListener(); } /** * Checks that the update is not stalled during 'onResume()'. * However, you should execute this check at all app entry points. */ private void checkNewAppVersionState() { appUpdateManager .getAppUpdateInfo() .addOnSuccessListener( appUpdateInfo -> { //FLEXIBLE: // If the update is downloaded but not installed, // notify the user to complete the update. if (appUpdateInfo.installStatus() == InstallStatus.DOWNLOADED) { popupSnackbarForCompleteUpdateAndUnregister(); } //IMMEDIATE: if (appUpdateInfo.updateAvailability() == UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS) { // If an in-app update is already running, resume the update. startAppUpdateImmediate(appUpdateInfo); } }); } /** * Needed only for FLEXIBLE update */ private void unregisterInstallStateUpdListener() { if (appUpdateManager != null && installStateUpdatedListener != null) appUpdateManager.unregisterListener(installStateUpdatedListener); }
And we're done!
Testing. Please read the docs so you will know how to test it properly with test tracks on Google Play.
Long story short:
Sign your app with the release certificate and upload it to the one of publishing tracks in Developer Play Console under App Releases (alpha/beta/other custom closed track).
In your release track page in the Manage Testers section create and add a list of testers and make sure you checked the checkbox! - this step is optional since your developer account email is also a testers account and you can use it for testing.
Under the list of testers you will find "Opt-in URL" - copy this url and give it to your testers or open it yourself. Go to that page and accept proposition for testing. There will be a link to the app. (You won't be able to search for the app in Play Store so bookmark it)
Install the app on your device by that link.
In build.gradle
increment the version of defaultConfig { versionCode k+1 }
and build another signed apk Build > Generate Signed Bundle / APK... and upload it to your publishing track.
Wait for... 1 hour? 2 hours? or more before it will be published on the track.
CLEAR THE CACHE of Play Store app on your device. The problem is that Play app caches details about installed apps and their available updates so you need to clear the cache. In order to do that take two steps:
7.1. Go to Settings > App > Google PLay Store > Storage > Clear Cache.
7.2. Open the Play Store app > open main menu > My apps & games > and there you should see that your app has a new update.
If you don't see it make sure that your new update is already released on the track (go to your bookmarked page and use it to open your apps listing on the Play Store to see what version is shown there). Also, when your update will be live you'll see a notification on the top right of your Developer Play Console (a bell icon will have a red dot).
Hope it helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With