BroadcastReceiver实践:定义多个同行为闹钟(AlarmManager)服务

出现问题:如何设定很多个的闹钟( AlarmManager)启动同一个行为(Action),而又互不影响呢?

如果PendingIntent的flag用的FLAG_UPDATE_CURRENT,那一个新的闹钟任务不是会把旧的待响的闹钟任务更新掉吗?

关于PendingIntent的flag设置请看这里

解决思路:设定闹钟的服务先把所有要设定的闹钟信息,按时间的先后存储起来。并先设定时间最近的一个闹钟。当一个闹钟触发后,发送一个消息给设定闹钟的服务,服务得到消息后,再设定下一个闹钟,循环这一步,直到所有闹钟设定完成。

重点:闹钟触发后,怎么发送消息。以及在服务里如何接受消息。

以下贴出主要代码,已有注释:


Reminder类实现Comparable接口,重写compareTo方法,以排序。

public class Reminder implements Parcelable ,Comparable{//Parcelable接口是为了实现在传递此类型的数据,具体用法在此不多作介绍。
	private Date time;
	@Override
	public int describeContents() {
		return 0;
	}

	@Override
	public void writeToParcel(Parcel dest, int flags) {
		dest.writeLong(time.getTime());
	}

	public static final Parcelable.Creator<Reminder> CREATOR = new Parcelable.Creator<Reminder>() {
		public Reminder createFromParcel(Parcel in) {
			return new Reminder(in);
		}

		public Reminder[] newArray(int size) {
			return new Reminder[size];
		}
	};

	private Reminder(Parcel in) {
		time = new Date(in.readLong());
	}
	@Override
	public int compareTo(Object o) {
		if (o instanceof Reminder)//以Reminder的时间先后来排序
			return (int)(time.getTime()-((Reminder) o).getTime().getTime());
		return 0;
	}


主服务类,设定闹钟服务
public class MainService extends Service {
	Intent intent;
	ArrayList<Reminder> remAList;
	MainServReceiver receiver;
	public static final String rece_action = "com.lsto.action.SERVRE_ACTION";

	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	@Override
	public void onCreate() {
		// 代码方式注册BroadcastReceiver
		receiver = new MainServReceiver();
		IntentFilter filter = new IntentFilter(rece_action);
		registerReceiver(receiver, filter);
		super.onCreate();
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		ArrayList<Reminder> aList = intent
				.getParcelableArrayListExtra(Reminder.ARRAYKEY);
		if (aList != null) {
			remAList = (ArrayList<Reminder>) aList.clone();
			Collections.sort(remAList);//按Reminder的时间先后升序排序
			for (int i = 0; i < remAList.size(); i++) {
				if (remAList.get(i).isPastDue())
					remAList.remove(i);
			}
			setOneAlarm();
		}
		return START_STICKY;
	}

	/**
	 * 从排好序的List中获取第一个元素作为闹钟的信息,并设定一个闹钟服务。设定好后,从List中移除这个元素
	 */
	private void setOneAlarm() {
		if (remAList.size() == 0)
			return;
		Reminder Rem = remAList.get(0);
		// 闹钟服务用来启动通知服务
		Intent intent = new Intent();
		intent.setAction("com.lsto.SERV_NOTIFY");
		intent.putExtra(Reminder.KEY, Rem);
		PendingIntent piServ = PendingIntent.getService(this, 0, intent,
				PendingIntent.FLAG_UPDATE_CURRENT);
		AlarmManager aMan = (AlarmManager) getSystemService(Service.ALARM_SERVICE);
		aMan.set(AlarmManager.RTC_WAKEUP, Rem.getTime().getTime(), piServ);
		remAList.remove(0);
	}
//内部类继承BroadcastReceiver,接收到广播消息后,会回调实现的onReceive方法。在此该方法实现设定一个闹钟服务。
	public class MainServReceiver extends BroadcastReceiver {

		@Override
		public void onReceive(Context context, Intent intent) {
			setOneAlarm();
		}
	}
}

通知服务类部分代码,给系统的通知栏中发送消息,具体方法在此不多作解释。

public class NotifyServ extends Service {
	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}
	
	@Override
	public void onCreate() {
		super.onCreate();
	}

	public int onStartCommand(Intent intent, int flags, int startId) {
		Reminder rem = intent.getParcelableExtra(Reminder.KEY);
		setNotifyFromRem(rem);
		//发送广播消息,通知主服务设定下一个闹钟
		Intent sendIntent = new Intent(MainService.rece_action);
		sendBroadcast(sendIntent);
		return START_STICKY;
	}
...
...
...
}
本例已通过测试,但不知道什么原因,在LogCat中报以下错误,不过不影响正常使用。

04-21 20:46:21.256: E/ActivityThread(13926): Service com.lsto.MainService has leaked IntentReceiver com.lsto.MainService$MainServReceiver@4066cc68 that was originally registered here. Are you missing a call to unregisterReceiver()?

04-21 20:46:21.256: E/ActivityThread(13926): android.app.IntentReceiverLeaked: Service com.lsto.MainService has leaked IntentReceiver com.lsto.MainService$MainServReceiver@4066cc68 that was originally registered here. Are you missing a call to unregisterReceiver()?

总结—BroadcastReceiver的使用方法:

第一步,定义一个类继承BroadcastReceiver类,并实现onReceiver方法,这个方法就类似于监听器,一监听到有广播发出,就会被调用

public class MyReceiver extends BroadcastReceiver {

		@Override
		public void onReceive(Context context, Intent intent) {
		}
	}

第二步,指定匹配的Intent,不过有两种方式:

1.使用代码的方式

MyReceiver receiver = new MyReceiver();
IntentFilter filter = new IntentFilter("android.demo.MYRECEIVED");
registerReceiver(receiver, filter);

2.类似Activity和Service的方式,配置AndroidManifest.xml
<receiver android:name=".MyReceiver">
	<intent-filter>
		<action android:name="android.demo.MYRECEIVED"/>
	</intent-filter>
</receiver>

第三步,发送广播
Intent sendIntent = new Intent("android.demo.MYRECEIVED");
sendBroadcast(sendIntent);

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值