Android: ¿Cómo obligar a la actualización de todos los widgets de un tipo particular
He visto muchas preguntas en este sentido, y sigo viendo la misma respuesta una y otra vez. No quiero tener que tener un servicio para cada tipo de widget de mi aplicación, especialmente viendo como mi aplicación ya tiene 2 servicios persistentes.
En concreto, si uno de mis servicios existentes ve que los datos han cambiado, quiero actualizar mis widgets. Hacer esto en un temporizador es molesto, ya que podría ser días entre actualizaciones o puede haber varios dentro de una hora. Quiero que mis widgets siempre muestren información actualizada.
- Android Studio, Problemas de reproducción
- Android 4.0: widgets no aparecen?
- Animación en la barra de notificaciones Vista personalizada
- Quitar Widget de la pantalla de inicio cuando se desinstala
- Android: Apertura de actividad incorrecta del widget
Diseño de widgets Android parece funcionar en la base de que su widget extrae información cuando lo quiere, creo que hay muchos escenarios razonables donde una actividad puede desear enviar datos a un widget.
Lea la respuesta a continuación para saber cómo he trabajado cómo hacer precisamente esto. Por lo que puedo ver no hay efectos adversos si se hace correctamente.
- Android: no se puede abrir el contenido: file: /// storage / emulated / 0
- Android: LED no se enciende / apaga
- OnClick PendingIntent en widget a veces no funciona
- RemoteViewsService no se ejecuta,
- ¿Cómo iniciar una nueva actividad desde lockscreen?
- ¿Usando un ToggleButton en un widget?
- WidgetProvider Los extras de intención enviados con el botón de clic no se encuentran en onReceive
- Cómo construir un Widget Android Simple
Para obligar a nuestros widgets a un determinado proveedor de widgets a actualizar, tendremos que hacer lo siguiente:
- Configurar nuestro proveedor para recibir una difusión especializada
- Enviar la difusión especializada con:
- Todas las ID de widget actual asociadas con el proveedor
- Los datos a enviar
- Claves a las que sólo responde nuestro proveedor (¡Importante!)
- Obteniendo nuestro widget para actualizar en clic (sin un servicio!)
Paso 1: configure nuestro AppWidgetProvider
No voy a pasar por los detalles de la creación de la información del archivo xml o cambios en el manifiesto de Android – si no sabes cómo crear un widget correctamente, entonces hay un montón de tutoriales que hay que leer primero.
Aquí hay un ejemplo de la clase AppWidgetProvider
:
public class MyWidgetProvider extends AppWidgetProvider { public static final String WIDGET_IDS_KEY ="mywidgetproviderwidgetids"; public static final String WIDGET_DATA_KEY ="mywidgetproviderwidgetdata"; } @Override public void onReceive(Context context, Intent intent) { if (intent.hasExtra(WIDGET_IDS_KEY)) { int[] ids = intent.getExtras().getIntArray(WIDGET_IDS_KEY); if (intent.hasExtra(WIDGET_DATA_KEY)) { Object data = intent.getExtras().getParcelable(WIDGET_DATA_KEY); this.update(context, AppWidgetManager.getInstance(context), ids, data); } else { this.onUpdate(context, AppWidgetManager.getInstance(context), ids); } } else super.onReceive(context, intent); } @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { update(context, appWidgetManager, appWidgetIds, null); } //This is where we do the actual updating public void update(Context context, AppWidgetmanager manager, int[] ids, Object data) { //data will contain some predetermined data, but it may be null for (int widgetId : ids) { . . //Update Widget here . . manager.updateAppWidget(widgetId, remoteViews); } }
Paso 2 – Envío de la emisión
Aquí podemos crear un método estático que hará que nuestros widgets se actualicen. Es importante que usemos nuestras propias claves con la acción de actualización del widget, si usamos AppWidgetmanager.EXTRA_WIDGET_IDS no solo romperemos nuestro propio widget, sino también otros.
public static void updateMyWidgets(Context context, Parcelable data) { AppWidgetManager man = AppWidgetManager.getInstance(context); int[] ids = man.getAppWidgetIds( new ComponentName(context,MyWidgetProvider.class)); Intent updateIntent = new Intent(); updateIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE); updateIntent.putExtra(MyWidgetProvider.WIDGET_ID_KEY, ids); updateIntent.putExtra(MyWidgetProvider.WIDGET_DATA_KEY, data); context.sendBroadcast(updateIntent); }
Si utiliza este método con varios proveedores Asegúrese de que utilizan diferentes claves. De lo contrario, puede encontrar widget a código de actualización del widget b y que puede tener algunas consecuencias extrañas.
Paso 3: actualizar al hacer clic
Otra cosa agradable de hacer es conseguir nuestro widget actualizar magiacally cada vez que se hace clic. Agregue el código siguiente al método de actualización para lograr esto:
RemoteViews views = new RemoteViews(context.getPackageName(),R.layout.mywidget_layout); Intent updateIntent = new Intent(); updateIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE); updateIntent.putExtra(myWidgetProvider.WIDGET_IDS_KEY, ids); PendingIntent pendingIntent = PendingIntent.getBroadcast( context, 0, updateIntent, PendingIntent.FLAG_UPDATE_CURRENT); views.setOnClickPendingIntent(R.id.view_container, pendingIntent);
Este código hará que el método onUpdate sea llamado cada vez que se hace clic en el widget.
Notas
- Cualquier llamada a updateWidgets () hará que todas las instancias de nuestro widget se actualicen.
- Al hacer clic en el widget, todas las instancias de nuestro widget se actualizarán
- NO SE NECESITA SERVICIO
- Por supuesto, tenga cuidado de no actualizar a menudo – las actualizaciones de widget usan la energía de la batería.
- Tenga en cuenta que la difusión es recibida por TODOS los proveedores de widgets y sus claves especiales que garantizan que solo nuestros widgets se actualicen.
Lo siento al OP por una respuesta tardía, pero para cualquier otra persona, puedes usar un método como este para actualizar todos los widgets de tu aplicación de un tipo en particular (diseño y clase):
public static void updateAllWidgets(final Context context, final int layoutResourceId, final Class< ? extends AppWidgetProvider> appWidgetClass) { RemoteViews remoteViews = new RemoteViews(context.getPackageName(), layoutResourceId); AppWidgetManager manager = AppWidgetManager.getInstance(context); final int[] appWidgetIds = manager.getAppWidgetIds(new ComponentName(context, appWidgetClass)); for (int i = 0; i < appWidgetIds.length; ++i) { manager.updateAppWidget(appWidgetIds[i], remoteViews); } }
Lo que hace es crear una RemoteViews
para su diseño y luego se apodera de la AppWidgetManager
y encuentra todos los widgets de la aplicación para la clase que proporcionó, itera sobre ellos y los actualiza.
Cada vez que se trata de tipos es bastante fácil simplemente trabajar con la estática. Y, si lo que deseas es que sucedan cosas específicas basadas en un "disparador", siempre recomendaría la programación basada en eventos … Los intentos son esencialmente el "evento" predeterminado en Android (para pasar datos en tu evento, asegúrate de que el objeto implemente La interfaz Parcelable).
Hay muchos muchos ejemplos de estos conceptos en los diversos foros y documentación de SDK.
- Botón de radio con imagen como opción en lugar de texto
- Cómo utilizar múltiples MapActivities / MapViews por aplicación / proceso de Android