2010-08-25 19 views
9

Estoy desarrollando una aplicación con numerosas actividades. Me gustaría crear una notificación persistente que (más o menos) diga, "AppName - Return to AppName" que estará presente cada vez que se ejecuten mis servicios en segundo plano. Crear y eliminar la notificación no fue un problema.Utilizar una notificación persistente para permitir al usuario volver a ejecutar la aplicación de Android

Ahora, el usuario podría estar en cualquiera de varias pantallas/Actividades, salir de la aplicación, y luego querer volver a ingresar a la aplicación a través de la notificación. El problema es, la notificación debe tener un intento, que inicia una actividad predeterminada . Quiero que la notificación vuelva a ingresar a la aplicación en sea cual sea la actividad que se encuentre en la parte superior de la pila del historial.

Mi primer intento de una solución fea fue realizar una actividad (llamémosle "returnFromNotify") cuyo único trabajo fue "terminar" en su "onCreate". La notificación abriría "returnFromNotify" en el ámbito del historial de aplicaciones, que luego se eliminaría automáticamente, enviando al usuario al estado anterior de la pila de la aplicación. Esto parece funcionar ... a menos que el usuario haya utilizado "volver" para salir completamente de la aplicación. Luego, cuando acceden a la notificación, se carga "returnFromNotify" y luego finaliza, enviándolos nuevamente a la pantalla de inicio (ya que no hay actividades en la pila de historial de la aplicación).

Consideré intentar detectar si había algo en la pila de historial antes de "returnFromNotify", y si no, reinicié mi actividad principal. Parece que tampoco puedo encontrar una manera de hacer esto.

¿Alguna entrada o sugerencia para un principiante de Java/Android? FYI, Mi historia principal es con lenguajes basados ​​en scripts.

Respuesta

6

me gusta su idea original de crear una actividad "returnFromNotify" mejor que su solución propuesta, ya que es posible detectar si el ResumeActivity es en la parte inferior de la pila (y por lo tanto la única actividad en la pila) .

Así es como puede hacerlo:

Añadir su ResumeActivity al manifiesto y especificar el atributo noHistory:

<activity android:name=".ResumeActivity" android:noHistory="true" /> 

Especificación noHistory se asegurará de que esta actividad no se quedará en la pila tan pronto cuando termina. De esta forma, sabrá que solo se mostrará una instancia actualmente en ejecución de ResumeActivity en la pila.

Con el fin de comprobar la pila de aplicaciones, también tiene que pedir el permiso GET_TASKS:

<uses-permission android:name="android.permission.GET_TASKS" /> 

Ahora se puede utilizar para determinar si ActivityManager::getRunningTasks() ResumeActivity es la única actividad en la pila:

public class ResumeActivity extends Activity { 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     if(isOnlyActivityInStack()) { //check the application stack 
      //This activity is the only activity in the application stack, so we need to launch the main activity 
      Intent main = new Intent(this, MainActivity.class); 
      main.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
      startActivity(main); 
     } else { 
      //Return the user to the last activity they had open 
      this.finish(); 
     } 
    } 

    /** 
    * Checks the currently running tasks. If this activity is the base activity, we know it's the only activity in the stack 
    * 
    * @return boolean This activity is the only activity in the stack? 
    **/ 
    private boolean isOnlyActivityInStack() { 
     ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); 
     boolean onlyActivityInStack = false; 

     for(RunningTaskInfo tasks : manager.getRunningTasks(Integer.MAX_VALUE)) { 
      if(tasks.baseActivity.getPackageName().equals(this.getPackageName())) { //find this package's application stack 
       if(tasks.baseActivity.getClassName().equals(this.getClass().getName())) { 
        //If the ResumeActivity is the base activity, we know that it is the only activity in the stack 
        onlyActivityInStack = true; 
        break; 
       } 
      } 
     } 

     return onlyActivityInStack; 
    } 

} 

