Auto update (download and install latest app version) programmatically - android

Can anyone enlighten me on how to programmatically auto update (download and install latest version) an app with/out opening the said app? then display it in a notification. Do I need a 3rd party platform or etc., Can anyone provide me with an easy-to-understand sample code as a reference.

You could use 3rd party library like AppUpdater and implement it in a background service
Possible implementation:
In activity:
onCreate() {
...
// schedule updater service
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
SchedulerUtils.scheduleNextUpdaterService(applicationContext)
} else {
SchedulerUtils.scheduleRepeatingUpdaterService(applicationContext)
}
}
whole SchedulerUtils: https://gist.github.com/neone35/e463c418bbea0ecc9ac699a7e7f02a1b
Example service: https://gist.github.com/neone35/f8ce2a8d62b81e8abcefd53f06417263
And replace service logoutCourier() with similar to this:
private fun checkForUpdates() {
mAppUpdater = AppUpdater(this)
.setDisplay(Display.DIALOG)
.setDuration(Duration.INDEFINITE)
.setUpdateFrom(UpdateFrom.JSON)
.setUpdateJSON(Constants.AUTO_UPDATE_URL)
.setTitleOnUpdateAvailable(getString(R.string.update_found))
.setContentOnUpdateAvailable(getString(R.string.update_app_descr))
.setButtonUpdate(getString(R.string.download))
//.setButtonDismiss(getString(R.string.postpone))
.setButtonDismiss("")
.setIcon(R.drawable.ic_logo)
.setButtonDoNotShowAgain("")
.setCancelable(false)
//.showAppUpdated(true) // to test out - show even when no update
mAppUpdater.start()
}

Related

Using InApp Update API mode Flexible

I was using In App Update API with update type as Flexible using below code
appUpdateManager.startUpdateFlowForResult(
appUpdateInfo,
AppUpdateType.FLEXIBLE,
this,
APP_UPDATE_REQUEST_CODE)
Where the update type is provided as AppUpdateType.FLEXIBLE.
It showcases the correct UI where it provides option for users to either select Update or No Thanks.
As showcased in below image.
However clicking on Update actually showcases a fullscreen UI with progressbar generally associated with Immediate updated instead of performing the update in background.
Using play code SDK version 1.8.X
// Rate this app
// So, make sure you also include that repository in your project's build.gradle file.
implementation 'com.google.android.play:core:1.8.0'
// For Kotlin users also import the Kotlin extensions library for Play Core:
implementation 'com.google.android.play:core-ktx:1.8.1'
Does anyone has a idea why this would be happening?
Thanks in Advance.
Maybe your problem is
override fun onResume() {
super.onResume()
appUpdateManager
.appUpdateInfo
.addOnSuccessListener {
// If an in-app update is already running, resume the update.
if (it.updateAvailability() == UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS)
startUpdate(it, AppUpdateType.IMMEDIATE) // <<-- !!HERE!!
// If the update is downloaded but not installed, notify the user to complete the update.
if (it.installStatus == InstallStatus.DOWNLOADED) {
nav_progress_download.hide()
popupSnackbarForCompleteUpdate()
}
}
}
When you click Update button, onResume is called.
And updateAvailability() of AppUpdateType.FLEXIBLE is same as UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS
Check this...
How to know the AppUpdateType at the origin of the DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS update availability?
https://issuetracker.google.com/issues/153785560

Flexible In-App update installed while app is in background

