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
//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
//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 !!!