看似简单,实在涉及问题太多,有地方目前还是不解,先开篇放这,以后再写
相关文章:
1、《说说PendingIntent的内部机制》 绝对干货
2、《Android开发陷阱:利用PendingIntent传递唯一的Intent》我也碰到相同问题,详见备注
3、《Android-Intent和PendingIntent的关系》
4、《解决PendingIntent传递参数为空的问题》
5、《PendingIntent详解》
6、《PendingIntent详解 》
7、《Android中pendingIntent的深入理解》
备注:
这里有个问题:
以前在写博客时就发现了这个问题,到现在也一直无解,在写这篇文章《桌面widget详解(三)——桌面widget中的控件交互方法》我在博客里使用的是利用Intent.setData()的方式来传递的ID值,但如果用我们传统传递值的方式:intent.putExtra()来传ID值的话,在接收传过来的数值时,总是只有一个
发送时:
这里构造了两个不同的PendingIntent,而且设置了不同的RequestCode,RemoteView绑定如下:
@Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { // 创建一个Intent对象 Intent intent = new Intent(); intent.putExtra("id", R.id.btn1); intent.setAction(broadCastString); // 设置pendingIntent的作用 PendingIntent pendingIntent = PendingIntent.getBroadcast(context,UUID.randomUUID().hashCode(),intent, PendingIntent.FLAG_UPDATE_CURRENT); RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.example_appwidget); remoteViews.setOnClickPendingIntent(R.id.btn1, pendingIntent); // 创建一个Intent对象 Intent intent2 = new Intent(); intent2.putExtra("id", R.id.btn2); intent2.setAction(broadCastString); // 设置pendingIntent的作用 PendingIntent pendingIntent2 = PendingIntent.getBroadcast(context, UUID.randomUUID().hashCode(),intent2,PendingIntent.FLAG_UPDATE_CURRENT); RemoteViews remoteViews2 = new RemoteViews(context.getPackageName(),R.layout.example_appwidget); remoteViews2.setOnClickPendingIntent(R.id.btn2, pendingIntent2); // 更新Appwidget appWidgetManager.updateAppWidget(appWidgetIds, remoteViews); }接收时,问题来了:
在刚开始,intent.getIntExtra()时,返回的总是R.id.btn1,第二个按钮总是没有任何反应
@Override public void onReceive(Context context, Intent intent) { if (intent == null) { return; } String action = intent.getAction(); if (broadCastString.equals(action)) { int id = intent.getIntExtra("id", -1); String str = ""; if(id == R.id.btn1){ str ="btn 1 click:"; }else if(id == R.id.btn2){ str ="btn 2 click:"; } // 只能通过远程对象来设置appwidget中的控件状态 RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.example_appwidget); // 通过远程对象将按钮的文字设置为”一个随机数” Random random1 = new Random(); remoteViews.setTextViewText(R.id.text,str + random1.nextInt()); // 获得appwidget管理实例,用于管理appwidget以便进行更新操作 AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); // 相当于获得所有本程序创建的appwidget ComponentName componentName = new ComponentName(context,ExampleAppWidgetProvider.class); // 更新appwidget appWidgetManager.updateAppWidget(componentName, remoteViews); //这里没有绑定pendingIntent, } super.onReceive(context, intent); }
参考这篇文章:2、《Android开发陷阱:利用PendingIntent传递唯一的Intent》和PendingIntetn官方文档:http://developer.android.com/reference/android/app/PendingIntent.html
其中有句话:
A PendingIntent itself is simply a reference to a token maintained by the system describing the original data used to retrieve it. This means that, even if its owning application's process is killed, the PendingIntent itself will remain usable from other processes that have been given it. If the creating application later re-retrieves the same kind of PendingIntent (same operation, same Intent action, data, categories, and components, and same flags), it will receive a PendingIntent representing the same token if that is still valid, and can thus call cancel()
to remove it.
Because of this behavior, it is important to know when two Intents are considered to be the same for purposes of retrieving a PendingIntent. A common mistake people make is to create multiple PendingIntent objects with Intents that only vary in their "extra" contents, expecting to get a different PendingIntent each time. This does not happen. The parts of the Intent that are used for matching are the same ones defined by Intent.filterEquals
. If you use two Intent objects that are equivalent as per Intent.filterEquals
, then you will get the same PendingIntent for both of them.
There are two typical ways to deal with this.
If you truly need multiple distinct PendingIntent objects active at the same time (such as to use as two notifications that are both shown at the same time), then you will need to ensure there is something that is different about them to associate them with different PendingIntents. This may be any of the Intent attributes considered by Intent.filterEquals
, or different request code integers supplied to getActivity(Context, int, Intent, int)
, getActivities(Context, int, Intent[], int)
, getBroadcast(Context, int, Intent, int)
, or getService(Context, int, Intent, int)
.
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.
other | The other Intent to compare against. |
---|
写到这,发现了上面代码中的一个问题,即我使用了不同的RequestCode,但Intent之间,仅传递数值时仅用了不同的Extra域。
想到这,那我用不同的data域来试一下:
发送:
有没有看出来,下面的代码和《桌面widget详解(三)——桌面widget中的控件交互方法》第三部分:三、进阶——如何响应多个按钮控件,的区别了没,发送方法都是一致的,但这里使用的是匹配Action的匿名发送,而在《桌面widget详解(三)——桌面widget中的控件交互方法》使用的是指定类名的显示发送,但这里是发送不成功的,而显示指定是可以区别的。所以在上一篇博客中是可以成功的,其实在写上篇博客时,我就知道匿名发送是成功不了的,但不知道为什么,怕误解大家,所以就没提。
@Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { // 创建一个Intent对象 Intent intent = new Intent(); intent.setData(Uri.parse("harvic:" + R.id.btn1)); intent.setAction(broadCastString); // 设置pendingIntent的作用 PendingIntent pendingIntent = PendingIntent.getBroadcast(context, UUID .randomUUID().hashCode(), intent, PendingIntent.FLAG_UPDATE_CURRENT); RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.example_appwidget); remoteViews.setOnClickPendingIntent(R.id.btn1, pendingIntent); // 创建一个Intent对象 Intent intent2 = new Intent(); intent2.setData(Uri.parse("harvic:" + R.id.btn2)); intent2.setAction(broadCastString); // 设置pendingIntent的作用 PendingIntent pendingIntent2 = PendingIntent.getBroadcast(context, UUID .randomUUID().hashCode(), intent2, PendingIntent.FLAG_UPDATE_CURRENT); RemoteViews remoteViews2 = new RemoteViews(context.getPackageName(), R.layout.example_appwidget); remoteViews2.setOnClickPendingIntent(R.id.btn2, pendingIntent2); // 更新Appwidget appWidgetManager.updateAppWidget(appWidgetIds, remoteViews); }接收时:
根本接收不到任何东东!!!!!!!
public class ExampleAppWidgetProvider extends AppWidgetProvider { String broadCastString = "harvic.provider"; @Override public void onReceive(Context context, Intent intent) { if (intent == null) { return; } String action = intent.getAction(); if (broadCastString.equals(action)) { Uri data = intent.getData(); int resID = -1; if(data != null){ resID = Integer.parseInt(data.getSchemeSpecificPart()); } // 只能通过远程对象来设置appwidget中的控件状态 RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.example_appwidget); // 通过远程对象将按钮的文字设置为”一个随机数” Random random1 = new Random(); remoteViews.setTextViewText(R.id.text, resID +":" + random1.nextInt()); // 获得appwidget管理实例,用于管理appwidget以便进行更新操作 AppWidgetManager appWidgetManager = AppWidgetManager .getInstance(context); // 相当于获得所有本程序创建的appwidget ComponentName componentName = new ComponentName(context, ExampleAppWidgetProvider.class); // 更新appwidget appWidgetManager.updateAppWidget(componentName, remoteViews); // 这里没有绑定pendingIntent, } super.onReceive(context, intent); }
洋洋洒洒一大堆,现将问题记录于此,终有一天会海阔天空,相信自己