背景:
用戶按下Home鍵將程序置于后臺運行或者應(yīng)用啟動其他activity,比如系統(tǒng)瀏覽器,短信等,需要向系統(tǒng)發(fā)送通知,用戶做完別的操作后,點擊通知欄,回到應(yīng)用。
問題一
在什么時機(jī)發(fā)送通知?
用戶按下Home的事件在應(yīng)用層時捕捉不到的,因此只能從activity生命周期方法著手。
方法一:
系統(tǒng)所有activity繼承一個BaseActivity,在BaseActivity中維護(hù)一個當(dāng)前可見的activity數(shù)組:
protected static ArrayList sVisibleActivities = new ArrayList();
在onResume中,將當(dāng)前activity保存,同時清除所有通知:
protected void onResume()
{
if (!sVisibleActivities.contains(this))
{
sVisibleActivities.add(this);
}
// 清除系統(tǒng)消息
mNotificationManager.cancel(R.id.notify);
}
在onStop中,清除保存的當(dāng)前activity:
protected void onStop()
{
if (sVisibleActivities.contains(this))
{
sVisibleActivities.remove(this);
}
// 如果當(dāng)前沒有可見的activity,則發(fā)送系統(tǒng)通知
if (sVisibleActivities.isEmpty())
{
sendBackgroundNotify();
}
super.onStop();
}
這種方式在大多數(shù)情況下工作良好,可以達(dá)到需求,但是問題時,當(dāng)前臺的activity被至于后臺時,onStop()方法不一定會被調(diào)用,因此通知有可能不會被發(fā)出!
方法二:
幾經(jīng)周折,發(fā)現(xiàn)activity有一個生命周期方法可以達(dá)到目的:
從文檔來看,這個方法似乎就是為了按下Home鍵時這樣的場景設(shè)計的。
這樣,在onUserLeaveHint里發(fā)出系統(tǒng)通知即可。
但是問題又來了,如果啟動應(yīng)用,從一個activity依次調(diào)用startActivity,finish關(guān)閉自己,啟動一個新的activity時,onUserLeaveHint也會被調(diào)用....
再次翻閱文檔,發(fā)現(xiàn)Intent中的一個Flag:
這正是我想要的,這樣,在啟動activity時,往intent中加上這個flag,onUserLeaveHint就不會再被調(diào)用了,hoory...
用戶按下Home鍵將程序置于后臺運行或者應(yīng)用啟動其他activity,比如系統(tǒng)瀏覽器,短信等,需要向系統(tǒng)發(fā)送通知,用戶做完別的操作后,點擊通知欄,回到應(yīng)用。
問題一
在什么時機(jī)發(fā)送通知?
用戶按下Home的事件在應(yīng)用層時捕捉不到的,因此只能從activity生命周期方法著手。
方法一:
系統(tǒng)所有activity繼承一個BaseActivity,在BaseActivity中維護(hù)一個當(dāng)前可見的activity數(shù)組:
protected static ArrayList
在onResume中,將當(dāng)前activity保存,同時清除所有通知:
protected void onResume()
{
if (!sVisibleActivities.contains(this))
{
sVisibleActivities.add(this);
}
// 清除系統(tǒng)消息
mNotificationManager.cancel(R.id.notify);
}
在onStop中,清除保存的當(dāng)前activity:
protected void onStop()
{
if (sVisibleActivities.contains(this))
{
sVisibleActivities.remove(this);
}
// 如果當(dāng)前沒有可見的activity,則發(fā)送系統(tǒng)通知
if (sVisibleActivities.isEmpty())
{
sendBackgroundNotify();
}
super.onStop();
}
這種方式在大多數(shù)情況下工作良好,可以達(dá)到需求,但是問題時,當(dāng)前臺的activity被至于后臺時,onStop()方法不一定會被調(diào)用,因此通知有可能不會被發(fā)出!
方法二:
幾經(jīng)周折,發(fā)現(xiàn)activity有一個生命周期方法可以達(dá)到目的:
protected void onUserLeaveHint ()
Since: API Level 3
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.
Since: API Level 3
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鍵時這樣的場景設(shè)計的。
這樣,在onUserLeaveHint里發(fā)出系統(tǒng)通知即可。
但是問題又來了,如果啟動應(yīng)用,從一個activity依次調(diào)用startActivity,finish關(guān)閉自己,啟動一個新的activity時,onUserLeaveHint也會被調(diào)用....
再次翻閱文檔,發(fā)現(xiàn)Intent中的一個Flag:
public static final int FLAG_ACTIVITY_NO_USER_ACTION
Since: API Level 3
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.
Since: API Level 3
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.