androidwidgetbroadcastreceiverandroid-widgetcommonsware

setData on RemoteViewService intents


What is the use of

serviceIntent.setData(Uri.parse(serviceIntent.toUri(Intent.URI_INTENT_SCHEME)));

on the following Intent in an AppWidgetProvider class (see code below)

According to the CommonsWare book, the reason is:

While your application has access to your RemoteViewsService Class object, the app widget host will not, and so we need something that will work across process boundaries. You could elect to add your own to the RemoteViewsService and use an Intent based on that, but that would make your service more publicly visible than you might want.

Source: The Busy Coder's Guide to Android Development https://commonsware.com/Android/

But when I delete this line, nothing changes. The widget still works.

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

        [...]

        Intent serviceIntent = new Intent(context, WidgetService.class);
        serviceIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
        serviceIntent.setData(Uri.parse(serviceIntent.toUri(Intent.URI_INTENT_SCHEME)));

        views.setRemoteAdapter(R.id.stack_view, serviceIntent);
        views.setEmptyView(R.id.stack_view, R.id.empty_view);

        [...]

        appWidgetManager.updateAppWidget(appWidgetId, views);
    }

Solution

  • I figured it out. If you don't use setData, the system can not distinguish between different service intents, which causes it to call onGetViewFactory only once for multiple widgets and send the same intent to all of them. If you for example send the app widget id to your RemoteViewsService and from their to your RemoteViewsFactory and display it in every item, it will display the same id for all instances of the widget, if you don't use setData.