1. 程式人生 > >Android Wear計時器開發(3)

Android Wear計時器開發(3)

在本系列前幾篇文章中,我們介紹了Android Wear計時器app,對設計思路和app的結構進行了分析。本文將講解如何定時喚醒程式提醒使用者。

對於為什麼不用後臺服務的方式一直執行,我們已經進行了解釋——這種方式非常耗電。因此,我們必須要有一個定時喚醒機制。我們可以使用AlarmManager來實現這個機制,定時執行一個Intent,然後通知BroadcastReceiver。之所以選擇BroadcastReceiver而不用IntentService,是因為我們要執行的任務是輕量級的而且生命週期非常短暫。使用BroadcastReceiver可以避免每次執行任務的時候都經歷Service的整個生命週期。因此,對於我們這種輕量級的任務來說非常合適——我們執行的任務都在毫秒級。

BroadcastReceiver的核心在於onReceiver方法,我們需要在這裡安排各種事件響應。

Java
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970 ;html-script:false]publicclassMatchTimerReceiverextendsBroadcastReceiver{publicstaticfinalintMINUTE_MILLIS=60000;privatestaticfinallong
DURATION=45*MINUTE_MILLIS;privatestaticfinalIntent UPDATE_INTENT=newIntent(ACTION_UPDATE);privatestaticfinalIntent ELAPSED_ALARM=newIntent(ACTION_ELAPSED_ALARM);privatestaticfinalIntent FULL_TIME_ALARM=newIntent(ACTION_FULL_TIME_ALARM);privatestaticfinalintREQUEST_UPDATE=1;privatestaticfinalintREQUEST_ELAPSED=2;privatestaticfinalintREQUEST_FULL_TIME=3;publicstaticvoidsetUpdate(Context context){context.sendBroadcast(UPDATE_INTENT);}...privatevoidreset(MatchTimer timer){timer.reset();}privatevoidresume(Context context,MatchTimer timer){timer.resume();longplayedEnd=timer.getStartTime()+timer.getTotalStoppages()+DURATION;if(playedEnd>System.currentTimeMillis()){setAlarm(context,REQUEST_FULL_TIME,FULL_TIME_ALARM,playedEnd);}}privatevoidpause(Context context,MatchTimer timer){timer.pause();cancelAlarm(context,REQUEST_FULL_TIME,FULL_TIME_ALARM);longelapsedEnd=timer.getStartTime()+DURATION;if(!isAlarmSet(context,REQUEST_ELAPSED,ELAPSED_ALARM)&&elapsedEnd>System.currentTimeMillis()){setAlarm(context,REQUEST_ELAPSED,ELAPSED_ALARM,elapsedEnd);}}privatevoidstop(Context context,MatchTimer timer){timer.stop();cancelAlarm(context,REQUEST_UPDATE,UPDATE_INTENT);cancelAlarm(context,REQUEST_ELAPSED,ELAPSED_ALARM);cancelAlarm(context,REQUEST_FULL_TIME,FULL_TIME_ALARM);}privatevoidstart(Context context,MatchTimer timer){timer.start();longelapsedEnd=timer.getStartTime()+DURATION;setRepeatingAlarm(context,REQUEST_UPDATE,UPDATE_INTENT);if(timer.getTotalStoppages()>0&&!timer.isPaused()){longplayedEnd=timer.getStartTime()+timer.getTotalStoppages()+DURATION;if(playedEnd>System.currentTimeMillis()){setAlarm(context,REQUEST_FULL_TIME,FULL_TIME_ALARM,playedEnd);}if(elapsedEnd>System.currentTimeMillis()){setAlarm(context,REQUEST_ELAPSED,ELAPSED_ALARM,elapsedEnd);}}else{if(elapsedEnd>System.currentTimeMillis()){setAlarm(context,REQUEST_FULL_TIME,FULL_TIME_ALARM,elapsedEnd);}}}...}

程式碼還是非常直觀易於理解的。首先例項化一個MatchTimer物件(從SharedPreference中讀取資料),然後分別傳給對應的事件處理Handler。之後等待動作發生,最後更新Notification。

這裡會處理8個事件動作,其中5個負責控制計時器的狀態(START、STOP、PAUSE、RESUME、RESET);一個負責更新Notification,剩下兩個負責到45分鐘喚醒後震動提示。

我們先從這幾個控制狀態開始:

Java
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970 ;html-script:false]publicclassMatchTimerReceiverextendsBroadcastReceiver{publicstaticfinalintMINUTE_MILLIS=60000;privatestaticfinallongDURATION=45*MINUTE_MILLIS;privatestaticfinalIntent UPDATE_INTENT=newIntent(ACTION_UPDATE);privatestaticfinalIntent ELAPSED_ALARM=newIntent(ACTION_ELAPSED_ALARM);privatestaticfinalIntent FULL_TIME_ALARM=newIntent(ACTION_FULL_TIME_ALARM);privatestaticfinalintREQUEST_UPDATE=1;privatestaticfinalintREQUEST_ELAPSED=2;privatestaticfinalintREQUEST_FULL_TIME=3;publicstaticvoidsetUpdate(Context context){context.sendBroadcast(UPDATE_INTENT);}...privatevoidreset(MatchTimer timer){timer.reset();}privatevoidresume(Context context,MatchTimer timer){timer.resume();longplayedEnd=timer.getStartTime()+timer.getTotalStoppages()+DURATION;if(playedEnd>System.currentTimeMillis()){setAlarm(context,REQUEST_FULL_TIME,FULL_TIME_ALARM,playedEnd);}}privatevoidpause(Context context,MatchTimer timer){timer.pause();cancelAlarm(context,REQUEST_FULL_TIME,FULL_TIME_ALARM);longelapsedEnd=timer.getStartTime()+DURATION;if(!isAlarmSet(context,REQUEST_ELAPSED,ELAPSED_ALARM)&&elapsedEnd>System.currentTimeMillis()){setAlarm(context,REQUEST_ELAPSED,ELAPSED_ALARM,elapsedEnd);}}privatevoidstop(Context context,MatchTimer timer){timer.stop();cancelAlarm(context,REQUEST_UPDATE,UPDATE_INTENT);cancelAlarm(context,REQUEST_ELAPSED,ELAPSED_ALARM);cancelAlarm(context,REQUEST_FULL_TIME,FULL_TIME_ALARM);}privatevoidstart(Context context,MatchTimer timer){timer.start();longelapsedEnd=timer.getStartTime()+DURATION;setRepeatingAlarm(context,REQUEST_UPDATE,UPDATE_INTENT);if(timer.getTotalStoppages()>0&&!timer.isPaused()){longplayedEnd=timer.getStartTime()+timer.getTotalStoppages()+DURATION;if(playedEnd>System.currentTimeMillis()){setAlarm(context,REQUEST_FULL_TIME,FULL_TIME_ALARM,playedEnd);}if(elapsedEnd>System.currentTimeMillis()){setAlarm(context,REQUEST_ELAPSED,ELAPSED_ALARM,elapsedEnd);}}else{if(elapsedEnd>System.currentTimeMillis()){setAlarm(context,REQUEST_FULL_TIME,FULL_TIME_ALARM,elapsedEnd);}}}...}

這些方法主要有兩個功能:首先設定MatchTimer的狀態,然後設定時間提醒的鬧鈴,改變引數就可以播放鬧鈴。這個功能還可以封裝成一個工具方法,叫setUpdate()。這樣外部也可以觸發計時器的更新。

我們使用標準AlarmManager的方法來設定鬧鈴:

Java