I'm using Android Play Core Library's new feature In-App Updates.
So the documentation says that for a Flexible In-App Update, I need an InstallStateUpdatedListener which would listen for when the update is downloaded in the background, and then we need to show a UI or in my case a Snackbar to the user, describing that the user now needs to install the already downloaded update. This works fine when I'm in the foreground for the whole time, but when I go to the background before the in-app update is downloaded and then return to the foreground of the app after some time, my app automatically gets updated without showing any UI to the user asking them to install the update. This should not happen ideally as per the docs.
I've tried removing all kind of listeners, commenting out the code which completes the update, but to no avail.
appUpdateManager = AppUpdateManagerFactory.create(getAppContext());
if (appUpdateInfo.updateAvailability() != UpdateAvailability.UPDATE_AVAILABLE && appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)) {
final InstallStateUpdatedListener listener =
new InstallStateUpdatedListener() {
#Override
public void onStateUpdate(InstallState installState) {
if (installState.installStatus() ==
InstallStatus.DOWNLOADED) {
showUpdateCompletedSnackbar();
}
}
};
appUpdateManager.registerListener(listener);
try {
Log.d("BaseApp","Starting Flexible in app update");
appUpdateManager.startUpdateFlowForResult(
appUpdateInfo,
AppUpdateType.FLEXIBLE,
getActivity(),
2000);
} catch (IntentSender.SendIntentException exception) {
Log.e("BaseApp",exception);
}
}
private static void showUpdateCompletedSnackbar() {
Snackbar snackbar =
Snackbar.make(getContainer(),
appContext.getString(R.string.in_app_update_snackbar_text),
Snackbar.LENGTH_INDEFINITE);
snackbar.setAction("INSTALL", new View.OnClickListener() {
#Override
public void onClick(View v) {
appUpdateManager.completeUpdate();
}
});
snackbar.setActionTextColor(
ContextCompat.getColor(getAppContext(), R.color.blue));
snackbar.show();
}
Okay, so actually the documentation was not that clear about this, but one caveat in the Flexible In-app update is that, once you start downloading the in-app update and you continue using the app, the update will download in the background and then will notify the user through a UI that the Update has been downloaded and we need to install the update (this showing of UI and all will be handled by the developer).
But the second case, of which I had an issue, was that what if, before the update is downloaded, I move my app to the background. In that case, if the update is downloaded while the app is in the background, then it will install the update too without informing the user to the new version and then when you take your app to the foreground, you'll see the updated app, instead of any UI.
The Flexible update was for this only, that if the user is using the app, the update will be downloaded in the background without the user having the trouble to close the app and updating it leaving the work which they were doing in the app, and then post the update is downloaded the user will have a choice to finally install the update using a UI shown to them whenever they want or when they complete their ongoing work in the app.
There are more caveats in the app and this medium article would be helpful for you all to see more of the edge cases https://proandroiddev.com/android-in-app-updates-common-pitfalls-and-some-good-patterns-9024988bbbe8

AppsFlyer SDK Integration Test failed on app, but non-organic test data is reflected on the Dashboard

