1

我正在构建一个具有多个按钮的小部件,每个按钮都将自己的意图发送到广播接收器。广播接收器应该根据按下的按钮显示 Toast 消息。目前的代码如下所示:

public class WidgetProvider extends AppWidgetProvider {

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds){

        ComponentName thisWidget = new ComponentName(context, WidgetProvider.class);
        int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
        for (int widgetId : allWidgetIds) {
            RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout);

            SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);

            // Set the text of the buttons
            remoteViews.setTextViewText(R.id.widgetPreset1Button, prefs.getString("widget1", "Not set"));
            remoteViews.setTextViewText(R.id.widgetPreset2Button, prefs.getString("widget2", "Not set"));
            remoteViews.setTextViewText(R.id.widgetPreset3Button, prefs.getString("widget3", "Not set"));
            remoteViews.setTextViewText(R.id.widgetPreset4Button, prefs.getString("widget4", "Not set"));

            // Register the buttons with an OnClick event
            Intent intent1 = new Intent("myapp.SendWidgetPreset");
            intent1.putExtra("Widget", 1);
            PendingIntent pendingIntent1 = PendingIntent.getBroadcast(context, 0, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
            remoteViews.setOnClickPendingIntent(R.id.widgetPreset1Button, pendingIntent1);

            Intent intent2 = new Intent("myapp.SendWidgetPreset");
            intent2.putExtra("Widget", 2);
            PendingIntent pendingIntent2 = PendingIntent.getBroadcast(context, 0, intent2, PendingIntent.FLAG_UPDATE_CURRENT);
            remoteViews.setOnClickPendingIntent(R.id.widgetPreset2Button, pendingIntent2);

            Intent intent3 = new Intent("myapp.SendWidgetPreset");
            intent3.putExtra("Widget", 3);
            PendingIntent pendingIntent3 = PendingIntent.getBroadcast(context, 0, intent3, PendingIntent.FLAG_UPDATE_CURRENT);
            remoteViews.setOnClickPendingIntent(R.id.widgetPreset3Button, pendingIntent3);

            Intent intent4 = new Intent("myapp.SendWidgetPreset");
            intent4.putExtra("Widget", 4);
            PendingIntent pendingIntent4 = PendingIntent.getBroadcast(context, 0, intent4, PendingIntent.FLAG_UPDATE_CURRENT);
            remoteViews.setOnClickPendingIntent(R.id.widgetPreset4Button, pendingIntent4);

            new WidgetBroadcastReceiver();

            appWidgetManager.updateAppWidget(widgetId, remoteViews);
        }
    }
}

和广播接收器:

public class WidgetBroadcastReceiver extends BroadcastReceiver{

    public WidgetBroadcastReceiver(){
    }

    @Override
    public void onReceive(Context context, Intent arg1) {
        int widget = arg1.getIntExtra("Widget", -1);

        Toast.makeText(context, "Widget pressed: " + widget, Toast.LENGTH_SHORT).show();    
    }
}

我的问题是Widget pressed: 4无论按下哪个按钮,它都会显示。如果我将这四行intent4, intent4.putExtra(), pendingIntent4, 和remoteViews.setOnClickPendingIntent()所有其他意图放在首位,那么它总是会说Widget pressed: 3. 换句话说,无论最后的意图注册是什么,它都是在 Toast 消息中显示的小部件。

任何人都知道为什么这不符合我的要求吗?

4

3 回答 3

18

您需要为每个pendingintent ex 提供单独的请求代码:

PendingIntent pendingIntent1 = PendingIntent.getBroadcast(context, 0, intent1, PendingIntent.FLAG_UPDATE_CURRENT); 
PendingIntent pendingIntent1 = PendingIntent.getBroadcast(context, 1/*request code*/, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
于 2014-03-05T02:01:39.583 回答
1

您的 PendingIntents 正在被下一个覆盖。这是因为它们比较被封装的 Intent,并且在比较 Intent 时不考虑额外内容。为每个意图执行此操作:

Intent intent1 = new Intent("myapp.SendWidgetPreset");
intent1.putExtra("Widget", 1);

// This line makes your intents different
intent1.setData(Uri.parse(intent1.toUri(Intent.URI_INTENT_SCHEME)));

PendingIntent pendingIntent1 = PendingIntent.getBroadcast(context, 0, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.widgetPreset1Button, pendingIntent1);
于 2013-06-17T20:57:54.787 回答
1

似乎 PendingIntent.getBroadcast() 将忽略 requestCode(与 PendingIntent.getActivity 不同)。

因此,要制作独特的 PendingIntent,您可以为 Intent 提供数据。

例子:

public static Intent makeUniqueIntent(String action, int requestCode) {
        Intent intent = new Intent(action);
        intent.setData(Uri.parse("http://"+ String.valueOf(requestCode)));
        return intent;
    }

然后像往常一样制作你的待处理意图,包括 requestCode。

PendingIntent.getBroadcast(ctx, request_code,
                makeUniqueIntent(NotificationReceiver.INTENT, request_code),
                PendingIntent.FLAG_CANCEL_CURRENT);

对于 Intent 中的 Data 元素,AndroidManifest.xml 中的匹配 Intent Filter 还必须具有 Data 元素:

<receiver android:name=".service.NotificationReceiver">
       <intent-filter>
           <action android:name="my.package.my_action_string"/>
           <data android:scheme="http"/>
       </intent-filter>
</receiver>

上述意图过滤器仅作为一种方案(即“http”)被识别。因此,任何具有该方案的 Uri 都将匹配此过滤器的“数据”元素,并且将调用相应的 Receiver 类。

笔记:

  • NotificationReceiver 是我的课,扩展 BroadcastReceiver
  • NotificationReceiver.INTENT 是我在 NotificationReceiver 中声明的字符串常量。在此示例中,它将等于“my.package.my_action_string”;
  • request_code 可以是任何东西。如果您想在将来引用相同的 Pending Intent(例如取消使用它的警报),请使其唯一并保存它。

有关使用 Intent 过滤器进行数据测试的更多信息:

http://developer.android.com/guide/components/intents-filters.html#DataTest

于 2015-10-18T22:00:58.793 回答