Search code examples
androidandroid-activitybackground-process

Pushing other Android activity to foreground


From a package A, I triggered running service from privileged package B. Package B performs an update of package A. Target device is using Android 9 (API Level 28). The update is successful (app version code has changed). But my issue is that after the update, package A is in background ; on my device, it is on the background app list, I have to manually press on it to bring it to the foreground.

I would like it to come back to the foreground after install.

What I tried:

  • Sending a BroadcastIntent from package B to package A after install ; it looks like the intent is not received on package's A BroadcastReceiver (maybe due to the fact that it is in background or the app has been updated?)

  • After install this command works if I run it manually through adb: "$ adb shell am start -n "com.mma.mainapp/com.mma.mainapp.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER". So I tried performing it from package B after install after a delay: "am start -n "$mainAppPackage/$mainAppPackage.MainActivity" -a ${Intent.ACTION_MAIN} -c ${Intent.CATEGORY_LAUNCHER}".runCommand(File(".")).

  • I also tried performing this from package B after install after a delay with correct permission but package A is not listed:

    private fun moveToFront(mainAppPackage: String) {
        val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
        val recentTasks = activityManager.getRunningTasks(Int.MAX_VALUE)//activityManager.appTasks.map { it.taskInfo }
        for (i in recentTasks.indices) {
            log("PUSH Application executed : "
                    + recentTasks[i].baseActivity.toShortString()
                    + "\t\t ID: " + recentTasks[i].id + "")
            if (recentTasks[i].baseActivity.toShortString().indexOf(mainAppPackage) > -1) {
                log("PUSH TO FRONT : "
                        + recentTasks[i].baseActivity.toShortString()
                        + "\t\t ID: " + recentTasks[i].id + "")
                activityManager.moveTaskToFront(recentTasks[i].id, ActivityManager.MOVE_TASK_WITH_HOME)
            }
        }
    }
    
  • Overriding package A's Application::onCreate(), to bring activity to front: val i = Intent(context, MainActivity::class.java); i.setAction(Intent.ACTION_MAIN); i.addCategory(Intent.CATEGORY_LAUNCHER); context.startActivity(i) // working in isolation but onCreate is not trigerred after apk update.

Is there some way to perform this task? (this should be doable, given package B is privileged (installed under /system/priv-app on rooted device using the standard procedure) and has the same signature as package A)


Solution

  • You need to start an Activity after the installation is complete. It is possible you start activity before installation is complete. To get app A update completion register a broadcast receiver like this:

    private static final IntentFilter appUpdateIntentFilter = new IntentFilter();
    static {
        appUpdateIntentFilter.addDataScheme("package");
        appUpdateIntentFilter.addAction(Intent.ACTION_PACKAGE_ADDED); 
    }
    
    private AppUpdateReceiver appUpdateReceiver = new AppUpdateReceiver();
    

    then if you are starting the download from app B's service, register in onCreate and stop in onDestroy of the service:

    private void registerBroadcastReceiver() {
        try {
            registerReceiver(appUpdateReceiver, appUpdateIntentFilter);
        } catch (IllegalArgumentException e) {
            // already registered
        }
    }
    
    private void unregisterBroadcastReceiver() {
        try {
            unregisterReceiver(appUpdateReceiver);
        } catch (IllegalArgumentException e) {
            // already unregistered
        }
    }
    
    class AppUpdateReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            //if packageName is for app A then start an activity of app A
            int uid = intent.getIntegerExtra(Intent.EXTRA_UID);
            String appName = context.getPackageManager().getNameForUid(uid);
            if(appName.equals("com.appA.PackageName")) {
                //start an activity of app A 
            }
        }
    }