android要實現定時的功能那肯定就要用到鬧鈴相關的技術,
那么android鬧鈴實現是基於 AlarmManager 這個類的,首先我們來看一下它的幾個主要的方法。
打開AlarmManager的源碼,如下圖顯示:
兩個核心的方法 :
private final IAlarmManager mService;
public void set(int type, long triggerAtMillis, PendingIntent operation) { try { mService.set(type, triggerAtMillis, operation); } catch (RemoteException ex) { } }
和
public void setRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation) { try { mService.setRepeating(type, triggerAtMillis, intervalMillis, operation); } catch (RemoteException ex) { } }
第一個方法主要功能是注冊一個比較簡單的鬧鈴,第二個方法是注冊一個重復的鬧鈴,這里重復的意思是指:設置5s, 那么每隔5s會執行一次 。
我們看到這里具體的實現都是基於IAlarmManager的,而IAlarmManager是一個aidl(Android Interface definition language),具體的就不詳細介紹了,大家有興趣的可以自己研究一下。
下面我來看下set(int type, long triggerAtMillis, PendingIntent operation)方法是如何調用的:
// 進行鬧鈴注冊 Intent intent = new Intent(MainActivity.this, AlarmReceiver.class); PendingIntent sender = PendingIntent.getBroadcast(MainActivity.this, 0, intent, 0); // 過10s 執行這個鬧鈴 Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(System.currentTimeMillis()); calendar.add(Calendar.SECOND, 10); AlarmManager manager = (AlarmManager)getSystemService(ALARM_SERVICE); manager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), sender);
看一下AlarmReceiver 的源碼:
/** * * @ClassName: AlarmReceiver * @Description: 鬧鈴時間到了會進入這個廣播,這個時候可以做一些該做的業務。 * @author HuHood * @date 2013-11-25 下午4:44:30 * */ public class AlarmReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Toast.makeText(context, "鬧鈴響了, 可以做點事情了~~", Toast.LENGTH_LONG).show(); } }
還有別忘了,AndroidManifest.xml中需要加入:
<receiver android:name="com.example.alarmmanagerdemo.AlarmReceiver" android:process=":remote">
運行之后,過10s 彈出 "鬧鈴響了,可以做點事情了~~", 說明成功了。
ok,這個結果肯定不是我們想要的,我們想要的功能是每天定時提醒的功能,那么需要基於
setRepeating(int type, long triggerAtMillis,long intervalMillis, PendingIntent operation)
這個方法來實現,代碼如下:
Intent intent = new Intent(MainActivity.this, AlarmReceiver.class); PendingIntent sender = PendingIntent.getBroadcast(MainActivity.this, 0, intent, 0); long firstTime = SystemClock.elapsedRealtime(); // 開機之后到現在的運行時間(包括睡眠時間) long systemTime = System.currentTimeMillis(); Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(System.currentTimeMillis()); // 這里時區需要設置一下,不然會有8個小時的時間差 calendar.setTimeZone(TimeZone.getTimeZone("GMT+8")); calendar.set(Calendar.MINUTE, mMinute); calendar.set(Calendar.HOUR_OF_DAY, mHour); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0); // 選擇的定時時間 long selectTime = calendar.getTimeInMillis(); // 如果當前時間大於設置的時間,那么就從第二天的設定時間開始 if(systemTime > selectTime) { Toast.makeText(MainActivity.this,"設置的時間小於當前時間", Toast.LENGTH_SHORT).show(); calendar.add(Calendar.DAY_OF_MONTH, 1); selectTime = calendar.getTimeInMillis(); } // 計算現在時間到設定時間的時間差 long time = selectTime - systemTime; firstTime += time; // 進行鬧鈴注冊 AlarmManager manager = (AlarmManager)getSystemService(ALARM_SERVICE); manager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, firstTime, DAY, sender); Log.i(TAG,"time ==== " + time +", selectTime ===== " + selectTime + ", systemTime ==== " + systemTime +", firstTime === " + firstTime); Toast.makeText(MainActivity.this,"設置重復鬧鈴成功! ", Toast.LENGTH_LONG).show();
以上的思路大致是這樣的,首先根據設置的時間,算出當前時間離設置時間的時間差,加上這個時間差,我們就知道第一次提醒的時間,然后再設定重復的時間間隔,我們這里設置1天就可以了。
現在解釋一下setRepeating中第一個參數:
AlarmManager.RTC,硬件鬧鍾,不喚醒手機(也可能是其它設備)休眠;當手機休眠時不發射鬧鍾。
AlarmManager.RTC_WAKEUP,硬件鬧鍾,當鬧鍾發躰時喚醒手機休眠;
AlarmManager.ELAPSED_REALTIME,真實時間流逝鬧鍾,不喚醒手機休眠;當手機休眠時不發射鬧鍾。
AlarmManager.ELAPSED_REALTIME_WAKEUP,真實時間流逝鬧鍾,當鬧鍾發躰時喚醒手機休眠;
RTC鬧鍾和ELAPSED_REALTIME最大的差別就是前者可以通過修改手機時間觸發鬧鍾事件,后者要通過真實時間的流逝,即使在休眠狀態,時間也會被計算。
還有,我們這里是調用廣播的形式來實現的,也可以用service的方式來進行實現,只要把PendingIntent改動一下即可,相關代碼:
PendingIntent.getService(MainActivity.this, 0,new Intent(MainActivity.this,AlarmService.class), 0);
其他的均相同。
點擊這里:代碼