Reputation: 135
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
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
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