使用语句
获得PendingIntent,浏览了各类文章,大多数说了这种方法,但是基本上也就是止步于此,可是还有最重要的没有谈及,如何区别多个已注册的PendingIntent呢,看了一下PendingIntent.getBroadcast的javadoc,第四个参数flags意为标记,初步认为flags是标识各个PendingIntent的,于是在测试中设置了个全局变量
然后用currentIntent++作为第四个参数传递进去,测试,注册了两个监听,等待时间的到来,bingo,居然可以了,目测已经可以。可是继续深入时问题来了,我要传递参数怎样?正解做法就是在第三个参数中设置
然后在自己实现的Receiver里用传进来的参数Intent intent实现
就可以获得参数,可以真正在实现的时候发现,在receiver里始终取不到参数,再经过一番查找,发现要把PendingIntent.getBroadcast的第四个参数设置于PendingIntent.FLAG_UPDATE_CURRENT,设置后测试,果然可以,可是这样问题又出来了,又要如何区别注册的intent呢?再次查看getBroadcast的javadoc,几个参数都没有说明如何区别要注册的PendingIntent,反而看到第二个参数的说明很神奇,就是这个参数目前为保留状态,仍未用到,无奈中,继续search各种说法,才发现,用requestCode来区别居然是可以的(可是为什么javadoc要说该参数未被使用呢?不解;估计用于区分PendingIntent的方法就是其中任意一个参数不同便可以区分了)代码如下:
设置监听
Receiver中获取传递的数据:
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Bundle bundle= intent.getExtras();
if(bundle==null){
Toast.makeText(context,"nothing", Toast.LENGTH_LONG).show();
}else{
Set set=bundle.keySet();
for(String item:set){
System.out.println(item);
System.out.println(".............");
}
Toast.makeText(context,bundle.getCharSequence("try"), Toast.LENGTH_LONG).show();
}
}
以上转自:http://blog.csdn.net/huang_hws/article/details/7327670
上面写得非常不错!但是抛出了一个问题:如何区别要注册的PendingIntent ?真的是以requestCode来区分的?
实际上,并不是以requestCode来区分
不妨做个试验1:
Intent intent = new Intent("MyReceiver");
Intent _intent = new Intent("LOL"); //注意这里是 _intent !有下划线的
PendingIntent p = PendingIntent.getBroadcast(AlarmMainActivity.this, 0, intent,PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent p1 = PendingIntent.getBroadcast(AlarmMainActivity.this, 1, intent,PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent p2 = PendingIntent.getBroadcast(AlarmMainActivity.this, 0, intent,PendingIntent.FLAG_CANCEL_CURRENT);
PendingIntent p3 = PendingIntent.getBroadcast(AlarmMainActivity.this, 0, _intent,PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent p4 = PendingIntent.getBroadcast(AlarmMainActivity.this, 0, intent,PendingIntent.FLAG_UPDATE_CURRENT);
System.out.println("*******");
if(p == p1)System.out.println("p1==p");
if(p == p2)System.out.println("p2==p");
if(p == p3)System.out.println("p3==p");
if(p == p4)System.out.println("p4==p");
System.out.println("*******");
结果输出:
很吃惊!居然p1 - 4都没有一个跟p 是同一个引用,说明每调用PendingIntent.getBroadcast(.....),构造的PendingIntent都不一样,哪怕是构造参数也一样。
那么AlarmManager.cancle(PendingIntent operation)这注销PendingIntent的函数是如何实现注销的的功能的?
该方法在Android API Docs 中的解析:
Remove any alarms with a matching Intent. Any alarm, of any type, whose Intent matches this one (as defined by filterEquals(Intent)), will be canceled.
关于如何matches Intent,又转移到: filterEquals(Intent) 这方法(在Intent类中)
该方法在Android API Docs 中的解析:
public boolean filterEquals (Intent other)
Determine if two intents are the same for the purposes of intent resolution (filtering). That is, if their action, data, type, class, and categories are the same. This does not compare any extra data included in the intents.
这里说明只比较action data type class categories 而不比较里面的extra data(e.g. Bundle 、extra string int long ....)
所以这样就可以理解到cancle()的实现方式
但是国外大神们都说更requestCode 有关 参考: http://stackoverflow.com/questions/3273342/how-can-i-setup-multiple-alarms-in-android/3274576#3274576 不知道是不是我理解错了?(本人是弱菜>.<)
下面给出public boolean filterEquals (Intent other) 方法实现的源码:
public boolean filterEquals(Intent other) {
5489 if (other == null) {
5490 return false;
5491 }
5492 if (mAction != other.mAction) {
5493 if (mAction != null) {
5494 if (!mAction.equals(other.mAction)) {
5495 return false;
5496 }
5497 } else {
5498 if (!other.mAction.equals(mAction)) {
5499 return false;
5500 }
5501 }
5502 }
5503 if (mData != other.mData) {
5504 if (mData != null) {
5505 if (!mData.equals(other.mData)) {
5506 return false;
5507 }
5508 } else {
5509 if (!other.mData.equals(mData)) {
5510 return false;
5511 }
5512 }
5513 }
5514 if (mType != other.mType) {
5515 if (mType != null) {
5516 if (!mType.equals(other.mType)) {
5517 return false;
5518 }
5519 } else {
5520 if (!other.mType.equals(mType)) {
5521 return false;
5522 }
5523 }
5524 }
5525 if (mPackage != other.mPackage) {
5526 if (mPackage != null) {
5527 if (!mPackage.equals(other.mPackage)) {
5528 return false;
5529 }
5530 } else {
5531 if (!other.mPackage.equals(mPackage)) {
5532 return false;
5533 }
5534 }
5535 }
5536 if (mComponent != other.mComponent) {
5537 if (mComponent != null) {
5538 if (!mComponent.equals(other.mComponent)) {
5539 return false;
5540 }
5541 } else {
5542 if (!other.mComponent.equals(mComponent)) {
5543 return false;
5544 }
5545 }
5546 }
5547 if (mCategories != other.mCategories) {
5548 if (mCategories != null) {
5549 if (!mCategories.equals(other.mCategories)) {
5550 return false;
5551 }
5552 } else {
5553 if (!other.mCategories.equals(mCategories)) {
5554 return false;
5555 }
5556 }
5557 }
5558
5559 return true;
5560 }
后来我又发现原来PendingIntent复写了equals()的方法
所以我实验了一下: (替换了一下上面的)
System.out.println("*******");
if(p.equals(p1))System.out.println("p1==p");
if(p.equals(p2))System.out.println("p2==p");
if(p.equals(p3))System.out.println("p3==p");
if(p.equals(p4))System.out.println("p4==p");
System.out.println("*******");
Comparison operator on two PendingIntent objects, such that true is returned then they both represent the same operation from the same package. This allows you to use getActivity(Context, int, Intent, int)
, getBroadcast(Context, int, Intent, int)
, or getService(Context, int, Intent, int)
multiple times (even across a process being killed), resulting in different PendingIntent objects but whose equals() method identifies them as being the same operation.
otherObj | the object to compare this instance with. |
---|
true
if the specified object is equal to this Object
; false
otherwise. 564
@Override
565
public boolean equals(Object otherObj) {
566
if (otherObj instanceof PendingIntent) {
567
return mTarget.asBinder().equals(((PendingIntent)otherObj)
568
.mTarget.asBinder());
569
}
570
return false;
571
}