关于android中PendingIntent.getBroadcase的注册广播VSAlarmManager .cancle(PendingIntent)如何区分PendingIntent

使用语句

[java]  view plain copy
  1. PendingIntent intent= PendingIntent.getBroadcast(Context context, int requestCode, Intent intent, int flags)  


获得PendingIntent,浏览了各类文章,大多数说了这种方法,但是基本上也就是止步于此,可是还有最重要的没有谈及,如何区别多个已注册的PendingIntent呢,看了一下PendingIntent.getBroadcast的javadoc,第四个参数flags意为标记,初步认为flags是标识各个PendingIntent的,于是在测试中设置了个全局变量

[java]  view plain copy
  1. public static int currentIntent=0;  


然后用currentIntent++作为第四个参数传递进去,测试,注册了两个监听,等待时间的到来,bingo,居然可以了,目测已经可以。可是继续深入时问题来了,我要传递参数怎样?正解做法就是在第三个参数中设置

[java]  view plain copy
  1. intent.setExtra(String key,String value);  //设置传递的参数  

然后在自己实现的Receiver里用传进来的参数Intent intent实现

[java]  view plain copy
  1. intent.getIntegerExtra(String key);  


就可以获得参数,可以真正在实现的时候发现,在receiver里始终取不到参数,再经过一番查找,发现要把PendingIntent.getBroadcast的第四个参数设置于PendingIntent.FLAG_UPDATE_CURRENT,设置后测试,果然可以,可是这样问题又出来了,又要如何区别注册的intent呢?再次查看getBroadcast的javadoc,几个参数都没有说明如何区别要注册的PendingIntent,反而看到第二个参数的说明很神奇,就是这个参数目前为保留状态,仍未用到,无奈中,继续search各种说法,才发现,用requestCode来区别居然是可以的(可是为什么javadoc要说该参数未被使用呢?不解;估计用于区分PendingIntent的方法就是其中任意一个参数不同便可以区分了)代码如下:

设置监听

[java]  view plain copy
  1. Intent setAlertIntent=new Intent(this,AlertReceiver.class);  
  2. setAlertIntent.putExtra("try""i'm just have a try");  
  3. PendingIntent pendingIntent=PendingIntent.getBroadcast(this, alarmCount++, setAlertIntent,PendingIntent.FLAG_UPDATE_CURRENT);  
  4.   
  5. AlarmManager alarmManager=(AlarmManager)getSystemService(ALARM_SERVICE);  
  6. alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 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("*******");

结果还是一样!囧! PendingIntent 文档说明:

public boolean equals (Object otherObj)

Added in  API level 1

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.

Parameters
otherObj the object to compare this instance with.
Returns
  • true if the specified object is equal to this Objectfalse 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
    }


这里实在没有能力读下去了 :(    先放一边了。。

你可能感兴趣的:(Android中级)