programacion - tipos de widgets android studio
El widget no se eliminó al pasar RESULTADO_CANCELADO como resultado de la actividad de configuración (4)
Tengo algunos problemas con mis widgets. Aquí está la descripción:
Contexto:
Tengo un widget de casa.
Cuando lo agrego, aparece una Actividad de configuración para configurar algunos parámetros para el widget.
Si llamo a setResult (RESULT_OK, resultValue); Antes de finalizar la actividad de configuración, el widget se agrega a la página de inicio.
Si elimino el widget arrastrándolo a la papelera, se llamará public void onDeleted (Context context, int [] appWidgetIds) de mi clase AppWidgetProvider. Hasta ahora tan bueno.
Problema: si la actividad de configuración sale con el código de resultado RESULT_CANCELED ( setResult (RESULT_CANCELED); ), no se llamará público anulado onDeleted (Context context, int [] appWidgetIds) de mi clase AppWidgetProvider y el widget permanece en la lista de widgets activos. Cuando reinicio el teléfono, onUpdate (contexto contextual, AppWidgetManager appWidgetManager, int [] appWidgetIds) de mi clase AppWidgetProvider se llama y en int [] appWidgetIds tengo todos los widgets (los identificadores) que se supone que se deben cancelar (eliminar antes de agregarlos) + los activos (los que realmente se muestran en Inicio). Los widgets que se eliminaron al arrastrarlos a la papelera no se muestran en esta lista. Con el tiempo, esta lista de identificadores de widgets sigue creciendo cada vez más si el usuario cancela desde la Actividad de configuración.
La referencia de la API dice algo como: "Si devuelves RESULT_OK con Activity.setResult (), se agregará el AppWidget, y recibirás una emisión ACTION_APPWIDGET_UPDATE para este AppWidget. Si regresas RESULT_CANCELED, el anfitrión cancelará el agregado y no se mostrará este AppWidget, y recibirás una difusión ACTION_APPWIDGET_DELETED ".
¿Alguien puede darme algunos consejos sobre esto? Gracias.
Aquí está mi manifiesto:
<application android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="true">
<receiver android:name=".MytWidget" android:label="@string/app_name">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/my_widget_provider" />
</receiver>
<activity android:name=".ConfigurationActivity">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
</intent-filter>
</activity>
</application>
El resto del código no es relevante ya que se explicó anteriormente (y no tengo permiso para publicarlo).
¿Estás seguro de que tu código no es relevante? Todo en tu manifiesto está fuera del libro y se ve bien. Tu código debería ser muy similar a esto:
public void configCancelOnClick(View v) {
MyLog.d(TAG, "configCancelOnClick");
Intent intent = new Intent();
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
setResult(RESULT_CANCELED, intent);
finish();
}
Se requiere putExtra para indicar al sistema operativo qué widget no está creando ... Se requiere que el acabado se cierre correctamente. Si no lo tiene, no podrá pasar la intención al sistema operativo correctamente y perderá el setResult.
Finalmente, cuando config no sale correctamente (tecla de retroceso, tecla de inicio o código incorrecto), se crea un widget fantasma. Incluso con el código perfecto, si el usuario presiona la tecla de inicio mientras está en la configuración, tendrá un widget en cola para el sistema que realmente no existe en ninguna pantalla de inicio. Por eso los llamo fantasmas. Una vez que un widget haya completado con éxito la configuración, invocará onDeleted cuando se elimine de la pantalla de inicio. Queda con el problema de que, si se han creado fantasmas, onDisabled nunca se ejecutará.
Una última comprobación. Desde que se ejecuta la configuración, tiene lo siguiente en su archivo de información xml. Pero por si acaso, se ve así:
android:configure=your.package.name.ConfigurationActivity"
Parece que hay muchos problemas con los widgets desde las edades. Dicho esto, mientras buscaba una solución para uno de ellos, me topé con esta publicación: https://code.google.com/p/android/issues/detail?id=2539#c15
Básicamente, la idea es eliminar la actividad de configuración de la aplicación del manifiesto y verificar durante onUpdate si el widget se ha configurado, si no se abre la actividad de configuración.
Es completamente transparente para el usuario y se dice que soluciona el problema del "widget agregar / zombie". Intentaré eso ahora.
Sin embargo, no resuelve el problema con los widgets eliminados que se actualizan al reiniciar, a pesar de que parece haber sido corregido en las últimas versiones de Android (¿4.4+ no estoy seguro de cuál?).
En versiones anteriores de Android, observé que todos los widgets que he eliminado manualmente del lanzador se transforman en zombies al reiniciar, el sistema operativo que invoca OnUpdate para cada uno de esos widgets, por lo que tuve que mantener una lista de widgets eliminados.
Ahora, los ID de widget eliminados se reutilizan para los nuevos widgets, así que tengo que dejar de rastrear los widgets eliminados Lamentablemente, no tengo ni idea de cuándo (qué versión de Android) se solucionó este problema y las identificaciones comenzaron a reutilizarse.
Resolví este problema de esta manera,
En el método onUpdate () del proveedor del widget, compruebo si el widget está configurado y, si no lo está, no hago nada, por lo que no hay widgets fantasma. Al final de la configuración, simplemente lo puse en verdadero y estoy listo. Simplemente no olvide eliminarlo de sharedpreference cuando se elimine el widget.
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
{
super.onUpdate(context, appWidgetManager, appWidgetIds);
for(final int appWidgetId : appWidgetIds)
{
final StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(appWidgetId);
stringBuilder.append("_conf");
if(context.getSharedPreferences("settings",0).getBoolean(stringBuilder.toString(),false))
updateAppWidget(context,appWidgetId,appWidgetManager);
}
}
Tuve este mismo problema, hice esto en el evento onPause
public void removeWidget(int appWidgetId) {
AppWidgetHost host = new AppWidgetHost(Config.this, 1);
host.deleteAppWidgetId(appWidgetId);
}
Comprobado los identificadores del widget, el widget se elimina. El ID de host no es importante si solo tiene un host de widget de aplicación.
private boolean canceled = true;
@Override
protected void onPause() {
if(canceled) {
removeWidget(appWidgetId);
}
super.onPause();
}
En el clic OK, establezco el falso canceled