Turning on / off the receiver (CONNECTIVITY_CHANGE) causes APPWIDGET_UPDATE to be sent

I have a receiver listening android.net.conn.CONNECTIVITY_CHANGE

to update its appwidget when the connection is reestablished. This works great, but I get some weird behavior when I enable or disable my receiver via:

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

      

When the state is changed, I also get a broadcast android.appwidget.action.APPWIDGET_UPDATE

to my appwidget receiver, causing my appwidget to update again after detecting a lost connection, and then twice when the connection returns (once intentionally from my NetworkStateReceiver and then again from the APPWIDGET_UPDATE

broadcast).

Also, it only seems to be on my 4.04 device and not on my 2.1 device.

Manifest for NetworkStateReceiver and 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>

      

I've tried several ways to get around this, but none of them is a very good solution.

I can ignore any update from the broadcast APPWIDGET_UPDATE

. In fact, I have been doing this since the update of my appwidget is done via the service via the alert manager or config activity on first creation. For some reason (and perhaps an indication of what's going on), the broadcast APPWIDGET_UPDATE

also causes my remote views to fall back to their XML state, since it was added the first time. Perhaps I could work around this by keeping an extra state that would include bitmaps. Not ideal.

I could constantly listen to the NetworkStateReceiver rather than enable / disable, but this is against Android guidelines and for good reasons as it means unnecessary broadcasts.

Any other ideas?

EDIT . Further explanation of my current workaround.

I cannot ignore the broadcast APPWIDGET_UPDATE

even if I use alarms to trigger my updates. This is because it APPWIDGET_UPDATE

also resets my widget to its original state since it was first added to the home screen. In cases where I have a connection, I can do double updates because all information can be re-populated. I also still have to do my own update as the bug seems to be device specific and unprotected devices still need to be updated.

In cases where I have no connectivity, I then restore the widget from a previously saved state. This means that every time I do a successful update, I also save everything to SharedPreferences so that it can be restored under one of these "forced updates" when the internet is not available to properly repopulate the data.

In mine, AppWidgetProvider

I do (simplified):

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

      

WidgetUpdateService.onStartCommand () (also simplified):

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

      

+3


source to share


1 answer


So, if I understand correctly, two different things are happening:

  • When network status change notification is enabled, you get additional ACTION_APPWIDGET_UPDATE

    broadcasts to your AppWidgetProvider

    .

    While this is not what one would expect (although I can imagine the coded thinking that the widgets would like to update when the network state changes), it is not outside of the specific behavior of the Android system and therefore our code must be robust for arbitrary calls ACTION_WIDGET_UPDATE

    . Tracking the appWidgetId list and the last state of each widget on that list is a common way of identifying new widgets and instantly needed updates while leaving another update in the timer mechanisms.

  • As you put it: even if the update does nothing, the problem still occurs.

    If yours onUpdate

    doesn't do anything, it means reinitialization has nothing to do with ACTION_WIDGET_UPDATE

    . Somewhere, somehow, your initialization code gets called when you don't expect it. Now this is a pain, especially if there is no reason for the code, it should be like this. However, I and others have experienced this, so I point you two:



When I ran into the problem myself, I spent a lot of time injecting code into my code to find out which parts of my code were called when it became clear that the system was restarting my service for no specific reason, but what is it was solved as described in these two links. If I had to pick one thing that I thought was key, it would execute the service in a separate process for other activities (including AppWidgetProvider

).

0


source







All Articles