Appwidget зависает и отказывается обновлять больше: игнорирует updateAppWidget

Итак, у меня есть виджет приложения, который освежает красиво, загружая новую растровую карту в ImageView регулярно, как часы. Затем, в какой-то момент и тихо, он перестанет обновляться. Я могу сказать из журнала и из активности на сервере, который запрашивает мой код, что на самом деле все еще продолжает регулярно запускаться (через трансляции, пойманные с помощью onReceive(), и делает свои вещи, как ожидалось. Единственное, что не является Дело в том, что содержимое виджета не обновляется.

Итак, в коде, который выполняется при запуске виджета, я создаю новый RemoteViews и добавляю к нему материал, включая загрузку нового растрового изображения через remoteViews.setImageViewBitmap(imageViewID, bmp), а затем, наконец, вызывающий appWidgetManager.updateAppWidget(appWidgetId, remoteViews) для обновления содержимого виджета, Хорошо работает... пока он не перестанет работать.

Я не уверен, какой код для публикации, потому что вещь работает всего лишь 99% времени, но иногда updateAppWidget() перестает работать, без видимых причин. Кажется, это проблема системы, а не ошибка в моем коде, но я мог ошибаться.

Единственное, что, возможно, подсказывает это, когда происходят изменения в связности, например. переход от сигнала к Wi-Fi, возможно, частые такие изменения. В этих ситуациях, похоже, происходит больше.

И как только виджет замерзает, единственное, что размораживает его, - это перезапустить устройство. Без перезапуска даже удаление виджета и добавление нового не работает. Фактически, добавление нового приводит к мертвому виджету, который даже не реагирует на щелчок, чтобы открыть операцию конфигурации, по-видимому, потому что remoteViews.setOnClickPendingIntent(R.id.widget, configPendingIntent) игнорируется, как и все остальное в RemoteViews, я тщательно конструирую и отправляю на appWidgetManager.updateAppWidget().

Это похоже на то, что описано многими другими:

https://code.google.com/p/android/issues/detail?id=28216

и пока, похоже, не известно никакого излечения. Сообщение в https://code.google.com/p/android/issues/detail?id=28216#c56, казалось, давало некоторые обещания, но я пробовал звонить AppWidgetHost.startListening() в разных местах, в том числе через регулярные промежутки времени через повторяя сигнал тревоги, чтобы увидеть, могу ли я запускать виджет, но ничего не работает.

И другие пользователи (а не разработчики) тоже видят эту проблему: http://androidforums.com/threads/clock-widget-keeps-freezing-please-help.530333/

Любые идеи? Это медленно сводит меня с ума!

Ответ 1

remoteViews.setImageViewBitmap(imageViewID, bmp)

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

Вместо этого вы должны использовать setImageViewUri https://developer.android.com/reference/android/widget/RemoteViews.html#setImageViewUri(int,%20android.net.Uri). Это немного больше работы, потому что вам нужно сохранить растровое изображение, а затем отправить на него пусковую установку uri, хотя в настоящее время все или почти все пусковые установки имеют READ_EXTERNAL_STORAGE, поэтому может возникнуть проблема с tc uri для внешнего хранилища, вы не должны полагаться на что в будущем и вместо этого следует использовать FileProvider https://developer.android.com/reference/android/support/v4/content/FileProvider.html