33

I'm implementing a widget and I'm facing the following problems:

1) onUpdate is called when I add the widget to the home screen, even if I specified a Configuration Activity. As soon as I add it to the home screen, the APPWIDGET_ENABLED broadcast is sent, followed by the APPWIDGET_UPDATE and then the configuration activity is launched.. Is this a bug? How should I understand in the onUpdate method that is being invoked before the configuration activity has returned? I can do it through a shared preference value, but I'd like it to behave as written on the developer guide, i.e. the onUpdate method should not be called.

2) onUpdate is not called every updatePeriodMillis seconds, which have been set to 10000, i.e. 10 seconds for testing purposes.. Did I miss something in the receiver declaration within the Manifest file? I keep receiving the Lint warning Exported receiver does not require permission but I think this is a Lint issue and not my fault. EDIT: I've just found this within the reference docs: Note: Updates requested with updatePeriodMillis will not be delivered more than once every 30 minutes. So it is correct that the widget is not updated how often I'd specified and I've changed the time to 1800000 milliseconds.

3) I want to deliver my own broadcast action to the widget provider, is it correct to add another receiver block in the Manifest targeting the same provider class or should I add only another intent action within the intent-filter that contains the APPWIDGET_UPDATE action? BTW, I've commented my second receiver block and it is not the cause of the problems above. I created another receiver block because I wanted to declare it as not exported, in order to let the intent-filter action be triggered only by my app code and not anyone else.

AndroidManifest.xml

    <receiver android:name="MyWidgetProvider" 
        android:exported="true">
        <intent-filter>
            <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
        </intent-filter>

        <meta-data
            android:name="android.appwidget.provider"
            android:resource="@xml/my_widget_info" />
    </receiver>
    <receiver android:name="MyWidgetProvider" 
        android:exported="false">
        <intent-filter>
            <action android:name="org.test.mywidget.FORCE_SMALL_WIDGET_UPDATE" />
        </intent-filter>
    </receiver>

my_widget_info.xml

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="294dp"
    android:minHeight="110dp"
    android:updatePeriodMillis="1800000"
    android:initialLayout="@layout/my_widget_layout"
    android:configure="org.test.mywidget.MyWidgetConfiguration" 
    android:resizeMode="none">
</appwidget-provider>
Gianni Costanzi
  • 5,804
  • 11
  • 43
  • 70

1 Answers1

0

Providing an answer after digging into the source code:

1) This is expected behavior see here

This method is also called when the user adds the App Widget

2) Seems you have found your own answer. For others looking for the docs go here

Note: Updates requested with updatePeriodMillis will not be delivered more than once every 30 minutes

3) Since the AppWidgetProvider extends BroadcastReceiver but is not declared final you can add the action from your second receiver

<receiver android:name="MyWidgetProvider" 
        android:exported="true">
        <intent-filter>
            <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            <action android:name="org.test.mywidget.FORCE_SMALL_WIDGET_UPDATE" />
        </intent-filter>

        <meta-data
            android:name="android.appwidget.provider"
            android:resource="@xml/my_widget_info" />
    </receiver>

then you can override onReceive in your MyWidgetProvider class and if the action is your custom action handle it, otherwise call to the super.onRecieve(Context context, Intent intent) like so:

@Override
public void onReceive(Context context, Intent intent) {
    if(intent.getAction()
         .equals("org.test.mywidget.FORCE_SMALL_WIDGET_UPDATE")){
        // handle your action
    } else {
        super.onRecieve(context, intent);
    }
}

as per the Guide:

AppWidgetProvider is just a convenience class. If you would like to receive the App Widget broadcasts directly, you can implement your own BroadcastReceiver or override the onReceive(Context, Intent) callback.

One thing to note with this, the update to the remote view will only be called at the updatePeriodMillis, regardless of you adding your own action to the Intent for the provider to handle.

Good Luck and Happy Coding!

kandroidj
  • 12,901
  • 5
  • 56
  • 69
  • 5
    1) Yes, but next sentence tell us `However, if you have declared a configuration Activity, ` **this method is not called** `when the user adds the App Widget, but is called for the subsequent updates ` – Deni Erdyneev Apr 28 '18 at 04:31