2010-12-08 11 views
18

Tengo algunos problemas con mis widgets. Aquí está la descripción:Widget no eliminado al pasar RESULT_CANCELED como resultado de la actividad de configuración

Contexto:

tengo un widget casa.

Cuando lo agrego, aparece una actividad de configuración para establecer 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 principal.

Si elimino el widget arrastrándolo a la papelera de reciclaje, public void onDeleted (contexto Contexto, int []) appWidgetIds de mi clase AppWidgetProvider obtiene la llamada. Hasta ahora todo bien.

Problema: Si la actividad de configuración finaliza con código de resultado RESULT_CANCELED (setResult (RESULT_CANCELED);), public void onDeleted (contexto Contexto, Int appWidgetIds []) de mi clase AppWidgetProvider no se llama y el widget permanece en la lista de widgets activos. Cuando reinicio el teléfono, onUpdate (Context context, AppWidgetManager appWidgetManager, int [] appWidgetIds) de mi clase AppWidgetProvider se llama y en int [] appWidgetIds tengo todos los widgets (los ids) que se supone que se cancelarán (eliminados antes de ser agregado) + los activos (los que realmente se muestran en Inicio). Los widgets que se eliminaron al arrastrar a la papelera no se muestran en esta lista. Con el tiempo, esta lista de identificadores de widgets se hace cada vez más grande si el usuario cancela la actividad de configuración.

dice La referencia de la API algo como:. "Si regresa RESULT_OK usando Activity.setResult(), se añadirá el AppWidget, y recibirá una emisión ACTION_APPWIDGET_UPDATE para este AppWidget Si regresa RESULT_CANCELED, el anfitrión, se cancelará agregue y no muestre este AppWidget, y recibirá una transmisión ACTION_APPWIDGET_DELETED ".

¿Alguien puede darme algunas pistas sobre esto? Gracias.

Aquí está mi manifiesta:

<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ó más arriba (y no tengo permiso para publicarlo).

+1

Parece que tengo el problema documentado aquí: http://code.google.com/p/android/issues/detail?id=2539 – FiDo

Respuesta

8

¿Estás seguro de que tu código no es relevante? Todo en su manifiesto está fuera del libro y se ve bien. El código debería ser muy similar a este:

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(); 
} 

El putExtra se requiere para decirle al sistema operativo el cual widget no está creando ... El acabado se requiere para cerrar correctamente. Si no lo tiene, no obtendrá la intención de pasar 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 de fantasma. Incluso con un código perfecto, si el usuario pulsa 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. Es por eso que los llamo fantasmas.Una vez que un widget ha completado con éxito la configuración, invocará onDeleted cuando se elimine de la pantalla de inicio. Te queda el problema de que, si se han creado fantasmas, onDisabled nunca se ejecutará.

Un último control. Desde que se ejecuta config, tiene lo siguiente en su archivo info xml. Pero por si acaso, que se parece a esto:

android:configure=your.package.name.ConfigurationActivity" 
+0

Esta es la única y verdadera respuesta correcta :) No hay necesidad de compartirPreferencias lío , todo lo que necesitaba era pasar el appWidgetId en el Intento. Gracias ! –

+0

¡Excelente respuesta! Hoy traté de aprender AppWidgetHost y AppWidget, y me encontré con este tutorial: http://leonardofischer.com/hosting-android-widgets-my-appwidgethost-tutorial/ - tal vez el error no está en el SDK de Google, puede estar en el AppWidgetHost personalizado dentro del Iniciador de la 3ª fiesta: los desarrolladores pueden olvidarse de eliminar el AppWidget, que es simplemente "Cancelado" (el usuario vuelve a presionar sobre la actividad de configuración).Consulte el párrafo "Configuración del widget" en el tutorial anterior – hungson175

+0

Esto no es una solución y no está documentado, eso es lo que dice sobre la cancelación de la configuración: cuando la actividad de configuración se abre por primera vez, establezca el resultado de la actividad en RESULT_CANCELED. De esta forma, si el usuario se retracta de la actividad antes de llegar al final, se notifica al host del widget de la aplicación que la configuración se canceló y no se agregará el widget de la aplicación, aquí: http://developer.android.com/guide /topics/appwidgets/index.html – 3c71

13

tenía este mismo problema, lo hice en el caso onPause

public void removeWidget(int appWidgetId) { 
    AppWidgetHost host = new AppWidgetHost(Config.this, 1); 
    host.deleteAppWidgetId(appWidgetId); 
} 

comprobado los identificadores de widgets, se elimina el widget. La identificación del 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 permiso clic, me puse la canceled falsa

+0

+1 Primera respuesta decente. En el futuro, podría mostrar un poco más de contexto en los fragmentos de código (por ejemplo, mostrar la declaración del método onPause() en lugar de escribir "en el evento onPause"). – cdhabecker

+0

¿por qué en el evento onPause? ¿Y cómo sabes qué Ids son fantasmas y, por lo tanto, hay que eliminar? – MrJre

+0

Buena solución, de hecho, pero falla cuando no hay espacio para el widget en la pantalla de inicio. – Spiff

0

He resuelto este problema como este,

en el método del proveedor widget de onUpdate() puedo comprobar si el widget se ha configurado, y si no era yo no hago nada, entonces no hay widgets de fantasmas. Al final de la configuración, simplemente lo configuré como verdadero y estoy listo para continuar. Simplemente no olvides eliminarlo de la preferencia compartida 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); 

    } 


} 
0

Parece haber muchos problemas con los widgets desde hace mucho tiempo. Eso dijo mientras buscaba una solución para uno de ellos, me encontré 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 el actividad de configuración.

Es completamente transparente para el usuario y se dice que soluciona el problema "agregar/zombie widget". Lo intentaré ahora.


Sin embargo, no resuelve el problema con los widgets eliminados en proceso de actualización en el arranque, a pesar de que parece haber sido fijado en los últimos versiones de Android (4.4+ no está seguro de cuál?).

En las versiones anteriores de Android, observé que todos los widgets que eliminé manualmente del iniciador se transforman en zombies al reiniciar, el sistema operativo llamó efectivamente a Update para cada uno de esos widgets, por lo tanto tuve que mantener una lista de widgets eliminados .

Ahora los ID de widget eliminados se vuelven a utilizar para los nuevos widgets, por lo que tengo que dejar de seguir los widgets eliminados. Lamentablemente, no tengo idea de cuándo (qué versión de Android) se solucionó este problema y cómo los identificadores comenzaron a volverse a usar.

Cuestiones relacionadas