bitanon
bitanon

Reputation: 135

Why is my PendingIntent not broadcasting/receiving from Android widget setOnClickPendingIntent?

AppWidget.kt:

override fun onEnabled(context: Context) {
    // register price and widget button update receivers
    val filters = IntentFilter()
    filters.addAction(BROADCAST_PRICE_UPDATED)
    filters.addAction(BROADCAST_WIDGET_UPDATE_BUTTON_CLICK)
    LocalBroadcastManager.getInstance(context.applicationContext).registerReceiver(br, filters)
}

override fun onDisabled(context: Context) {
    // unregister price and widget button update receivers
    LocalBroadcastManager.getInstance(context.applicationContext).unregisterReceiver(br)
}

    private val br = object : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) { ... }

Notes: local broadcast receiver receives all other registered broadcasts, except from piWidgetUpdateButtonClicked. Using LocalBroadcastManager is the only way I've been able to send/receive broadcasts, as apparently using global broadcast system filters out broadcasts from my app's package?

internal fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int) {

// Construct the RemoteViews object
val views = RemoteViews(context.packageName, R.layout.app_widget)

// Create an Intent to launch MainActivity when widget background touched
val piLaunchMainActiv: PendingIntent = PendingIntent.getActivity(context,0,
    Intent(context.applicationContext, MainActivity::class.java),
    PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
    )
views.setOnClickPendingIntent(R.id.widget_background_layout, piLaunchMainActiv)

// create intent to update widget when button clicked TODO this not working
val piWidgetUpdateButtonClicked =
    PendingIntent.getBroadcast(context, appWidgetId,
        Intent(BROADCAST_WIDGET_UPDATE_BUTTON_CLICK), PendingIntent.FLAG_UPDATE_CURRENT
                or PendingIntent.FLAG_IMMUTABLE
    )
views.setOnClickPendingIntent(R.id.widget_update_button, piWidgetUpdateButtonClicked)

Notes: *piLauchMainActiv *pending intent works fine, but piWidgetUpdateButtonClicked does nothing. I've tried using context.applicationContext, also does nothing. Also I've tried explicitly setting receiving class: Intent.setClass(context, AppWidget::class.java), nothing.

Apparently, latest Google Android releases want you to register broadcast receivers programmatically, as I've done above, rather than in the manifest, which I've tried too, but also doesn't work:

AndroidManifest.xml:

        <receiver
        android:name=".AppWidget"
        android:exported="false">
        <intent-filter>
            <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
        </intent-filter>
        <intent-filter>
            <action android:name="org.bitanon.bitcointicker.BROADCAST_PRICE_UPDATED" />
        </intent-filter>
        <intent-filter>
            <action android:name="org.bitanon.bitcointicker.BROADCAST_WIDGET_UPDATE_BUTTON_CLICK" />
        </intent-filter>

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

After days and days of reading through other related posts on stackoverflow, nothing has helped. I'm completely stumped, please send help!

Upvotes: 1

Views: 411

Answers (2)

waqaslam
waqaslam

Reputation: 68187

You need to use explicit Intent when creating PendingIntent for broadcast. The behavior has been changed starting from Android 8.0 and onwards.

Upvotes: 0

phreakhead
phreakhead

Reputation: 15259

Is this on a Samsung phone? I've noticed on Samsung phones, they block starting services (and maybe sending broadcasts) in the background e.g. from a widget, unless you disable battery optimization for your app. Best to launch an Activity instead (it can be a transparent activity that just does the thing and quits, or starts your service or whatever)

Upvotes: 1

Related Questions