OTA updates for Device Owner Android Application(Kiosk mode)

2.7k views Asked by At

I am able to make my app, the device owner app through NFC as mentioned here. Now I want to update my app over the air, but I couldn't find a method without rooting.

Google is providing many options for enterprises to develop apps as mentioned here, but nowhere providing a way to update the application through OTA.

Looking for a solution.

5

There are 5 answers

1
coder On

Create a service to background check for update. if update available download apk file and write it on some where like sdcard. wait some seconds to write completely flush. then call following code to install your new apk.

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(fileName)), "application/vnd.android.package-archive");
startActivity(intent);

fileName is path of your new apk file on sd card.

2
Michael Roland On

This is just pure speculation as I've never tried to use the package installer API myself:

You could try to set an installer package for your device owner app (using PackageManager.setInstallerPackageName()). This installer package would need to be a separate APK signed with the same certificate as the device owner APK.

getPackageManager().setInstallerPackage("<device.owner.package.name>", "<installer.package.name>");

From your installer APK, you could then use PackageInstaller to prepare an update:

PackageInstaller pi = getPackageManager().getPackageInstaller();
int sessId = pi.createSession(new PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL));
PackageInstaller.Session session = pi.openSession(sessId);
OutputStream out = session.openWrite("app");
// .. write updated APK file to out
session.fsync(out);
session.commit(...);
session.close();

I'm not sure if this silently installs your update though (or if that works at all in the way I would have expected).

1
Michael Roland On

You could use Play Store to provide updates for your app:

  1. Provision device owner app through NFC, just as you already did.

  2. Provide an updated version (same package name, same signature, higher version number) of your device owner app on Play Store.

  3. In the Play Store app on your device, search for your Play Store version of the app and install the update.

  4. Activate auto-updates for your device owner app in Play Store (on the Play Store page of your app, click menu (three dots) and activate the checkbox for auto-update.

That's quite some effort for the provisioning phase, but the device should receive future updates automatically.

0
rupesh jain On

I guess you might want to become an EMM/MDM partner app-it is similar to device owner app but with enhanced privileges and APIs. Normally OEMs like Samsung/HTC provides hidden APIs to the MDM partner apps for upgrading apps.I am not sure whether Android for Work also provides this api.

For eg: OEMs provides an api called updatePackage(String packageName) which can be use by MDM client on the device to update the package.You can use this API to update the Device Owner App too.

0
Joey On

I stumbled across this question and wanted to add that the answer of a question from a link in the comments has been expanded and it is now possible to silently install the app, as long as your App is Device Owner:

https://stackoverflow.com/a/37153867/7173050

Here the part, from Android 6.0 and up: Once your app gets the Device owner permission, we can install, uninstall and update silently without any user intervention.

public static boolean installPackage(Context context, InputStream in, String packageName) throws IOException {
    PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller();
    PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
        PackageInstaller.SessionParams.MODE_FULL_INSTALL);
    params.setAppPackageName(packageName);
    // set params
    int sessionId = packageInstaller.createSession(params);
    PackageInstaller.Session session = packageInstaller.openSession(sessionId);
    OutputStream out = session.openWrite("COSU", 0, -1);
    byte[] buffer = new byte[65536];
    int c;
    while ((c = in.read(buffer)) != -1) {
        out.write(buffer, 0, c);
    }
    session.fsync(out);
    in.close();
    out.close();

    session.commit(createIntentSender(context, sessionId));
    return true;
}



private static IntentSender createIntentSender(Context context, int sessionId) {
    PendingIntent pendingIntent = PendingIntent.getBroadcast(
             context, sessionId, new Intent(ACTION_INSTALL_COMPLETE), 0);
    return pendingIntent.getIntentSender();
}

Uninstall:

String appPackage = "com.your.app.package";
Intent intent = new Intent(getActivity(), getActivity().getClass());
PendingIntent sender = PendingIntent.getActivity(getActivity(), 0, intent, 0);
PackageInstaller mPackageInstaller = getActivity().getPackageManager().getPackageInstaller();
mPackageInstaller.uninstall(appPackage, sender.getIntentSender());

And last but not least the link: https://github.com/android/platform_frameworks_base/blob/marshmallow-release/services/core/java/com/android/server/pm/PackageInstallerSession.java