Auto-Update for (private) Android apps

AndroidGoogle PlayAuto Update

Android Problem Overview


I'm developing a non-public Android app, i.e. the app won't be available in the global Android Market. The app will be installed on a limited number of clients, e.g. by using an apk file. How can I enable an auto-update functionality in this app?

I see different potential options (I do not know if those are technically hard or even impossible to implement or if there are any existing functionalities that can be reused):

  • On each launch the app tests if a new version exists (by requesting a server), if so downloads the new apk and replaces itself with the new version.
  • Use (or develop?) a separated app or service that undertakes the update-check and replacement-process.
  • Use (or develop?) a private market app which has an auto-update option. This option is similar to the second one, but more generic: The market app would be connected to a repository, i.e. it would handle an arbitrary number of (private) apps.

I would prefer option one since the auto-update functionality is included in the app which needs less development efforts.

Android Solutions


Solution 1 - Android

janjonas, in the company I work we had a similar problem with Windows Mobile 6.x, and we use pretty much the same solution pointed by EboMike:

enter image description here

The main app check if it's updated, against a WebService. It receives the current version & the URL from where download the new version, if necessary. The main app then start the Updater app, passing the URL, and quit.

The Updater do the download of the new program, via HTTP, showing to the user the % downloaded. The user can cancel the download anytime, in a controlled way, and the Updater can registry this cancellation.

Since the new app is downloaded, the Updater run the new app, and quit.

Solution 2 - Android

I think option one is the least amount of work for you, and actually the cleanest one too since it will go through the proper channel of using Android's built-in package installer which includes user notification and the option for the user to abort the installation if desired.

You already have it all outlined - check for a new version on a server (would be nice to give the user the option to turn that off), and if there is a new version, you could either just link to the URL with the APK (which will, IIRC, use the browser's download manager to download it), or you could download it with your app and then point the intent to your local file. Using the HTTP link is technically less work and cleaner - the more you let the operating system do, the better - unless there's a reason not to.

Solution 3 - Android

Enabling "Install non-market app" is still needed for any application outside the Google Play. If it not enabled, the installation process is going to ask for it and redirect the user to the Application Settings, and after that, the user can install the app.

Depending on your needs, you can delegate to a third part lib.

Solution 4 - Android

Some of the permissions we'll use to get this done are the following:

<uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Let me explain a bit... The last, WRITE_EXTERNAL_STORAGE, is self-explanatory. With ACCESS_SUPERUSER we'll tell the system that we intend to use root privileges. READ_EXTERNAL_STORAGE will be needed in the future in order for your app to read files on SD card.

Assuming that you have downloaded the file and that all those devices can be rooted (limited number of clients, not on Play, etc.), you could do this:

String filePath = Environment.getExternalStorageDirectory().toString() + "/your_app_directory/your_app_filename.apk";
Process installProcess = null;
int installResult = -1337;

try {
    installProcess = Runtime.getRuntime().exec("su -c pm install -r " + filePath);
} catch (IOException e) {
    // Handle IOException the way you like.
}

if (installProcess != null) {
    try {
        installResult = installProcess.waitFor();
    } catch(InterruptedException e) {
        // Handle InterruptedException the way you like.
    }

    if (installResult == 0) {
        // Success!
    } else {
        // Failure. :-/
    }
} else {
    // Failure 2. :-(
}

Solution 5 - Android

Here might be a very lame method but for some companies, if you believe its applicable, this might be very easy to implement.

  • Create an password screen (passwordActivity) that asks a password to access the application.
  • Once the password is entered, raise a flag (set a boolean value from false to true using sharedpreferences)
  • Place the .apk file on Google Store.
  • Change the password once everyone installs the app, and release a new update on Google Play Store.

Since the software is going to cache the flag value, the password screen won`t show up even the password is change. It will only show up for new installations so might need to repeat the process.

Note: This method might better fit if there is not hundreds of users using the application. And don`t forget this method is also not secure. To sum up, if you are looking a way to keep the application private and have no security concerns, this is what I recommend.

Solution 6 - Android

Update app Make sure that you already have your new apk download on location

void installNewVersion(String location) {

 Intent intent = new Intent(Intent.ACTION_VIEW);
 intent.setDataAndType(Uri.fromFile(new File(location + "app-debug.apk")),
            "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionjanjonasView Question on Stackoverflow
Solution 1 - AndroidtcbrazilView Answer on Stackoverflow
Solution 2 - AndroidEboMikeView Answer on Stackoverflow
Solution 3 - AndroidCelinHCView Answer on Stackoverflow
Solution 4 - AndroidBudimir GromView Answer on Stackoverflow
Solution 5 - Android0014View Answer on Stackoverflow
Solution 6 - AndroidwizmeaView Answer on Stackoverflow