esse
esse

Reputation: 5539

android intercept recent apps button

I have an application meant for children and I do not want them to be able to click the "Recent Apps" button (the one that looks like two rectangles on top of each other). I am taking care of capturing the back button and the home button and I have searched and read a lot about about trying to capture the Recent Apps button, but most say you cannot or the way they do it is very questionable.

The App "Kids Place" pops up a view that says "Action Not Allowed" and redirects you to its home screen if you press the Recent Apps button, this works even if you are in a different app, so how are they doing this?

Upvotes: 12

Views: 13921

Answers (5)

esse
esse

Reputation: 5539

The current best solution I found is the following:

   @Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);

    if (!hasFocus) {
        windowCloseHandler.postDelayed(windowCloserRunnable, 0);
    }
}

private void toggleRecents() {
    Intent closeRecents = new Intent("com.android.systemui.recent.action.TOGGLE_RECENTS");
    closeRecents.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
    ComponentName recents = new ComponentName("com.android.systemui", "com.android.systemui.recent.RecentsActivity");
    closeRecents.setComponent(recents);
    this.startActivity(closeRecents);
}

private Handler windowCloseHandler = new Handler();
private Runnable windowCloserRunnable = new Runnable() {
    @Override
    public void run() {
        ActivityManager am = (ActivityManager)getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
        ComponentName cn = am.getRunningTasks(1).get(0).topActivity;

        if (cn != null && cn.getClassName().equals("com.android.systemui.recent.RecentsActivity")) {
            toggleRecents();
        }
    }
}

This requires that you use <uses-permission android:name="android.permission.GET_TASKS" />

When using this approach when the user presses the recent apps button it will cause your activity will go through the activity lifecycle as follows: onPause -> onWindowFocusChanged -> onResume.

To the user the behavior appears that pressing the recent apps button has no response. NOTE: that I have found that if you press the recent apps button quickly it will display that view for brief time.

Upvotes: 22

Kirill Karmazin
Kirill Karmazin

Reputation: 6736

In the accepted answer you're using ClassName only for Android 4.2 - 4.4. It won't work on 5.0 and higher, or Android 4.1.

Here is the list of ClassNames for main Android versions:

  • Android 4.1: "com.android.internal.policy.impl.RecentApplicationsDialog"
  • Android 4.2 - 4.4: "com.android.systemui.recent.RecentsActivity"
  • Android 5.0 - 7.1: "com.android.systemui.recents.RecentsActivity" ("s" letter was added)

The best solution for you will be to utilize Accessibility Service. Override onAccessibilityEvent() method, filter out ClassNames listed above and do something when you detect this event. For example simulate pressing the 'Home' button. You can do this by making a global action in Accessibility Service.

Upvotes: 2

Miros
Miros

Reputation: 1

If you are interested in disabling all system buttons, may be the option would be to kill system bar completely, see Easy way to hide system bar on Android ICS

Upvotes: 0

Quintin B
Quintin B

Reputation: 5881

The best way I have found is to do this:

public class BaseActivity extends Activity {
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);

            Log.d("Focus debug", "Focus changed !");

        if(!hasFocus) {
            Log.d("Focus debug", "Lost focus !");

            Intent closeDialog = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
            sendBroadcast(closeDialog);
        }
    }
}// all credit goes here: http://www.juliencavandoli.com/how-to-disable-recent-apps-dialog-on-long-press-home-button/

This is not my own code, but this just hides the recent apps list from showing.

Upvotes: 2

djdance
djdance

Reputation: 3209

thanks esse for solution for higher SDK! I missed it.

But in my case I need to duplicate call (or effect is unstable)

        if (SDK>15){
            windowCloseHandler.postDelayed(windowCloserRunnable, 10);
            windowCloseHandler.postDelayed(windowCloserRunnable, 300);
        }

Upvotes: 0

Related Questions