2

Instead of showing the user a list of widget provider, I let him select one and then configure the widget, I manually load all widget providers and let the user drag and drop those widgets in my app. As soon as the user drops such an icon, I want to create and configure this widget. How do I do this?

Code with comments

// 1) get a list of all app widget providers
List<AppWidgetProviderInfo> providers = mAppWidgetManager.getInstalledProviders();

// 2) Display the list to the user and let him select a widget provider => done via custom UI

// 3) handle the user selected widget and create it
// 3.1) create new widget id 
int appWidgetId = mAppWidgetHost.allocateAppWidgetId();
// 3.2) configure widget
// ??? How do I do this now? appWidgetInfo.configure = null, so I can't use this as I  normally would do it
// 4) Save the appWidgetId or delete it again depending on if the user finished the setup or cancelled it

Normal approach (not important for my use case, but generally describes how it works)

  • create a widget id and then use the AppWidgetManager.ACTION_APPWIDGET_PICK intent to let the user pick a widget
  • after selection, pass on the data to the AppWidgetManager.ACTION_APPWIDGET_CONFIGURE intent and use intent.setComponent(appWidgetInfo.configure);
  • after setup, save the widget id (or delete it if the user canceled the setup) in my custom data and use the id to show and update the widget
  • => For my case, this is working fine...

Question

How do I get a valid AppWidgetProviderInfo with a configure field != null so that I can use following:

Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
// appWidgetInfo.configure is null for appWidgetInfo received from mAppWidgetManager.getInstalledProviders()
// it is not if the appWidgetInfo is received via the AppWidgetManager.ACTION_APPWIDGET_PICK intent...
intent.setComponent(appWidgetInfo.configure);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
activity.startActivityForResult(intent, WIDGET_CONFIGURE_REQUEST_CODE);

Or is there an alternative approach to this?

I think I somehow must create a widget with the AppWidgetProviderInfo manually and then reget the info with mAppWidgetManager.getAppWidgetInfo(appWidgetId); and then I will have a filled configure field as this seems to happen if I use AppWidgetManager.ACTION_APPWIDGET_PICK intent, but I don't know I do this manually...

prom85
  • 16,896
  • 17
  • 122
  • 242

1 Answers1

3

I could solve the issue. The ACTION_APPWIDGET_PICK intent binds the widget to the id, so this must be done manually in my case:

private static void configureWidgetManually(AppCompatActivity activity, AppWidgetProviderInfo appWidgetInfo) {
    int appWidgetId = mAppWidgetHost.allocateAppWidgetId();

    boolean hasPermission = mAppWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId, appWidgetInfo.provider);
    if (!hasPermission) {
         // this if part is untested, I never get into this part, but from my understanding it should work like this...
        Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND);
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, appWidgetInfo.provider);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER_PROFILE, appWidgetInfo.getProfile());
        }
        // Result of this can be handled the same way as the result of AppWidgetManager.ACTION_APPWIDGET_PICK, so we can even use the same request code...
        activity.startActivityForResult(intent, WIDGET_SELECTOR_REQUEST_CODE);
    } else {
        // Widget is bound, we can continue as if we would have used the `AppWidgetManager.ACTION_APPWIDGET_PICK` intent
        appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
        configureWidget(activity, appWidgetId, appWidgetInfo);
    }
}

private static void configureWidget(AppCompatActivity activity, int appWidgetId, AppWidgetProviderInfo appWidgetInfo) {

    if (appWidgetInfo.configure != null) {
        Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
        intent.setComponent(appWidgetInfo.configure);
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
        activity.startActivityForResult(intent, WIDGET_CONFIGURE_REQUEST_CODE);
    } else {
        // widget is configured, do whatever you want with the id...
    }
}
prom85
  • 16,896
  • 17
  • 122
  • 242