-
简单闹钟实现
1、建立一个AlarmReceiver继承入BroadcastReceiver,并在AndroidManifest.xml声明
publicstatic class AlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "闹钟提示:时间到!",Toast.LENGTH_LONG).show();
}
}
2、建立Intent和PendingIntent,来调用目标组件。
Intentintent = new Intent(this, AlarmReceiver.class);
PendingIntentpendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
3、设置闹钟
获取闹钟管理的实例:
AlarmManageralarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
设置单次闹钟:
alarmManager.set(AlarmManager.RTC_WAKEUP,System.currentTimeMillis() + (5*1000), pendingIntent);
设置周期闹钟:
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis() + (10*1000), (24*60*60*1000),pendingIntent);
-
Android闹钟数据存储
闹钟数据存储主要分两种存储方式:
-
以ContentProvide实现数据存储
ContentProvide形式存储的数据主要包括:闹钟是否已启动,闹钟时间(时:分),闹钟日期,闹钟振动,闹钟标签等内容。
-
以SharePreference实现数据存储。
SharePreference形式存储的数据主要包括:闹钟贪睡时间ID,闹钟时间(时:分)。
-
时钟主界面
主界面实现函数为DeskClock.java类实现的,mNextAlarm显示下一个闹铃的时间,如果没有闹铃,则该控件隐藏掉。
在函数refreshAlarm()中获得下一个闹铃时间。
-
设置闹钟
在Android系统中,闹钟列表界面有类AlarmClock.java类实现的,当选择添加一个类时,调用
privatevoid addNewAlarm() {
startActivity(newIntent(this, SetAlarm.class));
}
当修改已有的闹钟时,通过获得修改闹钟的ID,进入闹钟设置界面
publicboolean onContextItemSelected(final MenuItem item) {
finalAdapterContextMenuInfo info =
(AdapterContextMenuInfo)item.getMenuInfo();
finalint id = (int) info.id;
…..
caseR.id.edit_alarm:
Intentintent = new Intent(this, SetAlarm.class);
intent.putExtra(Alarms.ALARM_ID,id);
startActivity(intent);
returntrue;
}
在闹钟的设置界面由SetAlarm.java类实现的。该类继承了父类PreferenceActivity,同时实现了接口TimePickerDialog.OnTimeSetListener和接口Preference.OnPreferenceChangeListener。
在该界面可以实现闹钟是否启动,闹钟时间,闹钟日期,闹钟振动,闹钟标签等内容选择,当选择完成后调用SaveAlarm函数,通过Alarms类中的接口函数AddAlarm或SetAlarm将数据存储。
private longsaveAlarm() {
Alarm alarm =new Alarm();
alarm.id =mId;
alarm.enabled= mEnabledPref.isChecked();
alarm.hour =mHour;
alarm.minutes= mMinutes;
alarm.daysOfWeek= mRepeatPref.getDaysOfWeek();
alarm.vibrate= mVibratePref.isChecked();
alarm.label =mLabel.getText();
alarm.alert =mAlarmPref.getAlert();
long time;
if (alarm.id== -1) {
time =Alarms.addAlarm(this, alarm);
mId =alarm.id;
} else {
time =Alarms.setAlarm(this, alarm);
}
return time;
}
-
保存闹钟
Android系统中闹钟数据存储,删除,修改等工作由类Alarms.java完成。
AddAlarm添加一个闹钟
deleteAlarm删除一个闹钟存储数据
deleteAllAlarm删除所有的闹钟存储数据
disableAlert取消该闹钟
disableSnoozeAlert取消贪睡闹钟
enableAlarm闹钟enable选项修改
enableAlert启动该闹钟
setAlarm重设闹钟数据
setNextAlert设置系统下一个闹钟,首先比较已有闹钟的时间,选择最接近系统的闹钟,然后判断是否有贪睡闹钟,如果有,则比较贪睡闹钟与设置闹钟的时间设置,最终选择最近的闹钟。
publicstatic void setNextAlert(final Context context) {
Alarmalarm = calculateNextAlert(context);
longtime = getSnoozeAlert(context);
if((alarm != null && alarm.time <= time)
||(alarm != null && time == -1)) {
enableAlert(context,alarm, alarm.time);
}
elseif((alarm != null && time < alarm.time)
||(alarm == null && time != -1)) {
enableSnoozeAlert(context);
}
else{
disableAlert(context);
} }
calculateNextAlert计算距离系统时间最近的闹钟,并获取
saveSnoozeAlert函数将闹钟贪睡后的贪睡闹钟以SharePerference形式进行保存。
staticvoid saveSnoozeAlert(final Context context, final int id,
finallong time) {
SharedPreferencesprefs = context.getSharedPreferences(
AlarmClock.PREFERENCES,0);
if(id == -1) {
clearSnoozePreference(context,prefs);
}else {
SharedPreferences.Editored = prefs.edit();
ed.putInt(PREF_SNOOZE_ID,id);
ed.putLong(PREF_SNOOZE_TIME,time);
ed.apply();
}
//Set the next alert after updating the snooze.
setNextAlert(context);
}
-
执行闹钟
通过函数enableAlert向系统发送广播
privatestatic void enableAlert(Context context, final Alarm alarm,
finallong atTimeInMillis) {
AlarmManager am =(AlarmManager)
context.getSystemService(Context.ALARM_SERVICE);
if(Log.LOGV) {
Log.v("**setAlert id " + alarm.id + " atTime " +atTimeInMillis);
}
Intentintent = new Intent(ALARM_ALERT_ACTION);
Parcelout = Parcel.obtain();
alarm.writeToParcel(out,0);
out.setDataPosition(0);
intent.putExtra(ALARM_RAW_DATA,out.marshall());
PendingIntent sender= PendingIntent.getBroadcast(
context, 0, intent,PendingIntent.FLAG_CANCEL_CURRENT);
am.set(AlarmManager.POWER_OFF_WAKEUP,atTimeInMillis, sender);
alarm_flag_setup(context,atTimeInMillis,alarm);
setStatusBarIcon(context,true);
Calendarc = Calendar.getInstance();
c.setTimeInMillis(atTimeInMillis);
StringtimeString = formatDayAndTime(context, c);
saveNextAlarm(context,timeString);
}
当系统获取该广播后,Android系统按照所设置的时间启动闹钟服务。
-
闹钟响应
广播接收类AlarmReceiver在AndroidManifest.xml文件中注册内容如下:
<receiverandroid:name="AlarmReceiver">
<intent-filter>
<actionandroid:name="com.android.deskclock.ALARM_ALERT" />
<actionandroid:name="alarm_killed" />
<actionandroid:name="cancel_snooze" />
<actionandroid:name="android.intent.action.ACTION_SHUTDOWN" />
<actionandroid:name="android.intent.action.FAKE_SHUTDOWN_ON" />
<actionandroid:name="android.intent.action.ACTION_SHUTDOWN" />
<actionandroid:name="android.intent.action.FAKE_BOOT_COMPLETED" />
</intent-filter>
</receiver>
当闹钟按照所设置的时间,发送广播消息com.android.deskclock.ALARM_ALERT后,将启动AlarmReceiver中OnReceive函数。
在OnReceive中主要做如下工作:
-
如果该闹钟是贪睡闹钟,则清除掉该闹钟数据;
-
如果该闹钟是重复执行,则计算获得距离当前系统时间最近的一个闹钟作为下一个闹钟;
-
判断手机是否关机,如果关机,则return;
-
关闭dialog,将窗口灰置;
-
启动闹钟铃声服务;
-
修改状态栏等操作;
闹钟铃声服务由AlarmKlaxon.java类完成。
当在闹钟弹出窗口后,点击确定,则发出stopService广播,关闭闹钟铃声,同时设置闹钟贪睡时间,点击取消,则发送stopService广播,关闭闹钟。
在锁屏界面闹钟响应时,AlarmAlertFullScreen.java完成
在非锁屏界面下响应时,AlarmAlertextends AlarmAlertFullScreen完成,主要是2秒屏幕响应时间
-
问题
1/最多可以实现几个闹钟贪睡
2/如果有两个闹钟响起,前面一个会停止,后面一个会响起
3/每设置一次闹钟,闹钟列表就重新比较一次,得到时间最近的闹钟
4/闹钟重复设置,存储数据计算