本文出自 “阿敏其人” 簡書博客狠轻,轉載或引用請注明出處展氓。
"從前有座山侮繁,山里有座廟色徘,廟里有個老和尚他袈裟七彩燈...... "
推過來的歌曲真有意思各薇!
首先业岁,感謝Alex_Cin的留言坦仍,才有下文的產生。
之前寫過一小文叨襟,Android 程序打開即啟動指定頁面繁扎,比如密碼檢查頁。糊闽,實現(xiàn)方式麻煩瑣碎梳玫,后來Alex_Cin留言說可以考慮采用Application.ActivityLifecycleCallbacks來實現(xiàn) 監(jiān)聽程序處于前臺還是后臺
,閱讀學習后右犹,大呼過癮提澎。很早就想把這個寫成博客記錄分享給各位朋友,但是因為個人原因遲遲未完成念链,現(xiàn)在補上盼忌。
關于監(jiān)聽程序處于前臺還是后臺
- 弄一個BaseActivity积糯,onResume等方法加1減1?這樣不好谦纱,bug還是有的看成。
- 獲得所有程序的列表,判斷當前程序是否至于前臺跨嘉?不好川慌,而且新SDK有所限制。
- 廣播+服務祠乃,牛刀殺雞梦重。
所以,Application.ActivityLifecycleCallbacks登場亮瓷,清脆利索琴拧,簡單大氣。
老規(guī)矩嘱支,先看圖:
結構圖
菜已上艾蓝,酒已喝。說說菜怎么做的吧斗塘。
一、Application.ActivityLifecycleCallbacks
Application通過ActivityLifecycleCallbacks使用接口提供了一套回調方法亮靴,用于讓開發(fā)者對Activity的生命周期事件進行集中處理馍盟。 ActivityLifecycleCallbacks接口回調可以簡化監(jiān)測Activity的生命周期事件,在一個類中作統(tǒng)一處理茧吊。 ActivityLifecycleCallbacks使用要求API 14+ (Android 4.0+)贞岭。
既然是接口,那么來實現(xiàn)以下看看怎樣唄
隨便寫一個類搓侄,比如名為TestAppCb瞄桨,實現(xiàn)Application.ActivityLifecycleCallbacks接口
public class TestAppCb implements Application.ActivityLifecycleCallbacks {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
@Override
public void onActivityStarted(Activity activity) {
}
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
}
}
我們發(fā)現(xiàn)了很多跟Activity很聲明周期很相似的方法。作用不贅述讶踪,下面會附上一個名為ForegroundCallbacks的實現(xiàn)類芯侥,自行參考。
以往若需監(jiān)測Activity的生命周期事件代碼乳讥,你可能是這樣做的柱查,重寫每一個Acivity的onResume(),然后作統(tǒng)計和處理云石,ActivityLifecycleCallbacks接口回調可以簡化這一繁瑣過程唉工,在一個類中作統(tǒng)一處理。
二汹忠、具體使用
核心封裝類淋硝,根據(jù)下面的代碼的封裝雹熬,結合自定義的Application,就可以輕松地實現(xiàn)監(jiān)聽程序處于前臺還是后臺的需求谣膳。
public class ForegroundCallbacks implements Application.ActivityLifecycleCallbacks {
public static final long CHECK_DELAY = 500;
public static final String TAG = ForegroundCallbacks.class.getName();
public interface Listener {
public void onBecameForeground();
public void onBecameBackground();
}
private static ForegroundCallbacks instance;
private boolean foreground = false, paused = true;
private Handler handler = new Handler();
private List<Listener> listeners = new CopyOnWriteArrayList<Listener>();
private Runnable check;
public static ForegroundCallbacks init(Application application){
if (instance == null) {
instance = new ForegroundCallbacks();
application.registerActivityLifecycleCallbacks(instance);
}
return instance;
}
public static ForegroundCallbacks get(Application application){
if (instance == null) {
init(application);
}
return instance;
}
public static ForegroundCallbacks get(Context ctx){
if (instance == null) {
Context appCtx = ctx.getApplicationContext();
if (appCtx instanceof Application) {
init((Application)appCtx);
}
throw new IllegalStateException(
"Foreground is not initialised and " +
"cannot obtain the Application object");
}
return instance;
}
public static ForegroundCallbacks get(){
if (instance == null) {
throw new IllegalStateException(
"Foreground is not initialised - invoke " +
"at least once with parameterised init/get");
}
return instance;
}
public boolean isForeground(){
return foreground;
}
public boolean isBackground(){
return !foreground;
}
public void addListener(Listener listener){
listeners.add(listener);
}
public void removeListener(Listener listener){
listeners.remove(listener);
}
@Override
public void onActivityResumed(Activity activity) {
paused = false;
boolean wasBackground = !foreground;
foreground = true;
if (check != null)
handler.removeCallbacks(check);
if (wasBackground){
L.d ("went foreground");
for (Listener l : listeners) {
try {
l.onBecameForeground();
} catch (Exception exc) {
L.d ("Listener threw exception!:"+exc.toString());
}
}
} else {
L.d ("still foreground");
}
}
@Override
public void onActivityPaused(Activity activity) {
paused = true;
if (check != null)
handler.removeCallbacks(check);
handler.postDelayed(check = new Runnable(){
@Override
public void run() {
if (foreground && paused) {
foreground = false;
L.d ("went background");
for (Listener l : listeners) {
try {
l.onBecameBackground();
} catch (Exception exc) {
L.d ("Listener threw exception!:"+exc.toString());
}
}
} else {
L.d ("still foreground");
}
}
}, CHECK_DELAY);
}
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {}
@Override
public void onActivityStarted(Activity activity) {}
@Override
public void onActivityStopped(Activity activity) {}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}
@Override
public void onActivityDestroyed(Activity activity) {}
}
.
.
MyApplication 結合Application.ActivityLifecycleCallbacks
監(jiān)聽如此輕松
public class MyApplication extends Application{
@Override
public void onCreate() {
super.onCreate();
ForegroundCallbacks.init(this);
ForegroundCallbacks.get().addListener(new ForegroundCallbacks.Listener() {
@Override
public void onBecameForeground() {
L.d("當前程序切換到前臺");
if(CacheUtils.getBoolean(getApplicationContext(), MyConst.GESTRUE_IS_LIVE)){
L.d("已經開啟手勢鎖");
Intent intent = new Intent(getApplicationContext(), CheckGesPwdActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}else{
}
}
@Override
public void onBecameBackground() {
L.d("當前程序切換到后臺");
}
});
}
}
如上竿报,即可,手勢庫可以直接引用做個小demo参歹。
整個過程實現(xiàn)起來都是相當輕松的仰楚,亮點是ForegroundCallbacks,里面的代碼值得咀嚼和學習犬庇。
本文粗糙了點僧界,哈哈哈哈,不過我為什么感覺我還是挺良心的臭挽,哈哈哈哈捂襟。
附上github鏈接GestureLockMaster
三、單個Activity單獨使用欢峰?
就在一個頁面監(jiān)聽葬荷,當然可以。
public class TestLifeAc extends AppCompatActivity implements ForegroundCallbacks.Listener {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_city_list);
// 注冊監(jiān)聽
ForegroundCallbacks.get(this).addListener(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
// 移除監(jiān)聽
ForegroundCallbacks.get(this).removeListener(this);
}
@Override
public void onBecameForeground(Activity activity) {
// 切換為前臺
}
@Override
public void onBecameBackground(Activity activity) {
//切換為后臺
}
}
四纽帖,參考學習
Is my Android app currently foreground or background?
本篇完宠漩。