Widget sending multiple types of intentions

I create a widget with several buttons, each of which sends its intention to the broadcast receiver. The broadcast receiver is supposed to display a Toast message based on which the button was pressed. The code now looks like this:

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); } } } 

and BroadcastReceiver:

 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(); } } 

My problem is that Widget pressed: 4 always displayed no matter which button is pressed. If I put the four lines of intent4 , intent4.putExtra() , pendingIntent4 and remoteViews.setOnClickPendingIntent() above all other intentions, it will always say Widget pressed: 3 . In other words, whatever the last registration of intentions is, that is, the widget displayed in the Toast message.

Does anyone know why this doesn't work the way I want?

+1
android android-intent android-widget android-pendingintent broadcastreceiver
Jun 17 '13 at 20:50
source share
3 answers

you need to provide a separate request code for each 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); 
+15
Mar 05 '14 at 2:01
source share

Your PendingIntents will be overwritten next. This is because they compare the intent, which is encapsulated, and the additional functions are not taken into account when comparing the intentions. Do this for every intention:

 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); 
+1
Jun 17 '13 at 20:57
source share

It looks like PendingIntent.getBroadcast () is ignoring requestCode (unlike PendingIntent.getActivity).

Thus, to make PendingIntents unique, you could provide data for the intent.

Example:

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

Then make your pending hint as usual, including requestCode.

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

With a Data element in Intent, the corresponding Intent filter in AndroidManifest.xml should also have a Data element:

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

The above intent filter works because only the schema has been identified (ie "http"). Thus, any Uri with this scheme will correspond to this filter β€œdata” element and the corresponding Receiver class will be called.

Notes:

  • NotificationReceiver is my class extending BroadcastReceiver
  • NotificationReceiver.INTENT - A constant String declared in NotificationReceiver. In this example, it will be equal to "my.package.my_action_string";
  • request_code can be anything. Make it unique and save it if you want to refer to the same pending hint in the future (say, to cancel the alarm that uses it).

Additional information about the data test with Intent Filters settings:

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

0
Oct 18 '15 at 22:00
source share



All Articles