How to declare a receiver for a widget to handle your own broadcast along with system broadcast

1.3k Views Asked by At

Suppose I want to define a receiver for my own widget and I want it to handle my own broadcast org.test.mywidget.MY_ACTION along with the APPWIDGET_xxx system broadcasts, what is the correct way to define it, if I want it to handle my own broadcast only if it is sent from the same app package? I tried the following XML code but in this way the APPWIDGET_DELETE action was no more delivered to the widget provider:

    <receiver
        android:name="MyWidgetProvider">
        <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>

The XML above has the problem I've mentioned (no DELETED events delivered) and it also does not seem good to me, since the receiver is redefined.. So I compacted everything as follows:

    <receiver
        android:name="MyWidgetProvider">
        <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>

This works, APPWIDGET_UPDATE, APPWIDGET_DELETE and my own broadcast are all delivered but now I have a question: are now other apps able to deliver a broadcast intent with the action org.test.mywidget.FORCE_SMALL_WIDGET_UPDATE to my widget, since the android:exported value is set to true by default? Maybe I'm missing some basic concept related to this exported value, so I would be glad if some of you can make me understand everything better :)

1

There are 1 best solutions below

1
On

if I want it to handle my own broadcast only if it is sent from the same app package?

You do not need, or even want, an action string if it is all going to be within your own package. Just use the Intent constructor that takes a Java class object as the second parameter, and use that for sending broadcasts to be picked up by the receiver.

I tried the following XML code but in this way the APPWIDGET_DELETE action was no more delivered to the widget provider

That is because there is no <intent-filter> referencing that action string in your code.

are now other apps able to deliver a broadcast intent with the action org.test.mywidget.FORCE_SMALL_WIDGET_UPDATE to my widget, since the android:exported value is set to true by default?

Yes. Of course, third party apps can send APPWIDGET_UPDATE broadcasts, or even hack an Intent that identifies your component directly, and you will receive those as well.

I suspect that the right answer, in your case, is to simply implement a second BroadcastReceiver, one with no <intent-filter>, that handles operations that you solely want to be within your package. Or, if you do not need to use a PendingIntent for this BroadcastReceiver, consider LocalBroadcastManager from the Android Support package.