diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index a4bf9ef0e92..79842dffd10 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -137,7 +137,7 @@
android:exported="false">
-
+
-
+
diff --git a/app/src/main/java/io/homeassistant/companion/android/repositories/BaseDaoWidgetRepository.kt b/app/src/main/java/io/homeassistant/companion/android/repositories/BaseDaoWidgetRepository.kt
new file mode 100644
index 00000000000..2c27fc5e742
--- /dev/null
+++ b/app/src/main/java/io/homeassistant/companion/android/repositories/BaseDaoWidgetRepository.kt
@@ -0,0 +1,25 @@
+package io.homeassistant.companion.android.repositories
+
+import io.homeassistant.companion.android.database.widget.WidgetEntity
+import kotlinx.coroutines.flow.Flow
+
+interface BaseDaoWidgetRepository {
+
+ fun get(id: Int): T?
+
+ fun exist(appWidgetId: Int): Boolean {
+ return get(appWidgetId) != null
+ }
+
+ suspend fun add(entity: T)
+
+ suspend fun delete(id: Int)
+
+ suspend fun deleteAll(ids: IntArray)
+
+ suspend fun getAll(): List
+
+ suspend fun getAllFlow(): Flow>
+
+ suspend fun updateWidgetLastUpdate(widgetId: Int, lastUpdate: String)
+}
diff --git a/app/src/main/java/io/homeassistant/companion/android/repositories/ButtonWidgetRepository.kt b/app/src/main/java/io/homeassistant/companion/android/repositories/ButtonWidgetRepository.kt
new file mode 100644
index 00000000000..e271eee6148
--- /dev/null
+++ b/app/src/main/java/io/homeassistant/companion/android/repositories/ButtonWidgetRepository.kt
@@ -0,0 +1,5 @@
+package io.homeassistant.companion.android.repositories
+
+import io.homeassistant.companion.android.database.widget.ButtonWidgetEntity
+
+interface ButtonWidgetRepository : BaseDaoWidgetRepository
diff --git a/app/src/main/java/io/homeassistant/companion/android/repositories/ButtonWidgetRepositoryImpl.kt b/app/src/main/java/io/homeassistant/companion/android/repositories/ButtonWidgetRepositoryImpl.kt
new file mode 100644
index 00000000000..5fe937ddfe1
--- /dev/null
+++ b/app/src/main/java/io/homeassistant/companion/android/repositories/ButtonWidgetRepositoryImpl.kt
@@ -0,0 +1,29 @@
+package io.homeassistant.companion.android.repositories
+
+import io.homeassistant.companion.android.database.widget.ButtonWidgetDao
+import io.homeassistant.companion.android.database.widget.ButtonWidgetEntity
+import javax.inject.Inject
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flowOn
+
+class ButtonWidgetRepositoryImpl @Inject constructor(
+ private val dao: ButtonWidgetDao
+) : ButtonWidgetRepository {
+
+ override fun get(id: Int): ButtonWidgetEntity? {
+ return dao.get(id)
+ }
+
+ override suspend fun add(entity: ButtonWidgetEntity) = dao.add(entity)
+
+ override suspend fun delete(id: Int) = dao.delete(id)
+
+ override suspend fun deleteAll(ids: IntArray) = dao.deleteAll(ids)
+
+ override suspend fun getAll(): List = dao.getAll()
+
+ override suspend fun getAllFlow(): Flow> = dao.getAllFlow().flowOn(Dispatchers.IO)
+
+ override suspend fun updateWidgetLastUpdate(widgetId: Int, lastUpdate: String) = error("Not Implemented")
+}
diff --git a/app/src/main/java/io/homeassistant/companion/android/repositories/CameraWidgetRepository.kt b/app/src/main/java/io/homeassistant/companion/android/repositories/CameraWidgetRepository.kt
new file mode 100644
index 00000000000..2636cbe12bd
--- /dev/null
+++ b/app/src/main/java/io/homeassistant/companion/android/repositories/CameraWidgetRepository.kt
@@ -0,0 +1,5 @@
+package io.homeassistant.companion.android.repositories
+
+import io.homeassistant.companion.android.database.widget.CameraWidgetEntity
+
+interface CameraWidgetRepository : BaseDaoWidgetRepository
diff --git a/app/src/main/java/io/homeassistant/companion/android/repositories/CameraWidgetRepositoryImpl.kt b/app/src/main/java/io/homeassistant/companion/android/repositories/CameraWidgetRepositoryImpl.kt
new file mode 100644
index 00000000000..6b66772ebde
--- /dev/null
+++ b/app/src/main/java/io/homeassistant/companion/android/repositories/CameraWidgetRepositoryImpl.kt
@@ -0,0 +1,25 @@
+package io.homeassistant.companion.android.repositories
+
+import io.homeassistant.companion.android.database.widget.CameraWidgetDao
+import io.homeassistant.companion.android.database.widget.CameraWidgetEntity
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+
+class CameraWidgetRepositoryImpl @Inject constructor(
+ private val dao: CameraWidgetDao
+) : CameraWidgetRepository {
+
+ override suspend fun add(entity: CameraWidgetEntity) = dao.add(entity)
+
+ override suspend fun delete(id: Int) = dao.delete(id)
+
+ override suspend fun deleteAll(ids: IntArray) = dao.deleteAll(ids)
+
+ override suspend fun getAll(): List = dao.getAll()
+
+ override suspend fun getAllFlow(): Flow> = dao.getAllFlow()
+
+ override suspend fun updateWidgetLastUpdate(widgetId: Int, lastUpdate: String) = error("Not Implemented")
+
+ override fun get(id: Int): CameraWidgetEntity? = dao.get(id)
+}
diff --git a/app/src/main/java/io/homeassistant/companion/android/repositories/MediaPlayerControlsWidgetRepository.kt b/app/src/main/java/io/homeassistant/companion/android/repositories/MediaPlayerControlsWidgetRepository.kt
new file mode 100644
index 00000000000..55780c70917
--- /dev/null
+++ b/app/src/main/java/io/homeassistant/companion/android/repositories/MediaPlayerControlsWidgetRepository.kt
@@ -0,0 +1,6 @@
+package io.homeassistant.companion.android.repositories
+
+import io.homeassistant.companion.android.database.widget.MediaPlayerControlsWidgetEntity
+
+interface MediaPlayerControlsWidgetRepository :
+ BaseDaoWidgetRepository
diff --git a/app/src/main/java/io/homeassistant/companion/android/repositories/MediaPlayerControlsWidgetRepositoryImpl.kt b/app/src/main/java/io/homeassistant/companion/android/repositories/MediaPlayerControlsWidgetRepositoryImpl.kt
new file mode 100644
index 00000000000..7c091e2516d
--- /dev/null
+++ b/app/src/main/java/io/homeassistant/companion/android/repositories/MediaPlayerControlsWidgetRepositoryImpl.kt
@@ -0,0 +1,27 @@
+package io.homeassistant.companion.android.repositories
+
+import io.homeassistant.companion.android.database.widget.MediaPlayerControlsWidgetDao
+import io.homeassistant.companion.android.database.widget.MediaPlayerControlsWidgetEntity
+import javax.inject.Inject
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flowOn
+
+class MediaPlayerControlsWidgetRepositoryImpl @Inject constructor(
+ private val dao: MediaPlayerControlsWidgetDao
+) : MediaPlayerControlsWidgetRepository {
+
+ override fun get(id: Int): MediaPlayerControlsWidgetEntity? = dao.get(id)
+
+ override suspend fun add(entity: MediaPlayerControlsWidgetEntity) = dao.add(entity)
+
+ override suspend fun delete(id: Int) = dao.delete(id)
+
+ override suspend fun deleteAll(ids: IntArray) = dao.deleteAll(ids)
+
+ override suspend fun getAll(): List = dao.getAll()
+
+ override suspend fun getAllFlow(): Flow> = dao.getAllFlow().flowOn(Dispatchers.IO)
+
+ override suspend fun updateWidgetLastUpdate(widgetId: Int, lastUpdate: String) = error("Not Implemented")
+}
diff --git a/app/src/main/java/io/homeassistant/companion/android/repositories/RepositoryModule.kt b/app/src/main/java/io/homeassistant/companion/android/repositories/RepositoryModule.kt
new file mode 100644
index 00000000000..3ccb4af1a90
--- /dev/null
+++ b/app/src/main/java/io/homeassistant/companion/android/repositories/RepositoryModule.kt
@@ -0,0 +1,36 @@
+package io.homeassistant.companion.android.repositories
+
+import dagger.Binds
+import dagger.Module
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+
+@Module
+@InstallIn(SingletonComponent::class)
+abstract class RepositoryModule {
+
+ @Binds
+ abstract fun bindMediaPlayerWidgetRepository(
+ impl: MediaPlayerControlsWidgetRepositoryImpl
+ ): MediaPlayerControlsWidgetRepository
+
+ @Binds
+ abstract fun bindTemplateWidgetRepository(
+ impl: TemplateWidgetRepositoryImpl
+ ): TemplateWidgetRepository
+
+ @Binds
+ abstract fun bindEntityWidgetRepository(
+ impl: StaticWidgetRepositoryImpl
+ ): StaticWidgetRepository
+
+ @Binds
+ abstract fun bindCameraWidgetRepository(
+ impl: CameraWidgetRepositoryImpl
+ ): CameraWidgetRepository
+
+ @Binds
+ abstract fun bindButtonWidgetRepository(
+ impl: ButtonWidgetRepositoryImpl
+ ): ButtonWidgetRepository
+}
diff --git a/app/src/main/java/io/homeassistant/companion/android/repositories/StaticWidgetRepository.kt b/app/src/main/java/io/homeassistant/companion/android/repositories/StaticWidgetRepository.kt
new file mode 100644
index 00000000000..d5890213fba
--- /dev/null
+++ b/app/src/main/java/io/homeassistant/companion/android/repositories/StaticWidgetRepository.kt
@@ -0,0 +1,5 @@
+package io.homeassistant.companion.android.repositories
+
+import io.homeassistant.companion.android.database.widget.StaticWidgetEntity
+
+interface StaticWidgetRepository : BaseDaoWidgetRepository
diff --git a/app/src/main/java/io/homeassistant/companion/android/repositories/StaticWidgetRepositoryImpl.kt b/app/src/main/java/io/homeassistant/companion/android/repositories/StaticWidgetRepositoryImpl.kt
new file mode 100644
index 00000000000..1391255a425
--- /dev/null
+++ b/app/src/main/java/io/homeassistant/companion/android/repositories/StaticWidgetRepositoryImpl.kt
@@ -0,0 +1,27 @@
+package io.homeassistant.companion.android.repositories
+
+import io.homeassistant.companion.android.database.widget.StaticWidgetDao
+import io.homeassistant.companion.android.database.widget.StaticWidgetEntity
+import javax.inject.Inject
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flowOn
+
+class StaticWidgetRepositoryImpl @Inject constructor(
+ private val dao: StaticWidgetDao
+) : StaticWidgetRepository {
+
+ override fun get(id: Int): StaticWidgetEntity? = dao.get(id)
+
+ override suspend fun updateWidgetLastUpdate(widgetId: Int, lastUpdate: String) = dao.updateWidgetLastUpdate(widgetId, lastUpdate)
+
+ override suspend fun add(entity: StaticWidgetEntity) = dao.add(entity)
+
+ override suspend fun delete(id: Int) = dao.delete(id)
+
+ override suspend fun deleteAll(ids: IntArray) = dao.deleteAll(ids)
+
+ override suspend fun getAll(): List = dao.getAll()
+
+ override suspend fun getAllFlow(): Flow> = dao.getAllFlow().flowOn(Dispatchers.IO)
+}
diff --git a/app/src/main/java/io/homeassistant/companion/android/repositories/TemplateWidgetRepository.kt b/app/src/main/java/io/homeassistant/companion/android/repositories/TemplateWidgetRepository.kt
new file mode 100644
index 00000000000..e5ec45fed80
--- /dev/null
+++ b/app/src/main/java/io/homeassistant/companion/android/repositories/TemplateWidgetRepository.kt
@@ -0,0 +1,5 @@
+package io.homeassistant.companion.android.repositories
+
+import io.homeassistant.companion.android.database.widget.TemplateWidgetEntity
+
+interface TemplateWidgetRepository : BaseDaoWidgetRepository
diff --git a/app/src/main/java/io/homeassistant/companion/android/repositories/TemplateWidgetRepositoryImpl.kt b/app/src/main/java/io/homeassistant/companion/android/repositories/TemplateWidgetRepositoryImpl.kt
new file mode 100644
index 00000000000..fd59cd5ed68
--- /dev/null
+++ b/app/src/main/java/io/homeassistant/companion/android/repositories/TemplateWidgetRepositoryImpl.kt
@@ -0,0 +1,27 @@
+package io.homeassistant.companion.android.repositories
+
+import io.homeassistant.companion.android.database.widget.TemplateWidgetDao
+import io.homeassistant.companion.android.database.widget.TemplateWidgetEntity
+import javax.inject.Inject
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flowOn
+
+class TemplateWidgetRepositoryImpl @Inject constructor(
+ private val dao: TemplateWidgetDao
+) : TemplateWidgetRepository {
+
+ override fun get(id: Int): TemplateWidgetEntity? = dao.get(id)
+
+ override suspend fun delete(id: Int) = dao.delete(id)
+
+ override suspend fun deleteAll(ids: IntArray) = dao.deleteAll(ids)
+
+ override suspend fun getAll(): List = dao.getAll()
+
+ override suspend fun getAllFlow(): Flow> = dao.getAllFlow().flowOn(Dispatchers.IO)
+
+ override suspend fun updateWidgetLastUpdate(widgetId: Int, lastUpdate: String) = dao.updateTemplateWidgetLastUpdate(widgetId, lastUpdate)
+
+ override suspend fun add(entity: TemplateWidgetEntity) = dao.add(entity)
+}
diff --git a/app/src/main/java/io/homeassistant/companion/android/widgets/BaseWidgetConfigureActivity.kt b/app/src/main/java/io/homeassistant/companion/android/widgets/BaseWidgetConfigureActivity.kt
index e232ffd653f..8fafa995306 100644
--- a/app/src/main/java/io/homeassistant/companion/android/widgets/BaseWidgetConfigureActivity.kt
+++ b/app/src/main/java/io/homeassistant/companion/android/widgets/BaseWidgetConfigureActivity.kt
@@ -10,17 +10,18 @@ import android.widget.Toast
import io.homeassistant.companion.android.BaseActivity
import io.homeassistant.companion.android.common.R
import io.homeassistant.companion.android.common.data.servers.ServerManager
-import io.homeassistant.companion.android.database.widget.WidgetDao
+import io.homeassistant.companion.android.repositories.BaseDaoWidgetRepository
import javax.inject.Inject
-abstract class BaseWidgetConfigureActivity : BaseActivity() {
+abstract class BaseWidgetConfigureActivity> : BaseActivity() {
@Inject
lateinit var serverManager: ServerManager
protected var appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID
- abstract val dao: WidgetDao
+ @Inject
+ lateinit var repository: T
abstract val serverSelect: View
abstract val serverSelectList: Spinner
diff --git a/app/src/main/java/io/homeassistant/companion/android/widgets/BaseWidgetProvider.kt b/app/src/main/java/io/homeassistant/companion/android/widgets/BaseWidgetProvider.kt
index 275ec96eda9..bc246ed7ad2 100644
--- a/app/src/main/java/io/homeassistant/companion/android/widgets/BaseWidgetProvider.kt
+++ b/app/src/main/java/io/homeassistant/companion/android/widgets/BaseWidgetProvider.kt
@@ -6,32 +6,40 @@ import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
+import android.graphics.Color
import android.os.Bundle
import android.util.Log
import android.widget.RemoteViews
import androidx.core.content.ContextCompat
-import io.homeassistant.companion.android.common.data.integration.Entity
+import io.homeassistant.companion.android.R
import io.homeassistant.companion.android.common.data.servers.ServerManager
+import io.homeassistant.companion.android.database.widget.ThemeableWidgetEntity
+import io.homeassistant.companion.android.database.widget.WidgetBackgroundType
+import io.homeassistant.companion.android.repositories.BaseDaoWidgetRepository
+import io.homeassistant.companion.android.util.hasActiveConnection
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.first
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
/**
* A widget provider class for widgets that update based on entity state changes.
*/
-abstract class BaseWidgetProvider : AppWidgetProvider() {
+abstract class BaseWidgetProvider, WidgetDataType> : AppWidgetProvider() {
companion object {
const val UPDATE_VIEW =
- "io.homeassistant.companion.android.widgets.template.BaseWidgetProvider.UPDATE_VIEW"
+ "io.homeassistant.companion.android.widgets.UPDATE_VIEW"
const val RECEIVE_DATA =
- "io.homeassistant.companion.android.widgets.template.TemplateWidget.RECEIVE_DATA"
+ "io.homeassistant.companion.android.widgets.RECEIVE_DATA"
var widgetScope: CoroutineScope? = null
+ var widgetWorkScope: CoroutineScope? = null
val widgetEntities = mutableMapOf>()
val widgetJobs = mutableMapOf()
}
@@ -39,7 +47,10 @@ abstract class BaseWidgetProvider : AppWidgetProvider() {
@Inject
lateinit var serverManager: ServerManager
- private var thisSetScope = false
+ @Inject
+ lateinit var repository: T
+
+ protected var thisSetScope = false
protected var lastIntent = ""
init {
@@ -49,6 +60,7 @@ abstract class BaseWidgetProvider : AppWidgetProvider() {
private fun setupWidgetScope() {
if (widgetScope == null || !widgetScope!!.isActive) {
widgetScope = CoroutineScope(Dispatchers.Main + Job())
+ widgetWorkScope = CoroutineScope(Dispatchers.IO + Job())
thisSetScope = true
}
}
@@ -61,8 +73,7 @@ abstract class BaseWidgetProvider : AppWidgetProvider() {
// There may be multiple widgets active, so update all of them
for (appWidgetId in appWidgetIds) {
widgetScope?.launch {
- val views = getWidgetRemoteViews(context, appWidgetId)
- appWidgetManager.updateAppWidget(appWidgetId, views)
+ forceUpdateView(context, appWidgetId, appWidgetManager)
}
}
}
@@ -70,10 +81,11 @@ abstract class BaseWidgetProvider : AppWidgetProvider() {
override fun onReceive(context: Context, intent: Intent) {
lastIntent = intent.action.toString()
val appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1)
+ Log.d(getWidgetProvider(context).shortClassName, "Broadcast received: " + System.lineSeparator() + "Broadcast action: " + lastIntent + System.lineSeparator() + "AppWidgetId: " + appWidgetId)
super.onReceive(context, intent)
when (lastIntent) {
- UPDATE_VIEW -> updateView(context, appWidgetId)
+ UPDATE_VIEW -> forceUpdateView(context, appWidgetId)
RECEIVE_DATA -> {
saveEntityConfiguration(
context,
@@ -87,13 +99,13 @@ abstract class BaseWidgetProvider : AppWidgetProvider() {
}
}
- fun onScreenOn(context: Context) {
+ private fun onScreenOn(context: Context) {
setupWidgetScope()
if (!serverManager.isRegistered()) return
widgetScope!!.launch {
updateAllWidgets(context)
- val allWidgets = getAllWidgetIdsWithEntities(context)
+ val allWidgets = getAllWidgetIdsWithEntities()
val widgetsWithDifferentEntities = allWidgets.filter { it.value.second != widgetEntities[it.key] }
if (widgetsWithDifferentEntities.isNotEmpty()) {
ContextCompat.registerReceiver(
@@ -109,7 +121,7 @@ abstract class BaseWidgetProvider : AppWidgetProvider() {
val (serverId, entities) = pair.first to pair.second
val entityUpdates =
if (serverManager.getServer(serverId) != null) {
- serverManager.integrationRepository(serverId).getEntityUpdates(entities)
+ getUpdates(serverId, entities)
} else {
null
}
@@ -131,6 +143,7 @@ abstract class BaseWidgetProvider : AppWidgetProvider() {
private fun onScreenOff() {
if (thisSetScope) {
+ widgetWorkScope?.cancel()
widgetScope?.cancel()
thisSetScope = false
widgetEntities.clear()
@@ -145,7 +158,7 @@ abstract class BaseWidgetProvider : AppWidgetProvider() {
val systemWidgetIds = AppWidgetManager.getInstance(context)
.getAppWidgetIds(widgetProvider)
.toSet()
- val dbWidgetIds = getAllWidgetIdsWithEntities(context).keys
+ val dbWidgetIds = getAllWidgetIdsWithEntities().keys
val invalidWidgetIds = dbWidgetIds.minus(systemWidgetIds)
if (invalidWidgetIds.isNotEmpty()) {
@@ -157,18 +170,21 @@ abstract class BaseWidgetProvider : AppWidgetProvider() {
}
dbWidgetIds.filter { systemWidgetIds.contains(it) }.forEach {
- updateView(context, it)
+ forceUpdateView(context, it)
}
}
- private fun updateView(
+ fun forceUpdateView(
context: Context,
appWidgetId: Int,
appWidgetManager: AppWidgetManager = AppWidgetManager.getInstance(context)
) {
widgetScope?.launch {
- val views = getWidgetRemoteViews(context, appWidgetId)
+ val hasActiveConnection = context.hasActiveConnection()
+ val views = getWidgetRemoteViews(context, appWidgetId, hasActiveConnection)
+ Log.d(getWidgetProvider(context).shortClassName, "Updating Widget View updateAppWidget() hasActiveConnection: $hasActiveConnection")
appWidgetManager.updateAppWidget(appWidgetId, views)
+ onWidgetsViewUpdated(context, appWidgetId, appWidgetManager, views, hasActiveConnection)
}
}
@@ -178,11 +194,50 @@ abstract class BaseWidgetProvider : AppWidgetProvider() {
widgetJobs.remove(appWidgetId)
}
+ private suspend fun getAllWidgetIdsWithEntities(): Map>> =
+ repository.getAllFlow()
+ .first()
+ .associate {
+ it.id to (it.serverId to listOf(it.entityId.orEmpty()))
+ }
+
+ fun setWidgetBackground(views: RemoteViews, layoutId: Int, widget: ThemeableWidgetEntity?) {
+ when (widget?.backgroundType) {
+ WidgetBackgroundType.TRANSPARENT -> {
+ views.setInt(layoutId, "setBackgroundColor", Color.TRANSPARENT)
+ }
+
+ else -> {
+ views.setInt(layoutId, "setBackgroundResource", R.drawable.widget_button_background)
+ }
+ }
+ }
+
+ override fun onDeleted(context: Context, appWidgetIds: IntArray) {
+ widgetScope?.launch {
+ repository.deleteAll(appWidgetIds)
+ appWidgetIds.forEach { removeSubscription(it) }
+ }
+ }
+
+ open fun onWidgetsViewUpdated(context: Context, appWidgetId: Int, appWidgetManager: AppWidgetManager, remoteViews: RemoteViews, hasActiveConnection: Boolean) {
+ Log.d(
+ getWidgetProvider(context).shortClassName,
+ "onWidgetsViewUpdated() received, AppWidgetId: $appWidgetId hasActiveConnection: $hasActiveConnection"
+ )
+ }
+
+ open suspend fun onEntityStateChanged(context: Context, appWidgetId: Int, entity: WidgetDataType) {
+ Log.d(
+ getWidgetProvider(context).shortClassName,
+ "onEntityStateChanged(), AppWidgetId: $appWidgetId"
+ )
+ }
+
abstract fun getWidgetProvider(context: Context): ComponentName
- abstract suspend fun getWidgetRemoteViews(context: Context, appWidgetId: Int, suggestedEntity: Entity