Intereting Posts
Как создать кнопку изображения в Android? Исключение android.content.res.Resources $ NotFoundException: файл res / drawable / my.xml из идентификатора ресурса с ресурсом Приложение Android не загружается на некоторых телефонах в PathClassLoader Сгенерированный класс Dagger2 неожиданно отсутствует в Android Studio Как сказать ProGuard обфускации методов и имен классов? Как использовать изображение (сохраненное изображение устройства) с текстом на TextView Android? Рисовать линию через текст в текстовом виде Android: как создать представление, чтобы заполнить свободное пространство? RequestFocus не работает должным образом для EditText Использовать прогресс Диалог в нижнем колонтитуле Как я могу заставить GoogleApiClient запрашивать пользовательский интерфейс выбора учетной записи каждый раз, когда я вызываю соединение? Странные проблемы заикания, от которых я не могу избавиться (включая полный источник) OnPrepareActionMode не вызывается при создании ActionMode Какая польза от новой String в toArray (новая String ); Поддержка Android Multi-Window: обнаружение, отображается ли строка состояния?

Android: Как заставить обновление всех виджетов определенного типа

Я видел много вопросов в этом направлении, и я продолжаю видеть один и тот же ответ снова и снова. Я не хочу иметь Сервис для всех видов виджетов, которые имеет мое приложение, особенно потому, что у моего приложения уже есть 2 постоянных сервиса.

В частности, если одна из моих существующих служб увидела, что данные изменились, я хочу обновить свои виджеты. Выполнение этого по таймеру раздражает, так как это может быть дни между обновлениями или может быть несколько в течение одного часа. Я хочу, чтобы мои виджеты ВСЕГДА отображали актуальную информацию.

Дизайн виджета Android, похоже, работает на том основании, что ваш виджет извлекает информацию, когда он этого хочет, я думаю, что существует много разумных сценариев, в которых активность может потребовать передачи данных в виджет.

Прочтите приведенный ниже ответ, как я разработал, как это сделать. Насколько я вижу, нет никаких побочных эффектов, если это сделано правильно.

Solutions Collecting From Web of "Android: Как заставить обновление всех виджетов определенного типа"

Чтобы заставить наши виджеты для конкретного поставщика виджета обновляться, нам нужно будет сделать следующее:

  • Настройте наш провайдер, чтобы получить специализированную трансляцию
  • Отправьте специализированную трансляцию с помощью:
    1. Все текущие идентификаторы виджетов, связанные с поставщиком
    2. Данные для отправки
    3. Ключи, на которые реагирует только наш поставщик (Важно!)
  • Получение нашего виджета для обновления по клику (без сервиса!)

Шаг 1 – Настройте наш AppWidgetProvider

Я не буду подробно описывать создание файла xml или изменения в Android Manifest – если вы не знаете, как правильно создать виджет, тогда есть много учебников, которые вы должны прочитать в первую очередь.

Вот пример класса AppWidgetProvider :

 public class MyWidgetProvider extends AppWidgetProvider { public static final String WIDGET_IDS_KEY ="mywidgetproviderwidgetids"; public static final String WIDGET_DATA_KEY ="mywidgetproviderwidgetdata"; } @Override public void onReceive(Context context, Intent intent) { if (intent.hasExtra(WIDGET_IDS_KEY)) { int[] ids = intent.getExtras().getIntArray(WIDGET_IDS_KEY); if (intent.hasExtra(WIDGET_DATA_KEY)) { Object data = intent.getExtras().getParcelable(WIDGET_DATA_KEY); this.update(context, AppWidgetManager.getInstance(context), ids, data); } else { this.onUpdate(context, AppWidgetManager.getInstance(context), ids); } } else super.onReceive(context, intent); } @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { update(context, appWidgetManager, appWidgetIds, null); } //This is where we do the actual updating public void update(Context context, AppWidgetmanager manager, int[] ids, Object data) { //data will contain some predetermined data, but it may be null for (int widgetId : ids) { . . //Update Widget here . . manager.updateAppWidget(widgetId, remoteViews); } } 

Шаг 2 – Отправка трансляции

Здесь мы можем создать статический метод, который позволит обновить наши виджеты. Важно, что мы используем наши собственные ключи с действием обновления виджета, если мы используем AppWidgetmanager.EXTRA_WIDGET_IDS, мы не только сломаем собственный виджет, но и другие.

 public static void updateMyWidgets(Context context, Parcelable data) { AppWidgetManager man = AppWidgetManager.getInstance(context); int[] ids = man.getAppWidgetIds( new ComponentName(context,MyWidgetProvider.class)); Intent updateIntent = new Intent(); updateIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE); updateIntent.putExtra(MyWidgetProvider.WIDGET_ID_KEY, ids); updateIntent.putExtra(MyWidgetProvider.WIDGET_DATA_KEY, data); context.sendBroadcast(updateIntent); } 

Если использовать этот метод с несколькими провайдерами, убедитесь, что они используют разные ключи. В противном случае вы можете найти виджет для виджета с обновлением кода b, и это может иметь некоторые странные последствия.

Шаг 3 – обновление по клику

Еще одна приятная вещь – заставить наш виджет обновлять магически каждый раз, когда он нажимается. Добавьте следующий код в метод обновления, чтобы добиться этого:

 RemoteViews views = new RemoteViews(context.getPackageName(),R.layout.mywidget_layout); Intent updateIntent = new Intent(); updateIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE); updateIntent.putExtra(myWidgetProvider.WIDGET_IDS_KEY, ids); PendingIntent pendingIntent = PendingIntent.getBroadcast( context, 0, updateIntent, PendingIntent.FLAG_UPDATE_CURRENT); views.setOnClickPendingIntent(R.id.view_container, pendingIntent); 

Этот код вызовет вызов метода onUpdate всякий раз, когда на него нажимается виджет.

Заметки

  • Любой вызов updateWidgets () приведет к обновлению всех экземпляров нашего виджета.
  • Нажатие на виджет приведет к обновлению всех экземпляров нашего виджета
  • НЕТ ТРЕБУЕТСЯ СЕРВИС
  • Конечно, будьте осторожны, чтобы не обновлять часто – обновления виджета используют заряд батареи.
  • Имейте в виду, что широковещательная передача принимается всеми поставщиками виджетов и ее специальными ключами, которые гарантируют, что на самом деле обновляются только наши виджеты.

Извините за OP за поздний ответ, но для кого-либо еще вы можете использовать такой способ, чтобы обновить все виджеты вашего приложения (макет и класс):

 public static void updateAllWidgets(final Context context, final int layoutResourceId, final Class< ? extends AppWidgetProvider> appWidgetClass) { RemoteViews remoteViews = new RemoteViews(context.getPackageName(), layoutResourceId); AppWidgetManager manager = AppWidgetManager.getInstance(context); final int[] appWidgetIds = manager.getAppWidgetIds(new ComponentName(context, appWidgetClass)); for (int i = 0; i < appWidgetIds.length; ++i) { manager.updateAppWidget(appWidgetIds[i], remoteViews); } } 

Что это значит, он создает RemoteViews для вашего макета, а затем AppWidgetManager и находит все виджеты приложений для предоставленного вами класса, выполняет итерации над ними и обновляет их.

Каждый раз, когда вы имеете дело с типами, довольно просто работать со статикой. И, если вы хотите, чтобы определенные вещи происходили на основе «триггера», я всегда рекомендовал программирование на основе событий … Намерения по сути являются «событием» по умолчанию в Android (для передачи данных в вашем мероприятии убедитесь, что объект реализует Интерфейс Parcelable).

Существует много примеров этих концепций на различных форумах и документации SDK.