說實話,之前寫的兩篇博客Android廣播機制Broadcast詳解、Android時間、日期相關類和方法以及現在要寫的,都算是為之后要寫的鬧鍾應用做鋪墊,有興趣的話,大家可以去看看前兩篇博客。
一、AlarmManager簡介
對於一個鬧鍾應用的實現,個人覺得最主要的應該要屬於AlarmManager了。AlarmManager稱為全局定時器,字面意思就是鬧鍾管理(請原諒我蹩腳的英語),是Android中常用的一種系統級別的提示服務,在特定的時刻為我們廣播一個指定的Intent。簡單的說就是我們設定一個時間,然后在該時間到來時,AlarmManager為我們廣播一個我們設定的Intent,通常我們使用 PendingIntent(這貨在調用系統發送短信的時候也有,找個時間溫習下Intent,順帶把這個也好好學習下),PendingIntent可以理解為Intent的封裝包,簡單的說就是在Intent上在加個指定的動作。在使用Intent的時候,我們還需要在執行startActivity、startService或sendBroadcast才能使Intent有用。而PendingIntent的話就是將這個動作包含在內了。
//定義一個PendingIntent對象,此處先照樣畫葫蘆,下次學了再細講
PendingIntent pi = PendingIntent.getBroadcast(Context, int, Intent, int);
補充:網上有人再說PendingIntent的第二個和第四個參數不重要,其實不然,如果在鬧鍾這個應用中,你的第二個參數都是同一個常數,那么你之后設的鬧鍾會把之前的鬧鍾給覆蓋掉,導致時間到了也不提醒的情況。解決辦法就是:根據設置鬧鍾時的時間毫秒數來產生第二個參數。
二、AlarmManager常用方法簡介
AlarmManager類提供的常用方法主要有一下幾個:
public void set(int type, long triggerAtMillis, PendingIntent operation) 功能:用於設置一次性鬧鍾,第一個參數表示鬧鍾類型,第二個參數表示觸發這個鬧鍾要等待的時間,與type相關(不懂英文就查字典吧,我也是查了才理解這個參數的意思的),
第三個參數鬧鍾響應的動作 參數:type AlarmManager.ELAPSED_REALTIME 在指定的延時過后,發送廣播,但不喚醒設備。 AlarmManager.ELAPSED_REALTIME_WAKEUP 在指定的演示后,發送廣播,並喚醒設備 AlarmManager.RTC 在指定的時刻,發送廣播,但不喚醒設備 時刻是相對於1970-01-01 00:00:00來說的毫秒數 AlarmManager.RTC_WAKEUP 在指定的時刻,發送廣播,並喚醒設備 AlarmManager.POWER_OFF_WAKEUP表示鬧鍾在手機關機狀態下也能正常進行提示功能狀態值為4;不過我測試的時候並沒有這個常量,估計和SDK有關 operation 綁定了鬧鍾的執行動作,比如發送一個廣播、給出提示等等。 public void setExact(int type, long triggerAtMillis, PendingIntent operation) 功能:在規定的時間精確的執行鬧鍾,這個函數應該是鬧鍾執行精度比較高吧 public void setRepeating(int type, long triggerAtMills, long intervalMillis, PendingIntent operation) 功能:該方法用於設置重復鬧鍾,第一個參數表示鬧鍾類型,第二個參數表示觸發這個鬧鍾要等待的時間,第三個參數表示鬧鍾兩次執行的間隔時間,第三個參數表示鬧鍾響應動作。 public void setInexactRepeating(int type, long triggerAtMills, long intervalMillis, PendingIntent operation) 功能:設置一個重復鬧鍾的不精確版本,它相對而言更節能一些,因為系統可能會將幾個差不多的鬧鍾合並為一個來執行,減少設備的喚醒次數。
由於不是精確版,所以這里的intervaMills會略有不同 參數:intervalMillis: INTERVAL_FIFTEEN_MINUTES INTERVAL_HALF_HOUR INTERVAL_HOUR INTERVAL_HALF_DAY INTERVAL_DAY public void cancel(PendingIntent operation) 功能:取消一個設置的鬧鍾,移除任意匹配意圖的鬧鍾 public void setTimeZone(String timeZone) 功能:設置系統的默認時區。需要android.permission.SET_TIME_ZONE權限
三、一個簡單的鬧鍾的實例Demo
首先,我們現在AndroidManifest.xml中注冊一個廣播,如果不清楚可以去看我之前寫的博客Android隨筆之——Android廣播機制Broadcast詳解
<receiver android:name=".AlarmReceiver" ><!-- Reveiver名稱,如果是內部類靜態注冊廣播,請在內部類前加$ --> <intent-filter> <action android:name="android.intent.action.ALARM_RECEIVER" /><!-- 廣播接收的Intent --> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver>
接着,我們就要編寫一個廣播接收器,用來接收鬧鍾的廣播事件,進行相關處理
1 package com.example.alarmmanager; 2 3 import android.content.BroadcastReceiver; 4 import android.content.Context; 5 import android.content.Intent; 6 import android.widget.Toast; 7 8 public class AlarmReceiver extends BroadcastReceiver{ 9 10 @Override 11 public void onReceive(Context arg0, Intent arg1) { 12 //此處可以添加鬧鍾鈴聲 13 System.out.println("我是鬧鍾,我要叫醒你..."); 14 Toast.makeText(arg0, "我是鬧鍾,我要叫醒你...", Toast.LENGTH_SHORT).show(); 15 } 16 17 }
最后,在MainActivity.java寫上具體的實現代碼
1 package com.example.alarmmanager; 2 3 import java.text.ParseException; 4 import java.text.SimpleDateFormat; 5 import java.util.Date; 6 7 import android.annotation.SuppressLint; 8 import android.app.Activity; 9 import android.app.AlarmManager; 10 import android.app.PendingIntent; 11 import android.content.Intent; 12 import android.os.Bundle; 13 import android.os.SystemClock; 14 import android.view.View; 15 import android.view.View.OnClickListener; 16 17 public class MainActivity extends Activity implements OnClickListener { 18 19 private AlarmManager alarmManager; 20 private PendingIntent operation; 21 22 protected void onCreate(Bundle savedInstanceState) { 23 super.onCreate(savedInstanceState); 24 setContentView(R.layout.activity_main); 25 26 // 初始化按鈕,並綁定監聽事件 27 findViewById(R.id.ELAPSED_REALTIME_CLOCK).setOnClickListener(this); 28 findViewById(R.id.ELAPSED_REALTIME_WAKEUP_CLOCK).setOnClickListener( 29 this); 30 findViewById(R.id.RTC_CLOCK).setOnClickListener(this); 31 findViewById(R.id.RTC_WAKEUP_CLOCK).setOnClickListener(this); 32 findViewById(R.id.repeating_clock).setOnClickListener(this); 33 findViewById(R.id.cancel_clock).setOnClickListener(this); 34 35 // 獲取AlarmManager對象 36 alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE); 37 38 // 創建Intent對象,action為android.intent.action.ALARM_RECEIVER 39 Intent intent = new Intent("android.intent.action.ALARM_RECEIVER"); 40 operation = PendingIntent.getBroadcast(this, 0, intent, 0); 41 } 42 43 @Override 44 public void onClick(View v) { 45 switch (v.getId()) { 46 case R.id.ELAPSED_REALTIME_CLOCK: 47 // 在指定的演示后,發送廣播,並喚醒設備 48 // 延時是要把系統啟動的時間SystemClock.elapsedRealtime()算進去的 49 int triggerAtTime = (int) (SystemClock.elapsedRealtime() + 10 * 1000); 50 alarmManager.set(AlarmManager.ELAPSED_REALTIME, triggerAtTime, operation); 51 break; 52 case R.id.ELAPSED_REALTIME_WAKEUP_CLOCK: 53 // 在指定的演示后,發送廣播,並喚醒設備 54 // 延時是要把系統啟動的時間SystemClock.elapsedRealtime()算進去的 55 int triggerAtTime1 = (int) (SystemClock.elapsedRealtime() + 5 * 1000); 56 alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 57 triggerAtTime1, operation); 58 break; 59 case R.id.RTC_CLOCK:// 在指定的時刻,發送廣播,但不喚醒設備 60 alarmManager.set(AlarmManager.RTC, 61 getDateMills("2014-08-30 10:06:00"), operation); 62 break; 63 case R.id.RTC_WAKEUP_CLOCK:// 在指定的時刻,發送廣播,並喚醒設備 64 alarmManager.set(AlarmManager.RTC_WAKEUP, 65 getDateMills("2014-08-30 10:10:00"), operation); 66 break; 67 case R.id.repeating_clock:// 設置重復鬧鍾 68 alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, 5000, 10000, 69 operation); 70 break; 71 case R.id.cancel_clock:// 取消鬧鍾 72 alarmManager.cancel(operation); 73 break; 74 default: 75 break; 76 } 77 } 78 79 @SuppressLint("SimpleDateFormat") 80 public long getDateMills(String dateStr) { 81 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd kk:mm:ss"); 82 Date date; 83 try { 84 date = format.parse(dateStr); 85 return date.getTime(); 86 } catch (ParseException e) { 87 e.printStackTrace(); 88 } 89 return 0; 90 } 91 }
activity_main.xml
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical" > 6 7 <Button 8 android:id="@+id/ELAPSED_REALTIME_CLOCK" 9 android:layout_width="match_parent" 10 android:layout_height="wrap_content" 11 android:text="一次性鬧鍾:ELAPSED_REALTIME" /> 12 13 <Button 14 android:id="@+id/ELAPSED_REALTIME_WAKEUP_CLOCK" 15 android:layout_width="match_parent" 16 android:layout_height="wrap_content" 17 android:text="一次性鬧鍾:ELAPSED_REALTIME_WAKEUP " /> 18 19 <Button 20 android:id="@+id/RTC_CLOCK" 21 android:layout_width="match_parent" 22 android:layout_height="wrap_content" 23 android:text="一次性鬧鍾:RTC " /> 24 25 <Button 26 android:id="@+id/RTC_WAKEUP_CLOCK" 27 android:layout_width="match_parent" 28 android:layout_height="wrap_content" 29 android:text="一次性鬧鍾:RTC_WAKEUP_CLOCK" /> 30 31 <Button 32 android:id="@+id/repeating_clock" 33 android:layout_width="match_parent" 34 android:layout_height="wrap_content" 35 android:text="設置重復鬧鍾" /> 36 37 <Button 38 android:id="@+id/cancel_clock" 39 android:layout_width="match_parent" 40 android:layout_height="wrap_content" 41 android:text="取消鬧鍾" /> 42 43 </LinearLayout>
這樣,一個簡單的鬧鍾就完成了,呼~我的目標是做一個真正可以使用的鬧鍾,再接再厲!也歡迎大家關注我的博客!
作者:登天路
轉載請說明出處:http://www.cnblogs.com/travellife/
源碼下載:百度雲盤