Search code examples
androidandroid-widgetandroid-launcher

AppWidgetManager.ACTION_APPWIDGET_BIND always returns Activity.RESULT_CANCELED


I am building a custom launcher. I have followed the steps mentioned in the Android documentation for hosting App Widgets as well as browsing the default Launcher source code. But when I call startActivityForResult using the intent action as AppWidgetManager.ACTION_APPWIDGET_BIND, it is always returning Activity.RESULT_CANCELED even though the user is accepting from the dialog prompt shown on the UI.

Here's the code snippet

    appWidgetManager = AppWidgetManager.getInstance(this);
    appWidgetHost = new AppWidgetHost(this, 7772);
    int appWidgetId = appWidgetHost.allocateAppWidgetId();
    Intent pickIntent = new Intent(AppWidgetManager.ACTION_APPWIDGET_PICK);
    pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
    startActivityForResult(pickIntent, REQUEST_PICK);

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        Log.d(TAG, " onActivityResult " + requestCode + " res " + resultCode);
        if (requestCode == REQUEST_PICK && resultCode == Activity.RESULT_OK)
        {
            int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
            AppWidgetProviderInfo info = appWidgetManager.getAppWidgetInfo(appWidgetId);

            boolean hasPermission = appWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId, info.provider);
            if (!hasPermission)
            {
                Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND);
                intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
                intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, info.provider);
                startActivityForResult(intent, REQUEST_BIND);
            }

        }else if (requestCode == REQUEST_BIND) {
            // Here the resultCode is always returning Activity.RESULT_CANCELED
        }
    }

Can someone please help me out as to what I may be doing incorrectly?

I have also added android:name="android.permission.BIND_APPWIDGET" in the Manifest file.

And finally, through the Android logs, I can see errors like

1567-1940/system_process E/AppWidgetServiceImpl: Widget id 34 already bound to: ProviderId{user:0, app:10025, cmp:ComponentInfo{com.android.deskclock/com.android.alarmclock.AnalogAppWidgetProvider}}

Solution

  • Found the problem. Answering it here in case anyone else faces the same issue.

    If you use the AppWidgetManager.ACTION_APPWIDGET_PICK inten to pick the intent from the chooser displayed by the Android OS, there is no need to bind as the framework automatically binds the widget.

    If you implement a custom chooser (for example, something which shows the preview images of widgets which is implemented in lots of custom launchers), then binding is necessary.