Intent.putExtra适用于EXTRA_APPWIDGET_IDS,但不适用于EXTRA_APPWIDGET_ID

时间:2017-12-02 16:25:08

标签: android android-intent android-appwidget

以下是 AppWidgetProvider 类相关部分的代码段。

public class LargeWidgetProvider extends AppWidgetProvider {

    @Override
    public void onEnabled(Context context) {
        ...
    }

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int... appWidgetIds) {
        super.onUpdate(context, appWidgetManager, appWidgetIds);
        Log.i("Trigger2" , "Large Widget");
        for (int appWidgetId : appWidgetIds) {
            RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
                    R.layout.widget_large);

            preLoadWeather(context , remoteViews);
            Intent intent = new Intent(context, LargeWidgetProvider.class);
            intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
            PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
                    0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
            remoteViews.setOnClickPendingIntent(R.id.widget_button_refresh, pendingIntent);

            Intent intentStartActivity = new Intent(context, WeatherActivity.class);
            PendingIntent pendingIntent2 = PendingIntent.getActivity(context, 0, intentStartActivity, 0);
            remoteViews.setOnClickPendingIntent(R.id.widget_root, pendingIntent2);

            appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
        }
        LargeWidgetService.enqueueWork(context , new Intent(context, LargeWidgetService.class));
    }

    @Override
    public void onDisabled(Context context) {
        ...
    }

    private void preLoadWeather(Context context, RemoteViews remoteViews) {
        ...
    }

    private String format(String rs) {
        ...
    }

    public void updateAppWidget(Context context , AppWidgetManager appWidgetManager , int appWidgetId , String city) {
        Log.i("Trigger2" , "Large Widget");
        AppWidgetManager widgetManager = AppWidgetManager.getInstance(context);
        ComponentName widgetComponent = new ComponentName(context, LargeWidgetProvider.class);
        int[] widgetIds = widgetManager.getAppWidgetIds(widgetComponent);
        RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
                R.layout.widget_large);

        preLoadWeather(context , remoteViews);
        Intent intent = new Intent(context, LargeWidgetProvider.class);
        intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, widgetIds);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
                0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        remoteViews.setOnClickPendingIntent(R.id.widget_button_refresh, pendingIntent);

        Intent intentStartActivity = new Intent(context, WeatherActivity.class);
        PendingIntent pendingIntent2 = PendingIntent.getActivity(context, 0, intentStartActivity, 0);
        remoteViews.setOnClickPendingIntent(R.id.widget_root, pendingIntent2);

        appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
        LargeWidgetService.enqueueWork(context , new Intent(context, LargeWidgetService.class));
    }
}

这是我的 LargeWidgetService

的代码
public class LargeWidgetService extends JobIntentService {

    private static final String TAG = "LargeWidgetService";

    public static void enqueueWork(Context context , Intent intent) {
        enqueueWork(context , LargeWidgetService.class, 0x01 , intent);
    }

    @Override
    protected void onHandleWork(@NonNull Intent intent) {
        ...

        AppWidgetManager widgetManager = AppWidgetManager.getInstance(this);
        ComponentName widgetComponent = new ComponentName(this, LargeWidgetProvider.class);
        int[] widgetIds = widgetManager.getAppWidgetIds(widgetComponent);

        for (int appWidgetId : widgetIds) {
            try {
                WeatherInfo weatherRaw = new Request(this).getItems(new WidgetPrefs(appWidgetId , this).getCity(), units);
                lwPrefs.saveWeather(weatherRaw);
                updateWidget(weatherRaw);
            } catch (IOException e) {
                ...
            }
        }
    }

    private void updateWidget(WeatherInfo weather) {
        AppWidgetManager widgetManager = AppWidgetManager.getInstance(this);
        ComponentName widgetComponent = new ComponentName(this, LargeWidgetProvider.class);

        int[] widgetIds = widgetManager.getAppWidgetIds(widgetComponent);
        for (int appWidgetId : widgetIds) {
            ...
            RemoteViews remoteViews = new RemoteViews(this.getPackageName(),
                    R.layout.widget_large);
            ...
            widgetManager.updateAppWidget(appWidgetId, remoteViews);
        }
    }
}

PS。仅当我将configActivity附加到窗口小部件的xml时,才会调用updateAppWidget()中的LargeWidgetProvider。该活动如下:

public class LargeWidgetConfigActivity extends AppCompatActivity {
    int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setResult(RESULT_CANCELED);
        findViewById(android.R.id.content).setBackgroundColor(ContextCompat.getColor(this , R.color.primary));

        final Context context = this;

        Intent intent = getIntent();
        Bundle extras = intent.getExtras();
        if (extras != null) {
            mAppWidgetId = extras.getInt(
                    AppWidgetManager.EXTRA_APPWIDGET_ID,
                    AppWidgetManager.INVALID_APPWIDGET_ID);
        }

        // If they gave us an intent without the widget id, just bail.
        if (mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
            finish();
        }

        new MaterialDialog.Builder(this)
                .title(getString(R.string.pref_delete_cities_title))
                .content(getString(R.string.pref_delete_cities_summary))
                .positiveText(getString(android.R.string.ok))
                .negativeText(getString(android.R.string.cancel))
                .items(new DBHelper(this).getCities())
                .itemsCallbackSingleChoice(0, new MaterialDialog.ListCallbackSingleChoice() {
                    @Override
                    public boolean onSelection(MaterialDialog dialog, View itemView, int which, CharSequence text) {
                        new WidgetPrefs(mAppWidgetId , context).setCity(text.toString());
                        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
                        new LargeWidgetProvider().updateAppWidget(context, appWidgetManager, mAppWidgetId , text.toString());

                        Intent resultValue = new Intent();
                        resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
                        setResult(RESULT_OK, resultValue);

                        finish();
                        return true;
                    }
                })
                .show();
    }
}
  1. 在for循环内的onUpdate()函数中,我有一行intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);。因此,每当我点击我的小部件中的R.id.widget_button_refresh时,它都会更新我的所有小部件(代码工作)。当我将该行更改为intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);时,刷新按钮停止工作。有关如何解决此问题的任何线索? (这与配置活动无关)

  2. 如果我使用LargeWidgetProvider' updateAppWidget()内的代码,该按钮将停止工作。当我评论该函数内的所有代码时,刷新按钮再次开始工作。关于如何解决这个问题的任何想法?

1 个答案:

答案 0 :(得分:2)

如果您查看AppWidgetProvider的源代码,您会注意到,当处理 ACTION_APPWIDGET_UPDATE 操作时,只有 EXTRA_APPWIDGET_IDS 会转到被检查。 EXTRA_APPWIDGET_ID仅用于ACTION_APPWIDGET_DELETED和ACTION_APPWIDGET_OPTIONS_CHANGED。

如果您更改了UpdateAppWidget(...)方法的这两行:

intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, widgetIds);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
              0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

为:

intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] {appWidgetId});
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
              appWidgetId, intent, PendingIntent.FLAG_UPDATE_CURRENT);

您将获得所需的结果,只更新相应的小部件而不是所有小部件。