3

我有一个接收器正在监听,android.net.conn.CONNECTIVITY_CHANGE以便在连接恢复时更新我的​​ appwidget。这很好用,除非我通过以下方式启用或禁用接收器时出现一些奇怪的行为:

ComponentName receiver = new ComponentName(this, NetworkStateReceiver.class);
PackageManager pm = getPackageManager();
pm.setComponentEnabledSetting(receiver, PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
        PackageManager.DONT_KILL_APP);

当状态改变时,我还会收到一个android.appwidget.action.APPWIDGET_UPDATE广播到我的 appwidget 的接收器,导致我的 appwidget 在检测到连接丢失后再次更新,然后在返回连接时两次(一次是有意地从我的 NetworkStateReceiver,然后再次从APPWIDGET_UPDATE广播)。

此外,这似乎只发生在我的 4.04 设备上,而不是我的 2.1 设备上。

NetworkStateReceiver 和 AppWidgetProvider 的清单

    <receiver
        android:name=".AppWidgetProvider"
        android:label="@string/widget_name" >
        <intent-filter>
            <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
        </intent-filter>

        <meta-data
            android:name="android.appwidget.provider"
            android:resource="@xml/appwidget" />
    </receiver>
    <receiver 
        android:name=".NetworkStateReceiver" 
        android:enabled="false">
        <intent-filter>
            <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
        </intent-filter>
    </receiver>

我尝试了几种方法来解决这个问题,但没有一个是非常好的解决方案。

APPWIDGET_UPDATE我可以忽略广播中的任何更新。实际上,我已经这样做了,因为我的所有 appwidget 更新都是在首次创建时通过警报管理器或配置活动通过服务进行的。尽管出于某些原因(并且可能表明正在发生的事情),APPWIDGET_UPDATE广播还导致我的远程视图恢复到其 XML 状态,就像它第一次添加一样。我也可以通过保存额外的状态(包括位图)来解决这个问题。不理想。

我可以让 NetworkStateReceiver 一直收听而不是启用/禁用,但这违背了 Android 的建议,并且有充分的理由,因为这意味着不必要的广播。

其他想法?

编辑:进一步解释我当前的解决方法。

APPWIDGET_UPDATE即使我使用警报来触发我的更新,我也不能忽略广播。这是因为它APPWIDGET_UPDATE还将我的小部件重置为其初始状态,就像它第一次添加到主屏幕一样。在我有连接的情况下,我可以进行双重更新,因为所有信息都可以重新填充。我还必须自己进行更新,因为该错误似乎特定于设备且未受影响的设备仍需要更新。

在我没有连接的情况下,我会从之前保存的状态恢复小部件。这意味着每次我进行成功更新时,我也会将所有内容保存到 SharedPreferences 中,以便当互联网无法正确重新填充数据时,它可以在这些“强制更新”之一下恢复。

在我的AppWidgetProvider我做(简化):

Intent intent = new Intent(context, WidgetUpdateService.class);
intent.putExtra("loadFromSaved", true);   // this will be false when coming from AlarmManager
context.startService(intent);

WidgetUpdateService.onStartCommand() (也简化了):

if (intent.getExtras().getBoolean("loadFromSaved") {
    widgetLoader.loadFromSavedData();
} else {
    widgetLoader.load()
}
4

1 回答 1

0

所以,如果我理解正确的话,有两件不同的事情正在发生:

  1. 启用网络状态更改通知ACTION_APPWIDGET_UPDATE后,您的AppWidgetProvider.

    虽然这并不像人们所期望的那样(尽管我可以想象一种编码思想,即当网络状态发生变化时,小部件会想要更新自己),但它并不超出 android 系统的定义行为,因此我们的代码需要对任意ACTION_WIDGET_UPDATE调用具有鲁棒性。跟踪 appWidgetId 列表和该列表中每个小部件的最新状态是识别新小部件和立即需要更新的常用方法,同时将其他更新留给计时器机制。

  2. 正如你所说:即使更新什么也没做,问题仍然存在。

    如果您onUpdate什么都不做,那么这意味着重新初始化与ACTION_WIDGET_UPDATE. 不知何故,当您不希望它调用时,您的初始化代码会被调用。现在,这很痛苦,特别是如果没有代码原因应该如此。但是,我和其他人都经历过这种情况,所以我指出你两个:

当我自己遇到这个问题时,我花了很多时间将 Log 语句放入我的代码中,以查看我的代码的哪些部分何时被调用,并且很明显系统正在重新启动我的服务,但没有明确的原因,但这是如这两个链接中所述解决。如果我必须选择一件我认为是关键的事情,那就是在与其他活动(包括AppWidgetProvider)分开的进程中运行服务。

于 2013-04-14T20:07:48.473 回答