AppWidget 在多个设备上停止工作

AppWidget stopped working in several devices

我有一个 android 应用程序,它基本上是一个用于巴西东南部降雨检测的应用程序小部件。自推出以来一直运行良好,但突然在多个设备上停止运行。

appwidget 不再响应任何触摸。它在我的 phone(扩展了 AOSP 的 Lenovo K6)上运行良好,但我收到许多 Motorola/Samsung phone 的报告,该小部件只是冻结了。重启设备或重新安装应用程序均未解决。

由于我无法在我的 phone 或模拟器中重现该问题,因此找到问题源让我很头疼。一件重要的事情是,在我将 targetSdkVersion 更改为 26 后,小部件停止工作,这是去年 Google 要求的。不知道有没有关系,差不多是同时发生的

我在下面附加了我的小部件 class 的部分,它处理更新和设置按钮的意图(我省略了带有 /* ... */ 的部分,因为代码将是此处太冗长且令人困惑):

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 方法中是否引发了任何异常,但显然没有引发任何异常。

非常感谢您的帮助!

听起来您可能没有使用 运行 Oreo 设备进行测试。

Oreo 引入了 severe limitations 隐式广播(未在 Intent 上设置组件或包)。如果您有设备 运行 Oreo,并且您的应用以 Oreo 为目标,您将达到这些限制。如果您的应用以 Nougat and/or 为目标,那么您 运行 Nougat 或更低版本,您将不会注意到它们。

你应该很容易解决这个问题。

当您构建包装的 Intent 时,请改用它:

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

其余代码可以保持不变。这只是确保 Intent 明确针对您的 RadarWidget class,因此 Android 不会阻止它执行。