mirror of
https://github.com/home-assistant/android
synced 2024-09-06 17:23:32 +00:00
Automatically delete 'stale'/old widgets from database (#2702)
Automatically delete stale widgets from database - Automatically removes widgets that are no longer bound to the widget provider but that are still in the database -> 'stale'/old widgets will no longer cause unnecessary updates
This commit is contained in:
parent
2e7c72456c
commit
1cf3506d4b
|
@ -1,14 +1,10 @@
|
|||
package io.homeassistant.companion.android.widgets
|
||||
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import io.homeassistant.companion.android.BaseActivity
|
||||
import io.homeassistant.companion.android.common.R
|
||||
import io.homeassistant.companion.android.database.widget.WidgetDao
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
abstract class BaseWidgetConfigureActivity : BaseActivity() {
|
||||
|
||||
|
@ -16,34 +12,6 @@ abstract class BaseWidgetConfigureActivity : BaseActivity() {
|
|||
|
||||
abstract val dao: WidgetDao
|
||||
|
||||
protected val onDeleteWidget = View.OnClickListener { deleteConfirmation(it.context) }
|
||||
|
||||
private fun deleteConfirmation(context: Context) {
|
||||
val builder: android.app.AlertDialog.Builder = android.app.AlertDialog.Builder(context)
|
||||
|
||||
builder.setTitle(R.string.confirm_delete_this_widget_title)
|
||||
builder.setMessage(R.string.confirm_delete_this_widget_message)
|
||||
|
||||
builder.setPositiveButton(
|
||||
R.string.confirm_positive
|
||||
) { dialog, _ ->
|
||||
lifecycleScope.launch {
|
||||
dao.delete(appWidgetId)
|
||||
dialog.dismiss()
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
builder.setNegativeButton(
|
||||
R.string.confirm_negative
|
||||
) { dialog, _ -> // Do nothing
|
||||
dialog.dismiss()
|
||||
}
|
||||
|
||||
val alert: android.app.AlertDialog? = builder.create()
|
||||
alert?.show()
|
||||
}
|
||||
|
||||
protected fun showAddWidgetError() {
|
||||
Toast.makeText(applicationContext, R.string.widget_creation_error, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
|
|
|
@ -2,9 +2,11 @@ package io.homeassistant.companion.android.widgets
|
|||
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.appwidget.AppWidgetProvider
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.widget.RemoteViews
|
||||
import io.homeassistant.companion.android.common.data.integration.Entity
|
||||
import io.homeassistant.companion.android.common.data.integration.IntegrationRepository
|
||||
|
@ -92,7 +94,22 @@ abstract class BaseWidgetProvider : AppWidgetProvider() {
|
|||
private suspend fun updateAllWidgets(
|
||||
context: Context
|
||||
) {
|
||||
getAllWidgetIds(context).forEach {
|
||||
val widgetProvider = getWidgetProvider(context)
|
||||
val systemWidgetIds = AppWidgetManager.getInstance(context)
|
||||
.getAppWidgetIds(widgetProvider)
|
||||
.toSet()
|
||||
val dbWidgetIds = getAllWidgetIds(context)
|
||||
|
||||
val invalidWidgetIds = dbWidgetIds.minus(systemWidgetIds)
|
||||
if (invalidWidgetIds.isNotEmpty()) {
|
||||
Log.i(
|
||||
widgetProvider.shortClassName,
|
||||
"Found widgets $invalidWidgetIds in database, but not in AppWidgetManager - sending onDeleted"
|
||||
)
|
||||
onDeleted(context, invalidWidgetIds.toIntArray())
|
||||
}
|
||||
|
||||
dbWidgetIds.filter { systemWidgetIds.contains(it) }.forEach {
|
||||
updateView(context, it)
|
||||
}
|
||||
}
|
||||
|
@ -108,6 +125,7 @@ abstract class BaseWidgetProvider : AppWidgetProvider() {
|
|||
}
|
||||
}
|
||||
|
||||
abstract fun getWidgetProvider(context: Context): ComponentName
|
||||
abstract suspend fun getWidgetRemoteViews(context: Context, appWidgetId: Int, suggestedEntity: Entity<Map<String, Any>>? = null): RemoteViews
|
||||
abstract suspend fun getAllWidgetIds(context: Context): List<Int>
|
||||
abstract fun saveEntityConfiguration(context: Context, extras: Bundle?, appWidgetId: Int)
|
||||
|
|
|
@ -3,6 +3,7 @@ package io.homeassistant.companion.android.widgets.button
|
|||
import android.app.PendingIntent
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.appwidget.AppWidgetProvider
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
|
@ -85,10 +86,21 @@ class ButtonWidget : AppWidgetProvider() {
|
|||
|
||||
private fun updateAllWidgets(context: Context) {
|
||||
mainScope.launch {
|
||||
val buttonWidgetEntityList = buttonWidgetDao.getAll()
|
||||
val appWidgetManager = AppWidgetManager.getInstance(context)
|
||||
val systemWidgetIds = appWidgetManager.getAppWidgetIds(ComponentName(context, ButtonWidget::class.java))
|
||||
val dbWidgetList = buttonWidgetDao.getAll()
|
||||
|
||||
val invalidWidgetIds = dbWidgetList
|
||||
.filter { !systemWidgetIds.contains(it.id) }
|
||||
.map { it.id }
|
||||
if (invalidWidgetIds.isNotEmpty()) {
|
||||
Log.i(TAG, "Found widgets $invalidWidgetIds in database, but not in AppWidgetManager - sending onDeleted")
|
||||
onDeleted(context, invalidWidgetIds.toIntArray())
|
||||
}
|
||||
|
||||
val buttonWidgetEntityList = dbWidgetList.filter { systemWidgetIds.contains(it.id) }
|
||||
if (buttonWidgetEntityList.isNotEmpty()) {
|
||||
Log.d(TAG, "Updating all widgets")
|
||||
val appWidgetManager = AppWidgetManager.getInstance(context)
|
||||
for (item in buttonWidgetEntityList) {
|
||||
val views = getWidgetRemoteViews(context, item.id)
|
||||
|
||||
|
|
|
@ -223,8 +223,6 @@ class ButtonWidgetConfigureActivity : BaseWidgetConfigureActivity(), IconDialog.
|
|||
buttonWidget.textColor?.let { it.toColorInt() == ContextCompat.getColor(this, commonR.color.colorWidgetButtonLabelBlack) } ?: false
|
||||
|
||||
binding.addButton.setText(commonR.string.update_widget)
|
||||
binding.deleteButton.visibility = VISIBLE
|
||||
binding.deleteButton.setOnClickListener(onDeleteWidget)
|
||||
} else {
|
||||
binding.backgroundType.setSelection(0)
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package io.homeassistant.companion.android.widgets.camera
|
|||
import android.app.PendingIntent
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.appwidget.AppWidgetProvider
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.ConnectivityManager
|
||||
|
@ -84,10 +85,21 @@ class CameraWidget : AppWidgetProvider() {
|
|||
|
||||
private fun updateAllWidgets(context: Context) {
|
||||
mainScope.launch {
|
||||
val cameraWidgetList = cameraWidgetDao.getAll()
|
||||
val appWidgetManager = AppWidgetManager.getInstance(context)
|
||||
val systemWidgetIds = appWidgetManager.getAppWidgetIds(ComponentName(context, CameraWidget::class.java))
|
||||
val dbWidgetList = cameraWidgetDao.getAll()
|
||||
|
||||
val invalidWidgetIds = dbWidgetList
|
||||
.filter { !systemWidgetIds.contains(it.id) }
|
||||
.map { it.id }
|
||||
if (invalidWidgetIds.isNotEmpty()) {
|
||||
Log.i(TAG, "Found widgets $invalidWidgetIds in database, but not in AppWidgetManager - sending onDeleted")
|
||||
onDeleted(context, invalidWidgetIds.toIntArray())
|
||||
}
|
||||
|
||||
val cameraWidgetList = dbWidgetList.filter { systemWidgetIds.contains(it.id) }
|
||||
if (cameraWidgetList.isNotEmpty()) {
|
||||
Log.d(TAG, "Updating all widgets")
|
||||
val appWidgetManager = AppWidgetManager.getInstance(context)
|
||||
for (item in cameraWidgetList) {
|
||||
updateAppWidget(context, item.id, appWidgetManager)
|
||||
}
|
||||
|
|
|
@ -98,8 +98,6 @@ class CameraWidgetConfigureActivity : BaseWidgetConfigureActivity() {
|
|||
if (cameraWidget != null) {
|
||||
binding.widgetTextConfigEntityId.setText(cameraWidget.entityId)
|
||||
binding.addButton.setText(commonR.string.update_widget)
|
||||
binding.deleteButton.visibility = View.VISIBLE
|
||||
binding.deleteButton.setOnClickListener(onDeleteWidget)
|
||||
val entity = runBlocking {
|
||||
try {
|
||||
integrationUseCase.getEntity(cameraWidget.entityId)
|
||||
|
|
|
@ -2,6 +2,7 @@ package io.homeassistant.companion.android.widgets.entity
|
|||
|
||||
import android.app.PendingIntent
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
|
@ -46,6 +47,9 @@ class EntityWidget : BaseWidgetProvider() {
|
|||
@Inject
|
||||
lateinit var staticWidgetDao: StaticWidgetDao
|
||||
|
||||
override fun getWidgetProvider(context: Context): ComponentName =
|
||||
ComponentName(context, EntityWidget::class.java)
|
||||
|
||||
override suspend fun getWidgetRemoteViews(context: Context, appWidgetId: Int, suggestedEntity: Entity<Map<String, Any>>?): RemoteViews {
|
||||
val intent = Intent(context, EntityWidget::class.java).apply {
|
||||
action = UPDATE_VIEW
|
||||
|
|
|
@ -166,8 +166,6 @@ class EntityWidgetConfigureActivity : BaseWidgetConfigureActivity() {
|
|||
staticWidget.textColor?.let { it.toColorInt() == ContextCompat.getColor(this, commonR.color.colorWidgetButtonLabelBlack) } ?: false
|
||||
|
||||
binding.addButton.setText(commonR.string.update_widget)
|
||||
binding.deleteButton.visibility = VISIBLE
|
||||
binding.deleteButton.setOnClickListener(onDeleteWidget)
|
||||
} else {
|
||||
binding.backgroundType.setSelection(0)
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package io.homeassistant.companion.android.widgets.media_player_controls
|
|||
|
||||
import android.app.PendingIntent
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
|
@ -71,6 +72,9 @@ class MediaPlayerControlsWidget : BaseWidgetProvider() {
|
|||
@Inject
|
||||
lateinit var mediaPlayCtrlWidgetDao: MediaPlayerControlsWidgetDao
|
||||
|
||||
override fun getWidgetProvider(context: Context): ComponentName =
|
||||
ComponentName(context, MediaPlayerControlsWidget::class.java)
|
||||
|
||||
override fun onUpdate(
|
||||
context: Context,
|
||||
appWidgetManager: AppWidgetManager,
|
||||
|
|
|
@ -143,8 +143,6 @@ class MediaPlayerControlsWidgetConfigureActivity : BaseWidgetConfigureActivity()
|
|||
if (entities != null)
|
||||
selectedEntities.addAll(entities)
|
||||
binding.addButton.setText(commonR.string.update_widget)
|
||||
binding.deleteButton.visibility = View.VISIBLE
|
||||
binding.deleteButton.setOnClickListener(onDeleteWidget)
|
||||
}
|
||||
val entityAdapter = SingleItemArrayAdapter<Entity<Any>>(this) { it?.entityId ?: "" }
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package io.homeassistant.companion.android.widgets.template
|
|||
|
||||
import android.app.PendingIntent
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
|
@ -46,6 +47,9 @@ class TemplateWidget : BaseWidgetProvider() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun getWidgetProvider(context: Context): ComponentName =
|
||||
ComponentName(context, TemplateWidget::class.java)
|
||||
|
||||
override suspend fun getAllWidgetIds(context: Context): List<Int> {
|
||||
return templateWidgetDao.getAll().map { it.id }
|
||||
}
|
||||
|
|
|
@ -114,9 +114,6 @@ class TemplateWidgetConfigureActivity : BaseWidgetConfigureActivity() {
|
|||
templateWidget.textColor?.let { it.toColorInt() == ContextCompat.getColor(this, android.R.color.white) } ?: true
|
||||
binding.textColorBlack.isChecked =
|
||||
templateWidget.textColor?.let { it.toColorInt() == ContextCompat.getColor(this, commonR.color.colorWidgetButtonLabelBlack) } ?: false
|
||||
|
||||
binding.deleteButton.visibility = View.VISIBLE
|
||||
binding.deleteButton.setOnClickListener(onDeleteWidget)
|
||||
} else {
|
||||
binding.backgroundType.setSelection(0)
|
||||
}
|
||||
|
|
|
@ -171,14 +171,5 @@
|
|||
android:layout_marginTop="8dp"
|
||||
android:text="@string/add_widget" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/delete_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginTop="8dp"
|
||||
android:visibility="gone"
|
||||
android:text="@string/delete_widget" />
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
|
@ -46,14 +46,5 @@
|
|||
android:layout_marginTop="8dp"
|
||||
android:text="@string/add_widget" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/delete_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginTop="8dp"
|
||||
android:visibility="gone"
|
||||
android:text="@string/delete_widget" />
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
|
@ -130,13 +130,5 @@
|
|||
android:layout_gravity="end"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/add_widget" />
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/delete_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginTop="8dp"
|
||||
android:visibility="gone"
|
||||
android:text="@string/delete_widget" />
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
|
@ -235,15 +235,6 @@
|
|||
android:layout_gravity="end"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/add_widget" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/delete_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginTop="8dp"
|
||||
android:visibility="gone"
|
||||
android:text="@string/delete_widget" />
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
|
@ -118,15 +118,6 @@
|
|||
android:layout_gravity="end"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/add_widget" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/delete_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginTop="8dp"
|
||||
android:visibility="gone"
|
||||
android:text="@string/delete_widget" />
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
|
@ -119,8 +119,6 @@
|
|||
<string name="confirm_delete_all_notification_title">Confirm deleting all notifications</string>
|
||||
<string name="confirm_delete_this_notification_message">Are you sure? This cannot be undone</string>
|
||||
<string name="confirm_delete_this_notification_title">Confirm deleting this notification</string>
|
||||
<string name="confirm_delete_this_widget_message">Are you sure? This cannot be undone. If you accidentally deleted the wrong widget you will need to remove the bad widget from the home screen and create a new one.</string>
|
||||
<string name="confirm_delete_this_widget_title">Confirm deleting this widget</string>
|
||||
<string name="confirm_negative">NO</string>
|
||||
<string name="confirm_positive">YES</string>
|
||||
<string name="continue_on_phone">Continue on your phone</string>
|
||||
|
@ -138,7 +136,6 @@
|
|||
<string name="delete_all_notifications">Delete all notifications from history</string>
|
||||
<string name="delete_shortcut">Delete Shortcut</string>
|
||||
<string name="delete_this_notification">Delete this notification from history</string>
|
||||
<string name="delete_widget">Delete Widget</string>
|
||||
<string name="description">Description</string>
|
||||
<string name="details">Details</string>
|
||||
<string name="developer_tools">Developer Tools</string>
|
||||
|
|
Loading…
Reference in a new issue