Intercept Android Home/Recent button click events using AOSP

Post date: Nov 28, 2016 10:11:31 AM

Requirements:

I've been put in the situation to intercept the Home/Recent button click events and show the confirmation alert before user try to exit the current activity. We all knows that Home/Recent button event intercepting is against the android recommendation and doesn't have valid public API's to do so.

However I can't explain this to client, because we were working on AOSP level code changes and we are free to make any changes in android open source layer to accomplish this task :-) ;-)

Requirement analysis:

I've been trying to identify the class which handling the Home/Recent button click events and plan to intercept those event and post custom broadcast action and activities can listen for those events

Precondition:

I'm working on Android 4.4.2

http://androidxref.com/4.4.2_r2/

Intercept Home Button

To intercept home button, we should work on

public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) { in

http://androidxref.com/4.4.2_r2/xref/frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java

//Add below lines at the declaration

static final String ACTION_INTERCEPT_ON = "com.android.internal.policy.statusbar.intercept.on";

static final String ACTION_INTERCEPT_OFF = "com.android.internal.policy.statusbar.intercept.off";

static final String ACTION_INTERCEPT_HOME = "com.android.internal.policy.statusbar.intercept.home";

static final String ACTION_ALLOW_PROCEED_HOME = "com.android.internal.policy.statusbar.intercept.allow.home";

private boolean mIsHomePressedIntercepted = false;

//Add below lines after Line number : 930

register to intercept Home button click events

                    filter = new IntentFilter();

                    filter.addAction(ACTION_INTERCEPT_OFF);

                    filter.addAction(ACTION_INTERCEPT_ON);

                    filter.addAction(ACTION_ALLOW_PROCEED_HOME);

                    context.registerReceiver(mHomeReceiver, filter);

//Replace Line 2023 and 2024 with below codes

 

   if (mIsHomePressedIntercepted) {

                                sendBroadCastMessage(ACTION_INTERCEPT_HOME);

                            } else {

                                // Go home!

                                launchHomeFromHotKey();

                            }

//Add below lines at line number 4214

// To intercept the Home button click event

                BroadcastReceiver mHomeReceiver = new BroadcastReceiver() {

                    @Override

                    public void onReceive(Context context, Intent intent) {

                        if (ACTION_ALLOW_PROCEED_HOME.equals(intent.getAction())) {

                            // Go home!

                            launchHomeFromHotKey();

                        } else if (ACTION_INTERCEPT_OFF

                                .equals(intent.getAction())) {

                            mIsHomePressedIntercepted = false;

                        } else if (ACTION_INTERCEPT_ON.equals(intent.getAction())) {

                            mIsHomePressedIntercepted = true;

                        }

                    }   

                };

//Added bottom of the class

                private void sendBroadCastMessage(String action){

                    Intent in = new Intent(action);

                    mContext.sendBroadcast(in);

                } 

To intercept Recent button events:

Suppose to working below mentioned source file to intercept the Recent button events

http://androidxref.com/4.4.2_r2/xref/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java

//Add below code on declaration

public static final String ACTION_INTERCEPT_ON = "com.android.internal.policy.statusbar.intercept.on";

public static final String ACTION_INTERCEPT_OFF = "com.android.internal.policy.statusbar.intercept.off";

public static final String ACTION_ALLOW_PROCEED_RECENT = "com.android.internal.policy.statusbar.intercept.allow.recent";

public static final String ACTION_ALLOW_PROCEED_HOME = "com.android.internal.policy.statusbar.intercept.allow.home";

public static final String ACTION_INTERCEPT_RECENT = "com.android.internal.policy.statusbar.intercept.recent";

private boolean mInterceptIsEnabled = false;

//After line number 645

filter.addAction(ACTION_INTERCEPT_OFF);

filter.addAction(ACTION_INTERCEPT_ON);

filter.addAction(ACTION_ALLOW_PROCEED_RECENT);

//Export line number 746 and 747 as new function as mentioned blow

private void onClickRecentButton() {

  Log.d(TAG, ": Recent button has been clicked");

  awakenDreams();

  toggleRecentApps();

}

//Replace line number 746 and 747 with below code

if (mInterceptIsEnabled) {

 sendBroadCastMessage(ACTION_STATUSBAR_INTERCEPT_RECENT);

} else {

 onClickRecentButton();

}

//Add below code for receiver handling 2487

else if (ACTION_STATUSBAR_INTERCEPT_ON.equals(action)) {

 mInterceptIsEnabled = true;

} else if (ACTION_STATUSBAR_INTERCEPT_OFF.equals(action)) {

 mInterceptIsEnabled = false;

 } else if (ACTION_STATUSBAR_ALLOW_PROCEED_RECENT.equals(action)) {

  onClickRecentButton();

}

//Add bottom of the class

private void sendBroadCastMessage(String action){

        Intent in = new Intent(action);

        mContext.sendBroadcast(in);

}

Create BaseActivity to handle all this events:

Create a common base activity to intercept the Home/Recent button actions. Whoever want to intercept this events can extent this BaseActivity and have to setInterceptStatusBar(true) at onCreate() method

import android.app.Activity;

import android.content.BroadcastReceiver;

import android.content.Context;

import android.content.Intent;

import android.content.IntentFilter;

import android.util.Log;

public class BaseActivity extends Activity {

public static final String ACTION_INTERCEPT_ON = "com.android.internal.policy.statusbar.intercept.on";

public static final String ACTION_INTERCEPT_OFF = "com.android.internal.policy.statusbar.intercept.off";

public static final String ACTION_ALLOW_PROCEED_RECENT = "com.android.internal.policy.statusbar.intercept.allow.recent";

public static final String ACTION_ALLOW_PROCEED_HOME = "com.android.internal.policy.statusbar.intercept.allow.home";

public static final String ACTION_INTERCEPT_HOME = "com.android.internal.policy.statusbar.intercept.home";

public static final String ACTION_INTERCEPT_RECENT = "com.android.internal.policy.statusbar.intercept.recent";

private static final String TAG = "BaseActivity";

private boolean interceptStatusBar;

public boolean isInterceptStatusBar() {

    return interceptStatusBar;

}

protected void onHomePressed() {

    Log.d(TAG, "onHomePressed");

    sendBroadCastMessage(ACTION_ALLOW_PROCEED_HOME);

}

protected void onRecentPressed() {

    Log.d(TAG, "onRecentPressed");

    sendBroadCastMessage(ACTION_ALLOW_PROCEED_RECENT);

}

private void sendBroadCastMessage(String action) {

    Log.d(TAG, "sendBroadCastMessage :" + action);

    Intent in = new Intent(action);

    sendBroadcast(in);

}

@Override

protected void onDestroy() {

    unRegisterIntercept();

    super.onDestroy();

   

}

void unRegisterIntercept() {

    sendBroadCastMessage(ACTION_INTERCEPT_OFF);

    unregisterReceiver(interceptRecevier);

}

@Override

protected void onPause() {

    // TODO Auto-generated method stub

    super.onPause();

    unRegisterIntercept();

   

}

@Override

protected void onResume() {

    // TODO Auto-generated method stub

    super.onResume();

    registerIfRequired();

   

}

public void setInterceptStatusBar(boolean interceptStatusBar) {

    this.interceptStatusBar = interceptStatusBar;

    registerIfRequired();

}

    private void registerIfRequired() {

        if (this.interceptStatusBar) {

        Log.d(TAG, "Register to notifications");

        sendBroadCastMessage(ACTION_INTERCEPT_ON);

        IntentFilter filter = new IntentFilter();

        filter.addAction(ACTION_INTERCEPT_HOME);

        filter.addAction(ACTION_INTERCEPT_RECENT);

        registerReceiver(interceptRecevier, filter);

    } else {

        unRegisterIntercept();

    }

    }

BroadcastReceiver interceptRecevier = new BroadcastReceiver() {

    @Override

    public void onReceive(Context arg0, Intent intent) {

        String action = intent.getAction();

        Log.d(TAG, "Action received: " + action);

        if (action.equals(ACTION_INTERCEPT_HOME)) {

            onHomePressed();

        } else if (action.equals(ACTION_INTERCEPT_RECENT)) {

            onRecentPressed();

        }

    }

};

}

Finally!, Way to access in the needed activity

public class MainActivity extends Activity{

@Override

protected void onCreate(Bundle savedInstanceState) {

 super.onCreate(savedInstanceState);

   setInterceptHardButton(true);

}

protected void onHomePressed() {

    // TODO Auto-generated method stub

    Log.d(TAG, "Home button has been intercepted");

}

@Override

protected void onRecentPressed() {

    // TODO Auto-generated method stub

    Log.d(TAG, "Recent button has been intercepted");

}

}

}

Hope it would have save your time, kindly feel free to shot a comments if you required more assistance!!!

Have a great coding !!!