我有一个监听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);

当状态更改时,我还接收到一个到appwidget的接收器的android.appwidget.action.APPWIDGET_UPDATE广播,导致appwidget在检测到连接丢失后再次更新,然后在返回连接时接收两次(一次是有意从我的networkstateceiver,然后再次从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状态,就像它第一次被添加一样。我也可以通过保存额外的状态(包括位图)来解决这个问题。不理想。
我可以让networkstateceiver一直监听,而不是启用/禁用,但这违背了android的建议,而且理由充分,因为这意味着不必要的广播。
其他想法?
编辑:进一步解释我目前的解决办法。
我不能忽略APPWIDGET_UPDATE广播,即使我使用警报触发我的更新。这是因为APPWIDGET_UPDATE还将我的小部件重置为其初始状态,就像它第一次添加到主屏幕一样。如果我有一个连接,我可以做两次更新,因为所有的信息都可以重新填充。我还必须做我自己的更新,因为这个bug似乎是设备特定的,不受影响的设备仍然需要更新。
在没有连接的情况下,我会从先前保存的状态恢复小部件。这意味着每次我成功更新时,我也会将所有内容保存到sharedpreferences中,以便在Internet无法正确地重新填充数据时,在这些“强制更新”中的一个下恢复。
在我的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()
}

最佳答案

所以,如果我理解正确的话,有两件事发生了:
当启用网络状态更改通知时,您将获得到您的ACTION_APPWIDGET_UPDATE的额外AppWidgetProvider广播。
虽然这并不像人们所期望的那样(尽管我可以想象当网络状态改变时,小部件会想更新自己的编码思想),但它并不在android系统定义的行为之外,因此我们的代码需要对任意ACTION_WIDGET_UPDATE调用具有健壮性。跟踪appwidgetid列表和列表中每个小部件的最新状态是识别新小部件和立即需要更新的常用方法,同时将其他更新留给计时器机制。
正如你所说:即使更新什么也不做,问题仍然会发生。
如果您的onUpdate不起作用,则这意味着重新初始化与ACTION_WIDGET_UPDATE无关。不知怎的,在某个地方,当你不希望它初始化时,你的代码被调用。现在,这是一个痛苦,特别是如果没有代码的原因,这应该是这样的。然而,我和其他人都经历过这种情况,所以我要指出你们两个:
我的帮助列表:Service being re-Created by AlarmManager
关于意外启动服务的简短讨论和解决方案(在服务管理小部件的情况下,这通常意味着它们被重新初始化):Android service onCreate is called multiple times without calling onDestroy
当我自己面对这个问题时,我花了很多时间在我的代码中放置日志语句,以查看什么时候调用了我的代码的哪些部分,很明显,系统是出于没有定义的原因重新启动我的服务的,但这是按照这两个链接中的描述解决的。如果我必须选择一件我认为是关键的事情,那就是在一个与其他活动(包括AppWidgetProvider)不同的进程中运行服务。

关于android - 启用/禁用接收器(CONNECTIVITY_CHANGE)会导致APPWIDGET_UPDATE广播,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14614284/

10-13 04:18