Android定時鎖屏功能實現(AlarmManager定時部分)

来源:https://www.cnblogs.com/ken9527just/archive/2019/08/08/11323529.html
-Advertisement-
Play Games

菜鳥入坑記——第一篇 關鍵字:AlarmManager 一、AlarmManager簡介: 參考網址:https://www.jianshu.com/p/8a2ce9d02640 參考網站:https://www.runoob.com/w3cnote/android-tutorial-alarmma ...


菜鳥入坑記——第一篇

關鍵字:AlarmManager

一、AlarmManager簡介:

        參考網址:https://www.jianshu.com/p/8a2ce9d02640
        參考網站:https://www.runoob.com/w3cnote/android-tutorial-alarmmanager.html

        推薦此網址:https://www.jianshu.com/p/d69a90bc44c0

        瞭解android低電耗模式:https://developer.android.google.cn/training/monitoring-device-state/doze-standby.html
        AlarmManager的作用:在特定的時刻為我們廣播一個指定的Intent。
        即:自己設定一個時間,當系統時間到達此時間時,AlarmManager自動廣播一個我們設定好的Intent,指向某個Activity或Service。
        註意:① AlarmManager主要用來在某個時刻運行你的代碼,即使你的APP在那個特定的時間並沒有運行。

二、獲得AlarmManager實例對象:
        AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);

三、方法:

        setExact(int type, long startTime, PendingIntent pi); 一次性鬧鐘,執行時間精確,為精確鬧鐘

        參數解釋:此部分參考網站https://www.jianshu.com/p/8a2ce9d02640

四、程式設計:

        (1)類型type

        此處選用鬧鐘類型為AlarmManager.RTC:鬧鐘在睡眠狀態下不可用,該狀態下鬧鐘使用絕對時間(當前系統時間),狀態值為1。

        (2)開始時間startTime

        由於通過SP獲得的時間為String類型,需先轉換為long類型,且時間單位為ms

 1 /**
 2      * String類型轉換成date類型
 3      * strTime: 要轉換的string類型的時間,
 4      * formatType: 要轉換的格式yyyy-MM-dd HH:mm:ss
 5      * //yyyy年MM月dd日 HH時mm分ss秒,
 6      * strTime的時間格式必須要與formatType的時間格式相同
 7      */
 8     public static Date stringToDate(String strTime, String formatType){
 9         KLog.d("進入stringToDate");
10         try {
11             SimpleDateFormat formatter = new SimpleDateFormat(formatType);
12             Date date = null;
13             date = formatter.parse(strTime);
14             return date;
15         }catch (Exception e){
16             return null;
17         }
18     }
19     /**
20      * String類型轉換為long類型
21      * .............................
22      * strTime為要轉換的String類型時間
23      * formatType時間格式
24      * formatType格式為yyyy-MM-dd HH:mm:ss//yyyy年MM月dd日 HH時mm分ss秒
25      * strTime的時間格式和formatType的時間格式必須相同
26      */
27     public static long stringToLong (String strTime,String formatType){
28         KLog.d("進入stringToLong");
29         try{
30             //String類型轉換為date類型
31             Date date = stringToDate(strTime, formatType);
32             Log.d(TAG,"調用stringToDate()獲得的date:" + date);
33             if (date == null) {
34                 return 0;
35             }else {
36                 //date類型轉成long類型
37                 long Hour = date.getHours();
38                 long Min = date.getMinutes();
39                 long TimeLong = Hour*60*60*1000 + Min*60*1000;
40                 Log.d(TAG,"stringToLong()獲得的Hour:" + Hour + " h");
41                 Log.d(TAG,"stringToLong()獲得的Min:" + Min + " min");
42                 Log.d(TAG,"stringToLong()獲得的TimeLong:" + TimeLong + " ms");
43                 return TimeLong;
44             }
45         }catch (Exception e){
46             return 0;
47         }
48     }

 

        Java Date、String、Long三種日期類型之間的相互轉換

        參考網址:http://www.blogjava.net/weishuangshuang/archive/2012/09/27/388712.html

        成功獲得睡眠時間(SLEEP_TIME)和起床時間(GET_UP_TIME)(單位ms)之後,計算鎖屏時間IntervalTime(睡眠時間至起床時間):

       

