Reputation: 175
Create two Android Home Screen widgets for an app of two different sizes (3x2 & 5x2) as discussed in this StackOverflow question: Multiple widget sizes. As mentioned, two classes that implement AppWidgetProvider()
must be created that serve as the Kotlin business logic for each widget size. Each widget has its own layout XML
and info XML
.
EXAMPLEWidgetSmall.kt
package com.example.exampleapp
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.Context
import android.widget.RemoteViews
/**
* Implementation of App Widget functionality.
*/
class EXAMPLEWidgetSmall : AppWidgetProvider() {
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
// There may be multiple widgets active, so update all of them
for (appWidgetId in appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId)
}
}
override fun onEnabled(context: Context) {
// Enter relevant functionality for when the first widget is created
}
override fun onDisabled(context: Context) {
// Enter relevant functionality for when the last widget is disabled
}
}
internal fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int) {
val widgetText = context.getString(R.string.appwidget_text)
// Construct the RemoteViews object
val views = RemoteViews(context.packageName, R.layout.example_widget_small)
views.setTextViewText(R.id.appwidget_text, widgetText)
// Instruct the widget manager to update the widget
appWidgetManager.updateAppWidget(appWidgetId, views)
}
EXAMPLEWidgetMedium.kt
package com.example.exampleapp
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.Context
import android.widget.RemoteViews
/**
* Implementation of App Widget functionality.
*/
class EXAMPLEWidgetMedium : AppWidgetProvider() {
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
// There may be multiple widgets active, so update all of them
for (appWidgetId in appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId)
}
}
override fun onEnabled(context: Context) {
// Enter relevant functionality for when the first widget is created
}
override fun onDisabled(context: Context) {
// Enter relevant functionality for when the last widget is disabled
}
}
internal fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int) {
val widgetText = context.getString(R.string.appwidget_text)
// Construct the RemoteViews object
val views = RemoteViews(context.packageName, R.layout.example_widget_medium)
views.setTextViewText(R.id.appwidget_text, widgetText)
// Instruct the widget manager to update the widget
appWidgetManager.updateAppWidget(appWidgetId, views)
}
e:
/Users/example/examplefolder/exampleapp/android/app/src/main/kotlin/com/example/exampleapp/EXAMPLEWidgetMedium.kt: (15, 13): Overload resolution ambiguity:
internal fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int): Unit defined in com.example.exampleapp in file EXAMPLEWidgetMedium.kt
internal fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int): Unit defined in com.example.exampleapp in file EXAMPLEWidgetSmall.kt
e: /Users/example/examplefolder/exampleapp/android/app/src/main/kotlin/com/example/exampleapp/EXAMPLEWidgetMedium.kt: (28, 1): Conflicting overloads: internal fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int): Unit defined in com.example.exampleapp in file EXAMPLEWidgetMedium.kt, internal fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int): Unit defined in com.example.exampleapp in file EXAMPLEWidgetSmall.kt
e: /Users/example/examplefolder/exampleapp/android/app/src/main/kotlin/com/example/exampleapp/EXAMPLEWidgetSmall.kt: (15, 13): Overload resolution ambiguity:
internal fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int): Unit defined in com.example.exampleapp in file EXAMPLEWidgetMedium.kt
internal fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int): Unit defined in com.example.exampleapp in file EXAMPLEWidgetSmall.kt
e: /Users/example/examplefolder/exampleapp/android/app/src/main/kotlin/com/example/exampleapp/EXAMPLEWidgetSmall.kt: (28, 1): Conflicting overloads: internal fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int): Unit defined in com.example.exampleapp in file EXAMPLEWidgetMedium.kt, internal fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int): Unit defined in com.example.exampleapp in file EXAMPLEWidgetSmall.kt
The issue seems to revolve around internal fun updateAppWidget being used in both files causing an overload resolution ambiguity. If I try to change the name of this function, another error is thrown, as this deviates from the important function of the AppWidgetProvider()
class. In this StackOverflow answer: How to add multiple widgets in the same app?, it is suggested that a "BaseWidget" class be created that implements AppWidgetProvider()
and from which my two widget kt files would implement BaseWidget()
. However I am unsure if this would solve the issue because I would still be trying to use the same internal function updateAppWidget()
, nor how I would write this code (I am not familiar with Kotlin) because this var must vary in each file which defines each widget layout val views = RemoteViews(context.packageName, R.layout.example_widget_small)
. How can I fix this issue so that the app can compile with no errors and for these widgets can work so that I can continue with their layout? Thank you!
Upvotes: 2
Views: 612
Reputation: 40830
I see both AppWidgetProviders
are identical except for their layouts; so you would create an abstract parent class that has an abstract Int
field for the layout int resource id that you must set in each widget sub-class with the corresponding layout resource.
And keep any shared code normally in the parent class. Now the RemoteViews
can be implemented in the parent class with that Int
field which has been set in the implemented child classes.
Here's the implementation of that:
Parent class:: make it abstract, add the abstract widgetLayout
field; and keep the shared functionality
And for the error you face; you need to keep the internal fun updateAppWidget
as a part of your parent class.
abstract class ParentWidgetProvider : AppWidgetProvider() {
abstract var widgetLayout: Int // must be overiden by the child classes with the widget layout
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
// There may be multiple widgets active, so update all of them
for (appWidgetId in appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId)
}
}
override fun onEnabled(context: Context) {
// Enter relevant functionality for when the first widget is created
}
override fun onDisabled(context: Context) {
// Enter relevant functionality for when the last widget is disabled
}
private fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int) {
val widgetText = context.getString(R.string.appwidget_text)
// Construct the RemoteViews object
val views = RemoteViews(context.packageName, widgetLayout) //
views.setTextViewText(R.id.appwidget_text, widgetText)
// Instruct the widget manager to update the widget
appWidgetManager.updateAppWidget(appWidgetId, views)
}
}
And override the widgetLayout
in the child classes:
Small widget
class EXAMPLEWidgetSmall : ParentWidgetProvider() {
override var widgetLayout
get() = R.layout.example_widget_small
set(_) {R.layout.example_widget_small}
}
Medium widget (the same but with different layout file)
class EXAMPLEWidgetMedium : ParentWidgetProvider() {
override var widgetLayout
get() = R.layout.example_widget_medium
set(_) {R.layout.example_widget_medium}
}
Upvotes: 3