Sé que usted hizo esta pregunta hace más de 2 años, pero estoy proporcionando esta respuesta en caso de que alguien más se encuentre con esta situación en particular (como yo lo hice). Creo que estabas en el camino correcto con la solución para la que originalmente estabas trabajando.

+0

¡Sí! Este proyecto era para un trabajo con el que ya no estoy, así que no lo necesito ... pero parece EXACTAMENTE lo que estaba buscando, ¡así que gracias! Con suerte, alguien más lo encontrará útil también. – Slobaum

3

De acuerdo, creo que he encontrado un trabajo de reparación satisfactorio para mi caso específico. He agregado un entero estático a mi "actividad principal", y cada vez que se activa "onCreate", aumenta el número entero. Cada vez que se activa "onDestroy", disminuye.

En mi "returnFromNotify", miro el entero estático para ver si es mayor que 0. Si es así, supongo que hay una "mainActivity" activa, y que ejecutar "finish" dentro de "returnFromNotify" devolverá ahí. De lo contrario, supone que los usuarios se han "respaldado", que termina, y luego usa "startActivity" para iniciar una nueva instancia de "mainActivity".

Esta no es una solución universal, pero para mi propósito, creo que será suficiente. Todavía estoy abierto a otras respuestas, y si alguien puede hacer un agujero en mi lógica, por favor hágalo así: crítica constructiva es bienvenido. Gracias.

1

supongo que no hay manera fácil de hacer esto, pero en lugar de añadir un contador en la mainActivity que se extendería Application:

Clase base para aquellos que necesitan mantener el estado de aplicación global. Usted puede proporcionar su propia implementación de especificando su nombre en su etiqueta de AndroidManifest.xml , lo que hará que la clase sea instanciado para que cuando el proceso para su aplicación/paquete es creado.

Me gustaría mantener la máxima la lógica allí y tener un método como:

public Intent getIntentForLastActivityShown(); 

que se llamará cuando se hace clic en el elemento de notificación.

+1

¿Cómo utilizarías entonces getIntentForLastActivityShown()? No sería una forma más fácil de mantener un control sobre la notificación en la clase de la Aplicación y luego cada vez que inicie una nueva llamada de intención setLatestEventInfo desde la notificación y actualice el pendiente pendiente a la actividad visible actual. – schwiz

1

Mi primer enfoque sería usar SharedPreferences y almacenar un par de valores clave llamado algo así como lastDisplayedActivity. A continuación, en cada actividad de onResume (y posiblemente `onCreate ') que tendría una línea como esta:

sharedPreferences.edit().putInteger("lastDisplayedActivity", ReturnFromNotify.THIS_ACTIVITY_NAME); 

En otras palabras, usted almacenar una variable de amplia aplicación que indica qué actividad se mostró la última. Luego, simplemente toma esta variable de SharedPreferences e inicia la actividad correspondiente.

+0

No es una mala idea, pero me obligaría a agregar código al ciclo de vida de cada actividad (que prefiero no hacer). Además, ¿el lanzamiento de la actividad correspondiente mantendría el estado de la instancia de actividad anterior o crearía una nueva instancia de esa actividad? Realmente necesito que retenga el estado en el que estaban. – Slobaum

+0

Puede restaurar el estado automáticamente en algunos casos, pero si su actividad no se muestra actualmente, Android * puede matarlo en cualquier momento * para reclamar memoria extra. En otras palabras, si quiere asegurarse de guardar el estado de la Actividad, debe almacenarlo en otro lugar. Existen numerosas formas de hacerlo, pero si tiene una buena cantidad de datos, recomendaría utilizar una base de datos SQLite: http://developer.android.com/guide/topics/data/data-storage.html#db – Computerish

0

Normalmente utilizo la actividad denominada "Iniciador" que comprueba el estado de mi aplicación modelo y comienzo las actividades (u otras cosas) según las reglas del modelo. Puse el objeto Modelo en mi clase de aplicación. El modelo puede usar Preferencias para almacenar su estado. Lo hago para evitar campos estáticos en las actividades.

Cuestiones relacionadas