1         //計算時間間隔
2         if (GET_UP_TIME >= SLEEP_TIME){
3              IntervalTime = GET_UP_TIME - SLEEP_TIME;
4         }else {
5              IntervalTime = 24*60*60*1000 + GET_UP_TIME - SLEEP_TIME;
6         }

        (3)定義跳轉Activity的操作:PendingIntent pi

        我們的目的是利用AlarmManager的set()方法讓鬧鐘在我們指定的時間點執行我們自定義的intent操作。這裡時間點的設置非常重要,若時間設置的不精確(一般精確到秒即可,以下代碼中精確至ms),將會導致鬧鐘執行intent有延遲。(SLEEP_TIME_HOUR和SLEEP_TIME_MIN分佈是睡眠時間的小時數和分鐘數)

 

 1 //設置當前的時間
 2 Calendar calendar = Calendar.getInstance();
 3 calendar.setTimeInMillis(System.currentTimeMillis());
 4 //根據用戶選擇的時間來設置Calender對象(即:睡覺時間)
 5 calendar.set(Calendar.HOUR_OF_DAY, (int)SLEEP_TIME_HOUR);
 6 calendar.set(Calendar.MINUTE, (int) SLEEP_TIME_MIN);
 7 calendar.set(Calendar.SECOND, 0);
 8 calendar.set(Calendar.MILLISECOND,0);
 9 //設置當前時區(若時區不對,鬧鐘將有偏差)
10 TimeZone timeZone = TimeZone.getDefault();//獲取系統時間時區
11 KLog.d("當前設置的時區為: " + timeZone);
12 calendar.setTimeZone(timeZone);
13 KLog.d("睡覺時間:" + SLEEP_TIME + "ms, 起床時間:" + GET_UP_TIME + "ms.");
14 KLog.d("夜間休息時長:IntervalTime = " + IntervalTime + "ms.");

        定義intent操作:

 

1         //定義用於跳轉到 LockScreenActivity.class 中的Intent對象intent
2         Intent intent = new Intent(RobotClientMainActivity.this, LockScreenActivity.class);
3         intent.putExtra("INTERVAL", IntervalTime);

 

        putExtra("INTERVAL", IntervalTime); "INTERVAL"為關鍵字,IntervalTime為傳入值(此處指睡眠時鎖屏的時間ms)。帶值跳轉至LockScreenActivity.class中,LockScreenActivity執行相應的鎖屏操作。

       初始化鬧鐘的執行操作pi:

PendingIntent.getActivity的使用:https://www.cnblogs.com/lyxin/p/5995681.html

1 //初始化鬧鐘的執行操作pi
2 pi = PendingIntent.getActivity(RobotClientMainActivity.this,0
,intent,PendingIntent.FLAG_UPDATE_CURRENT);

方法:PendingIntent.getActivity(Context context, int requestCode, Intent intent, int flags);

        第一個參數是上下文context;

        第二個參數是請求碼,用於標識此PendingIntent的對象,相當於關鍵字;

        第三個參數是意圖,用於跳轉Activity;

        第四個參數代表了PendingIntent的四種不同的狀態,可用理解為狀態標識符。四種狀態如下:

①FLAG_CANCEL_CURRENT:

如果當前系統中已經存在一個相同的PendingIntent對象,則已有的PendingIntent將會取消,然後重新生成一個PendingIntent對象。

②FLAG_NO_CREATE:

如果當前系統中不存在相同的PendingIntent對象,系統將不會創建該PendingIntent對象,而是直接返回null。

③FLAG_ONE_SHOT:

該PendingIntent只作用一次。在該PendingIntent對象通過send()方法觸發過後,PendingIntent將自動調用cancel()進行銷毀,如果你再調用send()方法,系統將會返回一個SendIntentException。

④FLAG_UPDATE_CURRENT:

