AppWidget перестал работать на нескольких устройствах - PullRequest
0 голосов
/ 06 января 2019

У меня есть приложение для Android, которое в основном является приложением для обнаружения дождя на юго-востоке Бразилии. С момента запуска он работал нормально, однако внезапно перестал работать на нескольких устройствах.

Приложение просто больше не реагирует на прикосновения. Он отлично работает на моем телефоне (Lenovo K6 с расширенной AOSP), но я получил сообщения от многих телефонов Motorola / Samsung, что виджет просто завис. Перезапуск устройства или переустановка приложения не решают проблему.

Поскольку я не могу воспроизвести проблему на своем телефоне или в эмуляторе, для меня стало головной болью найти источник проблемы. Важно отметить, что виджет перестал работать после того, как я изменил targetSdkVersion на 26, как это было запрошено Google в прошлом году. Я не знаю, связано ли это, но это произошло почти одновременно.

Я прилагаю ниже части моего класса виджетов, которые обрабатывают обновление и установку намерений для кнопок (я пропустил части с / * ... * /, так как код был бы слишком длинным и запутанным здесь) :

public class RadarWidget extends AppWidgetProvider {
    private static int noOfIntents = 4;

    /* ... */

    static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
        RadarWidget.updateAppWidget(context, appWidgetManager, appWidgetId, null, null, null, null);
    }

    static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bitmap overlay, Bitmap background, String dateTimeString, String title) {
        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.radar_widget);

        /* ... (read shared preferences) */

        views.setOnClickPendingIntent(R.id.radarwidget_syncbutton,
                getSyncPendingIntent(context, appWidgetId));
        views.setOnClickPendingIntent(R.id.radarwidget_gpsbutton,
                getToggleGPSPendingIntent(context, appWidgetId));
        views.setOnClickPendingIntent(R.id.radarwidget_rewbutton,
                getGoBackPendingIntent(context, appWidgetId));
        views.setOnClickPendingIntent(R.id.radarwidget_rewibutton,
                getGoBackPendingIntent(context, appWidgetId));
        views.setOnClickPendingIntent(R.id.radarwidget_ffbutton,
                getGoForwardPendingIntent(context, appWidgetId));
        views.setOnClickPendingIntent(R.id.radarwidget_ffibutton,
                getGoForwardPendingIntent(context, appWidgetId));

        /* ... (set texts, images, etc. on the widget) */

        appWidgetManager.updateAppWidget(appWidgetId, views);
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        /* If received intent is one of ours (for widget update), use our logic */
        if (intent.getAction().equals("com.comodo.weatherpal.ACTION_UPDATE_WIDGET")) {
            /* ... (get extras from intent) */

            AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);

            if (widgetId != -1) {
                /* ... (perform some logic according to received extras, update shared preferences) */

                RadarWidget.updateAppWidget(context, appWidgetManager, widgetId, null, null,
                        context.getString(R.string.radarwidget_loadinglabel), null);
            }
        }
        /* Received intent is not one of ours for widget updating, send it to super */
        else {
            super.onReceive(context, intent);
        }
    }

    static PendingIntent getSyncPendingIntent(Context context, int widgetId) {
        Intent intent = new Intent("com.comodo.weatherpal.ACTION_UPDATE_WIDGET");
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
        intent.putExtra("sync", true);
        return PendingIntent.getBroadcast(context, widgetId * noOfIntents, intent,
                PendingIntent.FLAG_UPDATE_CURRENT);
    }

    static PendingIntent getToggleGPSPendingIntent(Context context, int widgetId) {
        Intent intent = new Intent("com.comodo.weatherpal.ACTION_UPDATE_WIDGET");
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
        intent.putExtra("toggleGPS", true);
        return PendingIntent.getBroadcast(context, widgetId * noOfIntents + 1, intent,
                PendingIntent.FLAG_UPDATE_CURRENT);
    }

    static PendingIntent getGoBackPendingIntent(Context context, int widgetId) {
        Intent intent = new Intent("com.comodo.weatherpal.ACTION_UPDATE_WIDGET");
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
        intent.putExtra("goBack", true);
        return PendingIntent.getBroadcast(context, widgetId * noOfIntents + 2, intent,
                PendingIntent.FLAG_UPDATE_CURRENT);
    }

    static PendingIntent getGoForwardPendingIntent(Context context, int widgetId) {
        Intent intent = new Intent("com.comodo.weatherpal.ACTION_UPDATE_WIDGET");
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
        intent.putExtra("goForward", true);
        return PendingIntent.getBroadcast(context, widgetId * noOfIntents + 3, intent,
                PendingIntent.FLAG_UPDATE_CURRENT);
    }
}

Я разговаривал с одним из затронутых пользователей, я создал специальную тестовую версию, в которой я проверял, возникло ли какое-либо исключение в методе updateAppWidget, но, очевидно, ничего не поднялось.

Большое спасибо за помощь!

1 Ответ

0 голосов
/ 06 января 2019

Похоже, вы, вероятно, не тестируете устройство, работающее под управлением Oreo.

В Oreo введены строгие ограничения для неявных широковещательных рассылок (в Intent не задан ни один компонент или пакет). Если у вас есть устройство под управлением Oreo, а ваше приложение ориентировано на Oreo, вы достигнете этих пределов. Если ваше приложение ориентировано на Nougat и / или вы используете Nougat или ниже, вы их не заметите.

Вам должно быть довольно легко обойти это.

Когда вы создаете свои обернутые намерения, используйте вместо этого:

Intent intent = new Intent(context, RadarWidget.class);
intent.setAction("com.comodo.weatherpal.ACTION_UPDATE_WIDGET");

Остальная часть кода может остаться прежней. Это просто гарантирует, что Intent явно нацелен на ваш класс RadarWidget, поэтому Android не будет блокировать его выполнение.

...