Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PackageInstaller "Silent install and uninstall of apps by Device Owner” - Android M Preview

PackageInstaller (https://developer.android.com/reference/android/content/pm/PackageInstaller.html) seems to have been added starting in API 21 (Lollipop), however I have not found any solid code examples on how to install an APK via this API. Any code help would be appreciated.

I’m investigating COSU/Kiosk apps for Android M Preview and was trying to implement the new feature "Silent install and uninstall of apps by Device Owner” (https://developer.android.com/preview/api-overview.html#afw) via the PackageInstaller API.

Found these, but not helpful: How to install/update/remove APK using "PackageInstaller" class in Android L? What's "PackageInstaller" class on Lollipop, and how to use it?

Did not find any Android sample apps either.

Thanks in advance.

like image 704
ken604 Avatar asked Sep 09 '15 07:09

ken604


People also ask

What is a Google Android Package Installer?

packageinstaller is the package name of a pre-installed system app on the Android OS called Package Installer. For reference, Google Chrome's package name is com. android. chrome. Package Installer is the service that runs in the background when you install, update, or uninstall apps on your Android device.

How do I uninstall Package Installer?

Since Package Installer is built into the Android OS, it is not possible for a normal user to remove the package installer from the device. One also cannot uninstall the Package Installer from Android.

What is the app Package Installer used for?

Offers the ability to install, upgrade, and remove applications on the device. This includes support for apps packaged either as a single "monolithic" APK, or apps packaged as multiple "split" APKs. An app is delivered for installation through a PackageInstaller.


2 Answers

This is possible from Android 6.0 and up.

  • Make your app the Device owner.

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());

Complete device owner demo app in this repo.

like image 169
amalBit Avatar answered Oct 23 '22 10:10

amalBit


Figured it out, here's the code:

    try
    {
        PackageInstaller pi = app.getPackageManager().getPackageInstaller();
        int sessId          = pi.createSession(new PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL));

        PackageInstaller.Session session = pi.openSession(sessId);

        // .. write updated APK file to out


        long sizeBytes = 0;
        final File file = new File(filepathApk);
        if (file.isFile())
        {
            sizeBytes = file.length();
        }

        InputStream in = null;
        OutputStream out = null;

        in = new FileInputStream(filepathApk);
        out = session.openWrite("my_app_session", 0, sizeBytes);

        int total = 0;
        byte[] buffer = new byte[65536];
        int c;
        while ((c = in.read(buffer)) != -1)
        {
            total += c;
            out.write(buffer, 0, c);
        }
        session.fsync(out);
        in.close();
        out.close();

        System.out.println("InstallApkViaPackageInstaller - Success: streamed apk " + total + " bytes");

        // fake intent
        Context app = this;
        Intent intent = new Intent(app, AlarmReceiver.class);
        PendingIntent alarmtest = PendingIntent.getBroadcast(app,
                1337111117, intent, PendingIntent.FLAG_UPDATE_CURRENT);

        session.commit(alarmtest.getIntentSender());
        session.close();

    }
    catch (Exception ex)
    {
        ex.printStackTrace();
    }
like image 42
ken604 Avatar answered Oct 23 '22 09:10

ken604