I reduced a bigger portion of code to this easy to test AppWidgetProvider
class and I still have this problem.
Basically, I have a simple navigation part with a prev and next button. If the index is 0 , the prev button should be gone, if index is 10, the next button is gone. When it's in between, both buttons are displayed. Pressing the buttons increases or decreases the index, which is saved in SharedPreferences
The problem I have is that, for example, when the widget is updated for the first time (and the index is 0), the prev button is not gone. As I click the next button, I can see the index being increased and the TextView
in the center shows it. When the index is 10, at least the first time I tested it, the next button is gone, but then when I go back by pressing prev and the index is lower than 10, it doesn't show up again. And then, when I get to index 0, the prev button is not gone.
So, it's all this sort of weird behaviour that has to do with updating the widget that I have been going nuts with.
class DemoWidget : AppWidgetProvider() {
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
super.onUpdate(context, appWidgetManager, appWidgetIds)
for (appWidgetId in appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId)
}
}
override fun onReceive(context: Context, intent: Intent) {
super.onReceive(context, intent)
val action = intent.action ?: ""
if (action == "prev") {
setIndex(context, getIndex(context) - 1)
updateAppWidgets(context)
} else if (action == "next") {
setIndex(context, getIndex(context) + 1)
updateAppWidgets(context)
}
}
private fun updateAppWidgets(context: Context) {
val manager = AppWidgetManager.getInstance(context)
val ids = manager.getAppWidgetIds(ComponentName(context, javaClass))
ids.forEach {
updateAppWidget(context, manager, it)
}
}
private fun getIndex(context: Context): Int {
val prefs = context.getSharedPreferences(context.packageName, 0)
return prefs.getInt("index", 0)
}
private fun setIndex(context: Context, prefValue: Int) {
val prefs = context.getSharedPreferences(context.packageName, 0).edit()
prefs.putInt("index", prefValue)
prefs.apply()
}
private fun pendingIntent(context: Context?, action: String? = null): PendingIntent? {
val intent = Intent(context, javaClass)
intent.action = action
return PendingIntent.getBroadcast(
context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
}
private fun updateAppWidget(context: Context, manager: AppWidgetManager, widgetId: Int) {
val views = RemoteViews(context.packageName, R.layout.demo_widget)
val index = getIndex(context)
views.setTextViewText(R.id.textViewIndex, index.toString())
if (index > 0) {
views.setOnClickPendingIntent(
R.id.buttonPrev,
pendingIntent(context, "prev")
)
} else {
views.setViewVisibility(R.id.buttonBack, View.GONE)
}
if (index < 10) {
views.setOnClickPendingIntent(
R.id.buttonNext,
pendingIntent(context, "next")
)
} else {
views.setViewVisibility(R.id.buttonNext, View.GONE)
}
manager.updateAppWidget(widgetId, views)
}
}
and my layout
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/Widget.Demo.AppWidget.Container"
android:id="@+id/layoutWidget"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:theme="@style/Theme.Demo.AppWidgetContainer">
<ImageButton
android:id="@+id/buttonPrev"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start|center_vertical"
android:background="@android:color/transparent"
android:contentDescription="@string/back"
android:src="@drawable/app_widget_back_background" />
<TextView
android:id="@+id/textViewIndex"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:padding="@dimen/widget_menu_padding"
android:textColor="@color/white"
android:textAlignment="center" />
<ImageButton
android:id="@+id/buttonNext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|center_vertical"
android:background="@android:color/transparent"
android:contentDescription="@string/forward"
android:src="@drawable/app_widget_forward_background" />
</FrameLayout>
The Manifest file, if you need it
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/Theme.Demo">
<receiver
android:name=".DemoWidget"
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/demo_widget_info" />
</receiver>
</application>
</manifest>
Provider info (v31)
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/app_description"
android:initialLayout="@layout/demo_widget"
android:minWidth="@dimen/widget_min_width"
android:minHeight="@dimen/widget_min_height"
android:previewImage="@drawable/app_widget_preview"
android:preAviewLayout="@layout/demo_widget"
android:resizeMode="horizontal|vertical"
android:targetCellWidth="1"
android:targetCellHeight="1"
android:updatePeriodMillis="86400000"
android:widgetCategory="home_screen" />
views.setViewVisibility(R.id.buttonBack, View.GONE)
– InupdateAppWidget()
, you're setting the visibility for the "previous" button on a different ID. Not sure if that's just a typo here, or how that reconciles with the observed behavior, as I'm not sure if I'm understanding the description of that correctly.