android後臺執行定時任務(保活)&&使用AlarmManager的各種坑

最近有個需求,需要在android手機後臺一直執行一個任務,有一定的時間間隔。
目前方案有以下幾種
方式一:採用Handler的postDelayed(Runnable, long)方法

    handler = new Handler();
    runnable = new Runnable() {

        @Override
        public void run() {
            // handler自帶方法實現定時器
            System.out.println("33331");
            handler.postDelayed(this, 1000*3);//每隔3s執行

        }
    };
    handler.postDelayed(runnable, 1000*60);//延時多長時間啓動定時器

方式二:採用timer及TimerTask結合的方法

    TimerTask timerTask = new TimerTask() {
        @Override
        public void run() {
            System.out.println("99999998");
        }
    };
    timer.schedu,
            1000,//延遲1秒執行
            Time);//週期時間

}

方式三:採用AlarmManager機制

  @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

          new Thread(new Runnable() {
              @Override
              public void run() {
//                  EventBus.getDefault().post(new EventCategory(7));
                  System.out.println("99999988");//這是定時所執行的任務
              }
          }).start();

        AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);

        int anhour=6*1000;
        long triggerAtMillis = SystemClock.elapsedRealtime()+anhour;

        Intent alarmIntent = new Intent(this,MyService.class);

        PendingIntent pendingIntent = PendingIntent.getService(this, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        alarmManager.cancel(pendingIntent);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {// 6.0
            alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtMillis, pendingIntent);
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {//  4.4
            alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,triggerAtMillis, pendingIntent);
        } else {
            alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,triggerAtMillis, pendingIntent);
        }

        return super.onStartCommand(intent, flags, startId);
    }

這裏一定要注意的是AlarmManager.ELAPSED_REALTIME_WAKEUP 後面這個類型
在這裏插入圖片描述
記住不要再用setRepeating了,這個方法過時了,設置了一點都不去精確
還有很多人容易寫成RTC_WAKEUP ,但是取時間的時候卻用的是SystemClock.elapsedRealtime()
SystemClock.elapsedRealtime()獲取從設備boot後經歷的時間值。
SystemClock.elapsedRealtime()計算某個時間經歷了多長時間有意義,例如通話經歷了多長時間,這個值是系統設置無關這是會導致一個不管怎麼設置時間,結果都是5S執行一次的問題,請大家注意,一定要根據上面表格來。

記得註冊服務
在這裏插入圖片描述
調用方式
在這裏插入圖片描述
這裏推薦使用第三種方式

Timer並不太適用於那些需要長期在後臺運行的定時任務。爲了能讓電池更加耐用,每種手機都會有自己的休眠策略,Android 手機就會在長時間不操作的情況下自動讓 CPU 進入到睡眠狀態,這就有可能導致 Timer 中的定時任務無法正常運行。
Alarm具有喚醒 CPU 的功能,即可以保證每次需要執行定時任務的時候 CPU 都能正常工作。

1,Alarm定時不需要程序自身去維護,而又系統來維護,使得程序更好避免了容易出錯問題,更是佔用系統資源,cpu佔有率。

2,即使程序退出後,程序自身不會有任何煩惱的問題,系統到時間自動調用對應組件執行定義好的邏輯

3,定時的多樣性,包括一次定時,循環定時(在xx年x月x日執行,週一至週五執行,每天幾點幾分執行。。。)

如果你的應用是TO C的話,保活請看這一篇,全網搜過寫的最好的
https://www.jianshu.com/p/63aafe3c12af
如果你是TO B的,也就是面向企業的或者工具類的,可以這樣子
比如我的測試手機小米5s,打開應用管理

**

找到我們的應用Testkill,設置自啓動,設置之後,你的APK將做到即便是手動清理APP進程,也能在系統下自行重啓,會重新調用我們上述的MyService,從而達到無敵保活狀態,當然華爲,以及別的手機都會有自己的這個東西,類似白名單,把你的APK加進去即可。

**

比如我們看微信的,爲何能做到無敵保活狀態呢,即便是殺掉的狀態依然能接受新的微信消息,彈出消息提示

!
如果你把自啓動給它關掉,經過驗證,微信被殺也是無法接受新消息提醒的,over。

下面我們來說說使用AlarmManager的一些坑
測試手機系統Android 5.1.1
在這裏插入圖片描述
時間設置爲2S,看看執行結果

在這裏插入圖片描述
小米5 Android8.0
在這裏插入圖片描述
設置成4S的話兩個手機依然執行5s
在這裏插入圖片描述
在這裏插入圖片描述在這裏插入圖片描述

驗證成功 !!!

由於google對電量做了優化,5S是最小輪詢單位
5S以內不管怎麼設置時間,都是5S執行一次,
凡是>5S的,都是可以在5S以上時間執行的,ojbk.


Android JetPack有個組件WorkManager,也可以實現一些後臺定時任務,https://www.jianshu.com/p/f07e4141d432
WorkManager用於那些需要保證即使APP退出了系統依然可以運行的任務,比如將應用數據上傳到服務器。不要用於如果APP被殺進程,可以安全終止的後臺任務

參考
定時任務,AlarmManager使用
https://www.cnblogs.com/ProtectedDream/p/6351447.html#4079768

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章