天天看点

home键监听(Android应用切换到后台监听)

1、通过注册广播监听

package country.company.project.util;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.util.Log;

public class HomeWatcher {

    static final String TAG = "hg";
    private Context mContext;
    private IntentFilter mFilter;
    private OnHomePressedListener mListener;
    private InnerRecevier mRecevier;

    public HomeWatcher(Context context) {
        mContext = context;
        mFilter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
    }

    public void setOnHomePressedListener(OnHomePressedListener listener) {
        mListener = listener;
        mRecevier = new InnerRecevier();
    }

    public void startWatch() {
        if (mRecevier != null) {
            mContext.registerReceiver(mRecevier, mFilter);
        }
    }

    public void stopWatch() {
        if (mRecevier != null) {
            mContext.unregisterReceiver(mRecevier);
        }
    }

    class InnerRecevier extends BroadcastReceiver {
        final String SYSTEM_DIALOG_REASON_KEY = "reason";
        final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
        final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
        final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action.equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) {
                String reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY);
                if (reason != null) {
                    Log.e(TAG, "action:" + action + ",reason:" + reason);
                    if (mListener != null) {
                        if (reason.equals(SYSTEM_DIALOG_REASON_HOME_KEY)) {
                            // home键
                            mListener.onHomePressed();
                        } else if (reason
                                .equals(SYSTEM_DIALOG_REASON_RECENT_APPS)) {
                            // 长按home键
                            mListener.onHomeLongPressed();
                        }
                    }
                }
            }
        }
    }
}

package country.company.project.util;

public interface OnHomePressedListener {
    public void onHomePressed();

    public void onHomeLongPressed();
}

在Activity的onCreate()或者其它你需要的地方注册监听器

package country.company.project.util;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import country.company.project.util.R;

public class HomeWatcherActivity extends Activity {
    private final String TAG = "hg";
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.about);
        HomeWatcher mHomeWatcher = new HomeWatcher(this);
        mHomeWatcher.setOnHomePressedListener(new OnHomePressedListener() {
            @Override
            public void onHomePressed() {
                Log.e(TAG, "onHomePressed");
            }
            @Override
            public void onHomeLongPressed() {
                Log.e(TAG, "onHomeLongPressed");
            }
        });
        mHomeWatcher.startWatch();
    }
}
           

2、通过activity的一个生命周期方法:

protected void onUserLeaveHint ()

Since: API Level 
Called as part of the activity lifecycle when an activity is about to go into the background as the result of user choice. 
For example, when the user presses the Home key, onUserLeaveHint() will be called, but when an incoming phone call causes the in-call Activity to be automatically brought to the foreground,
onUserLeaveHint() will not be called on the activity being interrupted. In cases when it is invoked, this method is called right before the activity's onPause() callback.
This callback and onUserInteraction() are intended to help activities manage status bar notifications intelligently; specifically, for helping activities determine the proper time to cancel a notfication.
           

从文档来看,这个方法似乎就是为了按下Home键时这样的场景设计的。

这样,在onUserLeaveHint里发出系统通知即可。

但是问题又来了,如果启动应用,从一个activity依次调用startActivity,finish关闭自己,启动一个新的activity时,onUserLeaveHint也会被调用….

再次翻阅文档,发现Intent中的一个Flag:

public static final int FLAG_ACTIVITY_NO_USER_ACTION

Since: API Level 
If set, this flag will prevent the normal onUserLeaveHint() callback from occurring on the current frontmost activity before it is paused as the newly-started activity is brought to the front.

Typically, an activity can rely on that callback to indicate that an explicit user action has caused their activity to be moved out of the foreground. 
The callback marks an appropriate point in the activity's lifecycle for it to dismiss any notifications that it intends to display "until the user has seen them," such as a blinking LED.
If an activity is ever started via any non-user-driven events such as phone-call receipt or an alarm handler, this flag should be passed to Context.startActivity, ensuring that the pausing activity does not think the user has acknowledged its notification.
           

这正是我想要的,这样,在启动activity时,往intent中加上这个flag,onUserLeaveHint就不会再被调用了

这种方法不太好得原因是每一个start的Activity都需要添加flag才能用于应用切换到后台的判断,项目大的时候比较麻烦