Trying to integrate the AppsFlyer SDK for Android, I've followed all the steps indicated in the AppsFlyer guide. Initially, the dependency that was stated is:
implementation 'com.appsflyer:af-android-sdk:4+#aar'
But for some reason, it wasn't pointing to the latest version on it's own, making the init() version not visible. And so I instead went ahead and adjusted it to version 4.8.15 (currently the latest version), which worked as expected in the guide.
After adding the required permissions (with the optional permission) and the BroadcastReceiver (I don't have any other receivers for the referrer so I only used the SingleInstallBroadcastReceiver), I implemented the initialization on the app's Application class like so:
public class MyApp extends Application {
private static final String AF_DEV_KEY = "DEV_KEY_FROM_CONSOLE_HERE";
#Override
public void onCreate() {
super.onCreate()
initAppsFlyer();
}
public void initAppsFlyer() {
final AppsFlyerConversionListener listener = new AppsFlyerConversionListener() {
#Override
public void onInstallConversionDataLoaded(Map<String, String> conversionData) {
}
#Override
public void onInstallConversionFailure(String errorMessage) {
}
#Override
public void onAppOpenAttribution(Map<String, String> attributionData) {
}
#Override
public void onAttributionFailure(String errorMessage) {
}
};
AppsFlyerLib.getInstance().init(AF_DEV_KEY, listener, this);
AppsFlyerLib.getInstance().startTracking(this);
}
}
The manifest is pointing to the MyApp application class for sure. So that's it. The initial setup is complete. Time for the SDK Integration test as per the guide.
So I installed the app directly from Android Studio to my device, downloaded SDK Integration test app, whitelisted the device, and selected the name of the app as mentioned in the test guide. Every step followed accordingly.
Clicked on SDK Integration Testing...
Checking configuration...
Testing your app..
*app opens*
*closes*
*opens again*
Testing your app..
Checking configuration...
..
X Oops..
This app can not be monitored. Please make sure that:
You are using a supported AppsFlyer SDK version.
AppsFyler's BroadcastReceiver is configured.
startTracking() is placed in the MainActivity
It's the latest version. So it should work.
Copy pasted the receiver. Tried removing it and then re-run the test, it showed the missing receiver error. Pasted it back in.
I'm calling startTracking() in the actual application class. But what the heck. I gave it a try, called it in the MainActivity.onCreate() same result.
I have no idea what is causing the failure in the test. Not much to go on from as well since there's no details on how to debug it further. However, I checked the Dashboard, and there it is. Non-Organic install data counted.
Now I'm confused. Is there an issue with the integration or with the SDK integration test app?

preparing SMS app for Android KitKat

in agreement with the recent post from Android Developers http://android-developers.blogspot.pt/2013/10/getting-your-sms-apps-ready-for-kitkat.html ,I was trying to prepare my app to the new android version, but encountered a problem with the part they suggest to create a dialog to let the user set the app as the default application to handle SMS's :
Android Developers Post
public class ComposeSmsActivity extends Activity {
#Override
protected void onResume() {
super.onResume();
final String myPackageName = getPackageName();
if (!Telephony.Sms.getDefaultSmsPackage(this).equals(myPackageName)) {
// App is not default.
// Show the "not currently set as the default SMS app" interface
View viewGroup = findViewById(R.id.not_default_app);
viewGroup.setVisibility(View.VISIBLE);
// Set up a button that allows the user to change the default SMS app
Button button = (Button) findViewById(R.id.change_default_app);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent intent =
new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME,
myPackageName);
startActivity(intent);
}
});
} else {
// App is the default.
// Hide the "not currently set as the default SMS app" interface
View viewGroup = findViewById(R.id.not_default_app);
viewGroup.setVisibility(View.GONE);
}
}
}
the code itself in pretty much straightforward, but I'm unable to access to Telephony.Sms.getDefaultSmsPackage because it says that Telephony cannot be resolved, and I can't find any import or declaration that would fix that.
Can anyone please help?
android.provider.Telephony simply doesn't exist yet (as of API 18 - 4.3).
This class will be added in 4.4 (presumably API 19), and that blog post is highlighting the changes that you should make once the new API is released so you aren't surprised when the time comes.
From the end of the post:
To help you make the changes, we'll soon be providing the necessary SDK components for Android 4.4 that allow you to compile and test your changes on Android 4.4.
Don't forget that you should wrap this code in an API version check so you don't run into issues with older versions that don't have this class.
this change will break all the SMS blocking apps.
"Note that—beginning with Android 4.4—any attempt by your app to abort the SMS_RECEIVED_ACTION broadcast will be ignored so all apps interested have the chance to receive it."
Do you think there is a way to go around this?!
Maybe at least on Root?
Apparently there is with root access. The latest version Cerberus app claim to be doing this.
Now, if only I knew how they do it :(

How to notify users about an Android app update?

I've built an Android app which is now on Play Market. From time to time, I make updates to it, and I'd like to let users know that a new version is available.
How can I send an update notification to the users of the app?
You do not need to do anything specific for this. Since you mentioned that you are using Google Play, the update notification is taken care of by Google Play.
You just need to update the APK with a higher versionCode and Google Play should do the rest.
Update 2020: now you can use in-app updates mechanism
Docs: https://developer.android.com/guide/playcore/in-app-updates
You can do this in a lot of ways, depending on when you want the user to be able to see that there is an update available.
If you want the user to know about the update when the app is started, just create a utility method (inside the onCreate method of your main/first Activity) that checks if a newer version is available in Google Play. If it does, display an alert dialog with a relevant message and an Intent which opens your app in Google Play when the user clicks on the positive button of the alert dialog.
If you are updating the app regularly, the user will keep getting this alert dialog every time the app is started and hence, may get irritated. Thus, this is not the best approach.
If you want the user to get a notification on the phone (and not when the user starts the app), you can use the AlarmManager class to schedule a background service which checks for an update at regular intervals. If the service finds that an upgrade is actually available, publish a notification with an intent that opens your app in Google Play.
Of course, another approach is to leave it to the OS itself. If the user has not set the "Automatically update" preference for your app, the user will get a notification regularly about an update available for your, as well as any other apps.
But not all users enable background data on their devices, so this is not completely reliable.
In the end, you must respect the users preferences. If the user does not want to automatically update the app, or does not want to see a nagging dialog box whenever he/she starts your app, don't alert the user about the update.
In my opinion, you should create a PreferenceActivity that has a preference like "Check for updates regularly", which can be set from within your app. If it is set, do the needful in your own service. May be even give the user an option to select the period after which the service will check for an update.
I hope this helps!
It is up to each phone owner if she wants to be notified on new versions by google play, and it's up to each phone's manufacturer if this is to be enabled by default.
If you however are in a situation where you "require" the user to update to the new version to be compatible with some form of protocol or you have a similar similar use case where you have a server component somewhere, you might want to notify the user of a potential version conflict in the UI based on information about what is the latest version.
This information can be grabbed directrly from google play, however as #Yahel pointed out in this question google play is a closed system with no official API, and you might need to rely on unpredictable undocumented API. There is an unofficial API library here.
This leaves only one option, which is to keep this information on your own server. If you allready have a serverside this might be trivial. Simply put the latest version in an XML file and retreive that at regular intervals from your code. If the version code is outdated, trigger the notification in your UI. Here is an example implementation for doing that.
I hope this was helpful :-)
I know this is an old question but still if people are coming here to check this question, Google is now providing official support for in-app notification for application update the full documentation can be found here
Use this : https://www.push-link.com/
Google Play will notify your users that the app has an update via the notification bar.
If you set up a notification system yourself, the likely result would be that, although the user is notified of an update sooner, when he/she goes to Google Play to install the update it will not yet be available. This is because there is a lag from the time you "publish" an app/update and the time until it appears on Play. Telling your users that there is an update when the update is unavailable would only lead to confusion and frustration.
My advice: stick with Google's update notification system and don't worry about trying to get users an update 15 minutes sooner.
Some people use Android Cloud-to-Device Messaging (C2DM) to notify their users of updates. I don't think I'd bother, since I think Google Play does a pretty good job of notifying me of updates already, and implementing C2DM adds a whole new dimension to writing an app (because it requires a server component). But maybe you want to offer your users a richer update notification than you get from Google Play.
#Davek804's answer above is wrong. android:versionCode is an integer value that represents the version of the application code, relative to other versions, so using "1.5b" there is incorrect. Use "15" (or "150") instead
Found a nice solution for your problem:
Let´s say you want to check for version updates manually on app start and notify your users for the new Update.
Step 1: Download android-market-api (not the .jar file, the full project!)
Step 2: After importing it to eclipse, write in your activity the following code:
MarketService ms = new MarketService(activity);
ms.level(MarketService.REVISION).checkVersion();
now, we need to modify MarketService.java, because it seems to be broken.
Step 3: rewrite callback method and add the following methods
protected void callback(String url, JSONObject jo, AjaxStatus status){
if(jo == null) return;
String googlePlayversion = jo.optString("version", "0");
String smartphone_version = "";
PackageInfo pInfo;
try {
pInfo = act.getPackageManager().getPackageInfo(act.getPackageName(), 0);
smartphone_version = pInfo.versionName;
} catch (NameNotFoundException e) {}
boolean new_version_avaible = compare(smartphone_version, googlePlayversion);
if(new_version_avaible){
showUpdateDialog(jo);
}
}
private static boolean compare(String v1, String v2) {
String s1 = normalisedVersion(v1);
String s2 = normalisedVersion(v2);
int cmp = s1.compareTo(s2);
String cmpStr = cmp < 0 ? "<" : cmp > 0 ? ">" : "==";
System.out.printf("result: "+"'%s' %s '%s'%n", v1, cmpStr, v2);
if(cmpStr.contains("<")){
return true;
}
if(cmpStr.contains(">")||cmpStr.contains("==")){
return false;
}
return false;
}
public static String normalisedVersion(String version) {
return normalisedVersion(version, ".", 4);
}
public static String normalisedVersion(String version, String sep, int maxWidth) {
String[] split = Pattern.compile(sep, Pattern.LITERAL).split(version);
StringBuilder sb = new StringBuilder();
for (String s : split) {
sb.append(String.format("%" + maxWidth + 's', s));
}
return sb.toString();
}
If you want to test it, modify googlePlayversion string to a higher version than your local one.
The source comparison method I used is from How do you compare two version Strings in Java?
There is also a very good approach for checking version and give user in app notification or when you want to forcefully update the application if you can decide the first connection of your app with the server.In the response of the first request you can send the current version of app stored on your server and then on client end you can take the appropriate action.
Advantages of this approach-:
1-No extra request for version no.
2-It is also applicable if you are downloading the app other than the google playstore.
3-you can also use this idea if you want to check the version at particular operation of your app ex- transaction(if you add a new payment gateway.)
Don't know if you want to walk extra miles. You can try out google appengine, which serve version number for your app and let you android app check the appengine to see if there is a new version when the application is launched. That way, it does not matter if your app is in google play market nor amazon app store nor if it is installed on the phone without those two via sideloading. It is not very hard to setup appengine just for serving your application version in json. Replace "Hello World" string with your app version name ...
This can be using a simple webservice just this is one of the way to acheive.
i.e., when ever the app launch hit that webservice with the current version of the user app and on the server you need to check whether any new version is available or not(Must maintain the newest version of the app) and send the corresponding response to the user. If any newer version is available prompt the user to download the newest version of the application and if no newest version is available then allow the user to continue.
Hope so atleast something must be useful to you.
There are two models that are basically used to tackle the issue.
Pull Based
Push Based
Its depends on the architecture or design of particular system that determines whether pull based or push mechanism is used.
For pull based model you just make one http request to concerned server regarding the new version of application. The current application version no can be saved in SQLLite in android application. This can be given to server and new version can be checked against it at the server.
For push mechanism you can use C2DM push notification service.. details of which are given at http://code.google.com/android/c2dm/
Generally when you upload a new application to Google play most users get a notification about an update, some will have the app automatically downloaded to their device, depending on the settings they have.
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. You could use Google App Engine ( https://developers.google.com/appengine/) because that works with eclipse and java, which you probably already have.
I would not recommend this approach as it creates a lot of work for you to provide something that most users have already got.
i think this is too late but it can be help some one
public enum AppVersionUpgradeNotifier {
INSTANCE;
private static final String TAG = "AppVersionUpdateManager";
private static final String PREFERENCES_APP_VERSION = "pref_app_version_upgrade";
private static final String KEY_LAST_VERSION = "last_version";
private SharedPreferences sharedPreferences;
private VersionUpdateListener versionUpdateListener;
private boolean isInitialized;
public static synchronized void init(Context context, VersionUpdateListener versionUpdateListener) {
if (context == null || versionUpdateListener == null) {
throw new IllegalArgumentException(TAG + " : Context or VersionUpdateListener is null");
}
if (!INSTANCE.isInitialized) {
INSTANCE.initInternal(context, versionUpdateListener);
} else {
Log.w(TAG, "Init called twice, ignoring...");
}
}
private void initInternal(Context context, VersionUpdateListener versionUpdateListener) {
this.sharedPreferences = context.getSharedPreferences(PREFERENCES_APP_VERSION, Context.MODE_PRIVATE);
this.versionUpdateListener = versionUpdateListener;
this.isInitialized = true;
checkVersionUpdate();
}
private void checkVersionUpdate() {
int lastVersion = getLastVersion();
int currentVersion = getCurrentVersion();
if (lastVersion < currentVersion) {
if (versionUpdateListener.onVersionUpdate(currentVersion, lastVersion)) {
upgradeLastVersionToCurrent();
}
}
}
private int getLastVersion() {
return sharedPreferences.getInt(KEY_LAST_VERSION, 0);
}
private int getCurrentVersion() {
return BuildConfig.VERSION_CODE;
}
public void upgradeLastVersionToCurrent() {
sharedPreferences.edit().putInt(KEY_LAST_VERSION, getCurrentVersion()).apply();
}
public interface VersionUpdateListener {
boolean onVersionUpdate(int newVersion, int oldVersion);
}
}
use it on
public class MyApplication extends Application implements AppVersionUpgradeNotifier.VersionUpdateListener {
#Override
public void onCreate() {
super.onCreate();
AppVersionUpgradeNotifier.init(this,this);
}
#Override
public boolean onVersionUpdate(int newVersion, int oldVersion) {
//do what you want
return true;
}
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1.5b"
android:versionName="1.5b">
When you re-upload your app to Google Play, if these two attributes have been changed from the previous upload, Google Play will automatically send notifications to users who have installed your app. This is the AndroidManifest file.

Categories

Resources