手持ActivityLifecycleCallbacks挖诸,監(jiān)聽前后臺狀態(tài)如此舒服

本文出自 “阿敏其人” 簡書博客狠轻,轉載或引用請注明出處展氓。

"從前有座山侮繁,山里有座廟色徘,廟里有個老和尚他袈裟七彩燈...... "
推過來的歌曲真有意思各薇!

首先业岁,感謝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ī)矩嘱支,先看圖:

ges.gif

結構圖

Paste_Image.png

菜已上艾蓝,酒已喝。說說菜怎么做的吧斗塘。

一、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?

本篇完宠漩。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市懊直,隨后出現(xiàn)的幾起案子扒吁,更是在濱河造成了極大的恐慌,老刑警劉巖室囊,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件雕崩,死亡現(xiàn)場離奇詭異,居然都是意外死亡融撞,警方通過查閱死者的電腦和手機盼铁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來尝偎,“玉大人饶火,你說我怎么就攤上這事≈鲁叮” “怎么了趁窃?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長急前。 經常有香客問我醒陆,道長,這世上最難降的妖魔是什么裆针? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任刨摩,我火速辦了婚禮寺晌,結果婚禮上,老公的妹妹穿的比我還像新娘澡刹。我一直安慰自己呻征,他們只是感情好,可當我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布罢浇。 她就那樣靜靜地躺著陆赋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪嚷闭。 梳的紋絲不亂的頭發(fā)上攒岛,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天,我揣著相機與錄音胞锰,去河邊找鬼灾锯。 笑死,一個胖子當著我的面吹牛嗅榕,可吹牛的內容都是我干的顺饮。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼凌那,長吁一口氣:“原來是場噩夢啊……” “哼兼雄!你這毒婦竟也來了?” 一聲冷哼從身側響起帽蝶,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤赦肋,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后嘲碱,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡局蚀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年麦锯,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片琅绅。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡扶欣,死狀恐怖,靈堂內的尸體忽然破棺而出千扶,到底是詐尸還是另有隱情料祠,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布澎羞,位于F島的核電站髓绽,受9級特大地震影響,放射性物質發(fā)生泄漏妆绞。R本人自食惡果不足惜顺呕,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一枫攀、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧株茶,春花似錦来涨、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至僵闯,卻和暖如春卧抗,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背棍厂。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工颗味, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人牺弹。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓浦马,卻偏偏與公主長得像,于是被迫代替她去往敵國和親张漂。 傳聞我的和親對象是個殘疾皇子晶默,可洞房花燭夜當晚...
    茶點故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,160評論 25 707
  • 最近剛從舊公司離職,為面試在做準備航攒,因為平時開發(fā)CV大法用得比較多磺陡,很多基礎知識掌握得不是很牢靠以及很多工具框架只...
    黎清海閱讀 2,192評論 1 19
  • 1.什么是Activity?問的不太多币他,說點有深度的 四大組件之一,一般的,一個用戶交互界面對應一個activit...
    JoonyLee閱讀 5,734評論 2 51
  • 那張一本正經的臉 平平展展地從我身旁經過 她不希望我評價她 她怕我說出好話 又怕我說出不好的話 我學牛馬打了個響鼻...
    左左右右艾小年閱讀 400評論 0 0
  • 今天是第九周了蝴悉,天也突然冷了,我給學生們上課瘾敢,檢查作業(yè)拍冠,發(fā)現(xiàn)很多孩子都不能完完,整整地做完作業(yè)簇抵,這需要老師的一些技...
    lygly9閱讀 250評論 0 0