如果系統中有一個和你描述的PendingIntent對等的PendingIntent,那麼系統將使用該PendingIntent對象,但是會使用新的Intent來更新之前PendingIntent中的Intent對象數據,例如更新Intent中的Extras。

        (4)設置alarmManager:

1 //定義AlarmManager對象
2     private AlarmManager alarmManager;
1         //初始化alarmManager
2         alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
1         /**
2          * 設置AlarmManager在Calendar對應的時間啟動Activity
3          * 當到達睡覺時間時跳轉至LockScreenActivity執行鎖屏操作
4          */
5         alarmManager.setExact(AlarmManager.RTC,calendar.getTimeInMillis(),pi);
6         KLog.d("從calender中讀取到的睡眠時間:" + calendar.getTime()
7                 + "/n 毫秒:"+calendar.getTimeInMillis());

在此處,系統已經能夠在指定的時間跳轉至鎖屏操作。但是實踐中出現的問題是:只要系統時間已經超過指定時間,關機重啟時會自動跳入鎖屏操作——為什麼???。。。:(  。。。求大神指導

********************************************************************************************************************************************************************************************************************************************************************************

雖然沒有弄清alarmManager.setExact的機制;但是利用其在實踐中的表現(指過了鎖屏時間重啟後仍會鎖屏),在關鍵時間點加入if/else的判斷,成功實現了功能。

相關條件判斷如下:

定義和初始化部分:

1  //定義睡覺和起床時間單位ms
2         long SLEEP_TIME,GET_UP_TIME;
3         //睡覺和起床時間對應的小時數和分鐘數
4         long SLEEP_TIME_HOUR,SLEEP_TIME_MIN;
5         long GET_UP_TIME_HOUR,GET_UP_TIME_MIN;
6         //定義睡覺時間和起床時間之間的時間間隔
7         long IntervalTime;
8         //定義系統當前時間(單位ms)
9         long CurrentTime_ms;
1 //設置當前的時間
2         Calendar calendar = Calendar.getInstance();
3         calendar.setTimeInMillis(System.currentTimeMillis());
4         KLog.d("111系統當前時間為:" + calendar.getTime());
5         KLog.d("系統當前時間Hour:" + calendar.get(Calendar.HOUR_OF_DAY));
6         KLog.d("系統當前時間Min:" + calendar.get(Calendar.MINUTE));
7         KLog.d("系統當前時間Second:" + calendar.get(Calendar.SECOND));
8         CurrentTime_ms = calendar.get(Calendar.HOUR_OF_DAY)*60*60*1000
9                 +calendar.get(Calendar.MINUTE)*60*1000+calendar.get(Calendar.SECOND)*1000;

條件判斷:

 1  /**
 2          * 計算夜間休息時長
 3          * 如果當前時間沒到睡眠時間,則休息時長定為睡眠時間至起床時間
 4          * 若果當前時間在睡眠時間和起床時間之間,則休息時長定為當前時間至起床時間
 5          */
 6         if (GET_UP_TIME >= SLEEP_TIME) {
 7             if ((CurrentTime_ms >= SLEEP_TIME) && (CurrentTime_ms <= GET_UP_TIME)) {
 8                 IntervalTime = GET_UP_TIME - CurrentTime_ms;
 9 
10             }else {
11                 IntervalTime = GET_UP_TIME - SLEEP_TIME;
12             }
13         }else {
14             if ((CurrentTime_ms <= SLEEP_TIME) && (CurrentTime_ms >= GET_UP_TIME)) {
15                 IntervalTime = 24*60*60*1000 + GET_UP_TIME - SLEEP_TIME;
16             }else {
17                 if(CurrentTime_ms <= GET_UP_TIME) {
18                     IntervalTime = GET_UP_TIME - CurrentTime_ms;
19                 }else {
20                     IntervalTime = 24*60*60*1000 + GET_UP_TIME - CurrentTime_ms;
21                 }
22             }
23         }
24         KLog.d("夜間休息時長:IntervalTime = " + IntervalTime + "ms.");
 1 /**
 2          * 設置AlarmManager在Calendar對應的時間啟動Activity
 3          * 當到達睡覺時間時跳轉至LockScreenActivity執行鎖屏操作
 4          * 若系統當前時間已經不屬於夜間休息時間,加入判斷使程式不再調用alarmManager
 5          */
 6         if (GET_UP_TIME >= SLEEP_TIME) {
 7             if (CurrentTime_ms < GET_UP_TIME) {
 8                 KLog.d("當前時間 CurrentTime_ms = " + CurrentTime_ms + "ms");
 9                 KLog.d("起床時間 GET_UP_TIME = " + GET_UP_TIME + "ms");
10                 alarmManager.setExact(AlarmManager.RTC,calendar.getTimeInMillis(),pi);
11                 KLog.d("從calender中讀取到的睡眠時間:" + calendar.getTime()
12                         + "/n 毫秒:"+calendar.getTimeInMillis());
13             }
14         }else {
15             KLog.d("當前時間 CurrentTime_ms = " + CurrentTime_ms + "ms");
16             KLog.d("起床時間 GET_UP_TIME = " + GET_UP_TIME + "ms");
17             alarmManager.setExact(AlarmManager.RTC,calendar.getTimeInMillis(),pi);
18             KLog.d("從calender中讀取到的睡眠時間:" + calendar.getTime()
19                     + "/n 毫秒:"+calendar.getTimeInMillis());
20         }

實現功能:在指定時間範圍內對APP鎖屏,在鎖屏時間內,重啟APP仍可鎖屏,不會因重啟而終止整個鎖屏活動。

小結:查閱了N多資料,終於實現了這一功能(*^▽^*),雖然還有許多不懂的地方,但是我會繼續努力的。

最後,大神們給給意見撒。。。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 用戶連接到mysql,並做各種查詢,在用戶和伺服器中間分為兩個階段: 1:用戶是否有權連接上來 2:用戶是否有權執行此操作(如select,update等等) 先看第一個階段:伺服器如何判斷用戶是否有權連接上來 依據三個參數: 你從哪來? host 你是誰? user 你的密碼是多少? passwo ...
  • 大A股,股票數據,可用作數據分析練手,每個表和欄位都有註釋; 數據來源:https://tushare.pro/ mysql:連接地址:106.15.47.188: 埠:3306 用戶名:lxd 密碼:laoxiaoduan321 庫名:stocka裡面同步了股票數據,有興趣做分析的可以拿有空的話 ...
  • Redis簡介 Redis是什麼 Redis是一個開源的,使用ANSI C 編寫,高性能的Key Value的NoSQL資料庫。 Redis特點 1. 基於記憶體 2. 可持久化數據 3. 具有豐富的數據結構類型,適應非關係型數據的存儲需求 4. 支持絕大多數主流開發語言,如C、C++、Java、Py ...
  • 實時流式計算,也就是RealTime,Streaming,Analyse,在不同的領域有不同的定義,這裡我們說的是大數據領域的實時流式計算。 實時流式計算,或者是實時計算,流式計算,在大數據領域都是差不多的概念。那麼,到底什麼是實時流式計算呢? 谷歌大神Tyler Akidau在《the world ...
  • 每一個 Gradle 構建都會按照相同的順序經歷三個不同的階段:初始化、配置、執行。 ...
  • 1. 多線程的底層實現? 2. 線程間怎麼通信? 3. 網路圖片處理問題中怎麼解決一個相同的網路地址重覆請求的問題? 4. 用NSOpertion和NSOpertionQueue處理A,B,C三個線程,要求執行完A,B後才能執行C,怎麼做? 5. 列舉cocoa中常見對幾種多線程的實現,並談談多線程 ...
  • 初步認為應該是與熱點名稱的位元組數有關。 然後開始查看源碼。 /Settings/res/xml/tether_prefs.xml 中的 發現了熱點設置界面在HotspotSettings 裡面, 在HotspotSettings中點擊設置wifi熱點,進入/Settings/src/com/andr ...
  • Android上已經自動對鍵盤遮擋輸入框做了處理,所以我們只需要關註ios。 1.首先引入 KeyboardAvoidingView 2.然後在頁面的最外層加上 KeyboardAvoidingView 如果適配ios和Android,可以將頁面提取出來 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...