/* * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.micode.notes.ui; import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.DialogInterface.OnDismissListener; import android.content.Intent; import android.media.AudioManager; import android.media.MediaPlayer; import android.media.RingtoneManager; import android.net.Uri; import android.os.Bundle; import android.os.PowerManager; import android.provider.Settings; import android.view.Window; import android.view.WindowManager; import net.micode.notes.R; import net.micode.notes.data.Notes; import net.micode.notes.tool.DataUtils; import java.io.IOException; public class AlarmInitReceiver extends BroadcastReceiver { // 创建一个字符串数组,这里面写的是我们从数据库查询笔记信息的时候,想要获取的具体列的名字,在这里只打算获取笔记的ID和笔记的提醒日期这两列内容哦 private static final String [] PROJECTION = new String [] { NoteColumns.ID, NoteColumns.ALERTED_DATE }; // 定义一个常量,用来标记在查询结果集里,笔记ID这一列对应的位置序号,这里设为0,就是对应着上面PROJECTION数组里第一个元素的位置,方便后面准确地从结果里取出笔记ID的值 private static final int COLUMN_ID = 0; // 同样的道理,定义这个常量是为了标记在查询结果集里,提醒日期这一列对应的位置序号,设为1,对应着PROJECTION数组里第二个元素的位置,方便取提醒日期的值 private static final int COLUMN_ALERTED_DATE = 1; // 重写了BroadcastReceiver类里的onReceive方法哦,这个方法可重要啦,当这个广播接收器(也就是AlarmInitReceiver类的实例)收到广播消息的时候,就会自动调用这个方法来处理后续的事儿呢 @Override public void onReceive(Context context, Intent intent) { // 先获取一下当前系统的时间,这个时间是以毫秒为单位的,就像给当前时刻打了个时间戳一样,后面会拿这个时间和数据库里存的笔记提醒时间去做对比哦 long currentDate = System.currentTimeMillis(); // 通过安卓提供的内容解析器(它就像是个数据库操作的“小秘书”,能帮我们和数据库打交道)发起一个查询操作。 // 要查询的数据来源是Notes.CONTENT_NOTE_URI指定的地方(一般就是笔记相关的数据库表对应的一个地址啦), // 查询哪些列呢,就是前面定义的PROJECTION数组里写的那些列啦。 // 查询条件是这样的:只找提醒日期大于当前日期的,并且笔记类型是Notes.TYPE_NOTE(这个Notes.TYPE_NOTE在Notes类里应该有具体定义,表示某种特定类型的笔记)的记录, // 把当前日期作为参数传给查询条件(要转成字符串格式哦),最后的null表示我们暂时不需要对查询结果进行排序之类的额外操作啦。 Cursor c = context.getContentResolver().query(Notes.CONTENT_NOTE_URI, PROJECTION, NoteColumns.ALERTED_DATE + ">? AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE, new String[] { String.valueOf(currentDate) }, null); // 判断一下查询出来的结果集(也就是那个Cursor对象)是不是为空呀,如果不是空的,那就说明有符合条件的数据,咱们就可以接着往下处理这些数据啦 if (c!= null) { // 把游标(就是那个在结果集里“游走”的指针一样的东西)移动到第一条数据的位置上,如果能成功移动过去(也就是有数据),那就返回true,然后就可以进入循环去处理每条数据啦 if (c.moveToFirst()) { do { // 从游标当前指向的这行数据里,按照之前定义好的提醒日期列对应的索引(COLUMN_ALERTED_DATE),取出提醒日期这个列的值,这个值是个时间戳,用long类型的变量alertDate来接收它哦 long alertDate = c.getLong(COLUMN_ALERTED_DATE); // 创建一个新的Intent对象,这个Intent就像是一个任务清单,告诉安卓系统等会儿要去启动哪个组件,这里指定的是要启动AlarmReceiver类对应的组件哦,通常后面会配合闹钟管理的相关操作来用呢 Intent sender = new Intent(context, AlarmReceiver.class); // 利用ContentUris这个“小助手”,把当前这条笔记的ID(从游标里根据COLUMN_ID索引取出来的)附加到Notes.CONTENT_NOTE_URI这个基本的笔记资源地址上,这样就构成了一个完整的、专门指向这条笔记记录的Uri啦, // 然后把这个完整的Uri设置到刚才创建的Intent的Data属性里,这样接收这个Intent的地方(比如AlarmReceiver)就能知道是哪个笔记对应的闹钟触发了相关操作哦 sender.setData(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, c.getLong(COLUMN_ID))); // 创建一个PendingIntent对象,它是基于前面创建的那个Intent来的,相当于给这个Intent包了一层“外衣”,让它可以在特定条件下(像等会儿闹钟时间一到这种情况)去启动对应的组件呢, // 这里的参数0表示请求码(目前我们没什么特殊的请求码需求,就先用0啦),sender就是要执行的那个Intent,最后的0表示一些标志位,暂时用默认的0就行啦 PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, sender, 0); // 从安卓系统里获取AlarmManager这个闹钟管理的“大管家”,通过上下文对象的getSystemService方法,传入Context.ALARM_SERVICE这个标识就能获取到啦,后面就用它来设置闹钟相关的各种事儿哦 AlarmManager alermManager = (AlarmManager) context .getSystemService(Context.ALARM_SERVICE); // 让AlarmManager这个“大管家”去设置一个闹钟啦,这里指定闹钟的类型是RTC_WAKEUP,意思就是按照绝对时间来触发闹钟(就是指定的那个alertDate时间),而且如果设备当时处于睡眠状态的话,还会把设备唤醒哦, // alertDate就是刚才从游标里取出来的提醒时间,pendingIntent就是等闹钟触发时要去执行的操作(比如启动对应的组件之类的)啦 alermManager.set(AlarmManager.RTC_WAKEUP, alertDate, pendingIntent); } while (c.moveToNext()); } // 用完游标了,要记得关闭它呀,就像看完书要把书签收起来一样,关闭游标可以释放相关的资源,避免占用太多内存,造成不好的影响呢 c.close(); } } }