Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android PackageInstaller, re-open the app after it updates itself

I'm developing an app that runs as Device Owner, and I want to build an automatic updater inside it.

To do it I use the PackageInstaller, as I have the privileges to use it due to my Device owner position.

private void installPackage(InputStream inputStream)
        throws IOException {
    notifyLog("Inizio aggiornamento...");
    PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller();
    int sessionId = packageInstaller.createSession(new PackageInstaller
            .SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL));
    PackageInstaller.Session session = packageInstaller.openSession(sessionId);

    long sizeBytes = 0;

    OutputStream out = null;
    out = session.openWrite("my_app_session", 0, sizeBytes);

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

    session.commit(createIntentSender(sessionId));
}

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

The update goes right, but the problem is that it doesn't re-open the app itself after the update, even if I set an IntentSender to broadcast the action LauncherReceiver.START_INTENT to the new app instance (that will bring it on to start).

Here it is my Receiver:

public class LauncherReceiver extends BroadcastReceiver {

    public static final String START_INTENT = "com.aaa.aaa.action.START";

    @Override
    public void onReceive(Context context, Intent intent) {
        System.out.println("CALL RECEIVER!!");
        Intent startIntent = new Intent(context, StartActivity.class);
        startIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TOP);
        context.startActivity(startIntent);
    }
}

And it is registered in my manifest:

    <receiver android:name=".receivers.LauncherReceiver" android:enabled="true" android:exported="true">
        <intent-filter>
            <action android:name="com.aaa.aaa.action.START"></action>
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </receiver>

If I call it by CLI it works:

am broadcast -a com.worldnet.gestitruck.action.START 

So the receiver works but for some reason it doesn't work from the Package Installer session commit. The app close itself due to the upgrade but does't open again.

If I change the createIntentSender to this:

private IntentSender createIntentSender(int sessionId) {
    Intent intent = new Intent(Intent.ACTION_DIAL);
    intent.setData(Uri.parse("tel:0123456789"));
    PendingIntent pendingIntent = PendingIntent.getActivity(context,sessionId,intent,0);
    return pendingIntent.getIntentSender();
}

it actually opens the phone service. So I think the problem reside in the upgrade lifecycle, as the app is not ready when the broadcast action is spawned.

Moreover, I made another try and I created a side app that does nothing but call the broadcast action to my main app, so I can call this side app and with this "double step" it can actually re-open the just updated app. The problem is that I have to install two apps =/

Can anybody help me? Is there a way to re-open the just updated app?

like image 392
Jackie Degl'Innocenti Avatar asked May 12 '17 15:05

Jackie Degl'Innocenti


People also ask

What does used Google Android PackageInstaller mean?

android.content.pm.PackageInstaller. 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.

How do I uninstall package installer app?

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 default installer Android?

PackageInstaller is the default application for Android to interactively install a normal package. PackageInstaller provide user interface to manage applications/packages. PackageInstaller calls InstallAppProgress activity to receive instructions from the user.


1 Answers

Starting from about Android 5 (I don't know the exact API level), Android will send a broadcast Intent with ACTION="android.intent.action.MY_PACKAGE_REPLACED" after your app is updated. Just add

        <intent-filter>
            <action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
        </intent-filter>

to your <receiver> declaration and you should be able to listen for this and restart your app in onReceive().

like image 84
David Wasser Avatar answered Oct 08 '22 02:10

David Wasser