使用已知的AppWidgetProviderInfo创建小部件

时间:2017-10-06 08:27:47

标签: android widget appwidgetprovider

我没有向用户显示窗口小部件提供程序列表,而是让他选择一个然后配置窗口小部件,我手动加载所有窗口小部件提供程序,让用户将这些窗口小部件拖放到我的应用程序中。 一旦用户删除了这样的图标,我就想创建和配置这个小部件。我该怎么做?

带注释的代码

// 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

正常方法(对我的用例不重要,但通常描述它是如何工作的)

  • 创建窗口小部件ID,然后使用AppWidgetManager.ACTION_APPWIDGET_PICK意图让用户选择窗口小部件
  • 选择后,将数据传递给AppWidgetManager.ACTION_APPWIDGET_CONFIGURE意图并使用intent.setComponent(appWidgetInfo.configure);
  • 安装完成后,在我的自定义数据中保存小部件ID(如果用户取消了设置,则删除它)并使用id显示和更新小部件
  • =&GT;就我而言,这很好......

问题

如何使用configure field获取有效的AppWidgetProviderInfo!= null,以便我可以使用以下内容:

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

或者有替代方法吗?

我想我必须以某种方式手动创建一个包含AppWidgetProviderInfo的小部件,然后使用mAppWidgetManager.getAppWidgetInfo(appWidgetId);重新获取该信息,然后我会有一个填充的configure字段,因为这似乎发生了使用AppWidgetManager.ACTION_APPWIDGET_PICK意图,但我不知道我是手动执行此操作......

1 个答案:

答案 0 :(得分:2)

我可以解决这个问题。 ACTION_APPWIDGET_PICK意图将小部件绑定到id,因此必须在我的情况下手动完成:

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...
    }
}