¿Notificación para restaurar una tarea en lugar de una actividad específica?

Tengo un servicio de primer plano que mantiene una conexión abierta con el servidor siempre que el usuario inicie sesión en la aplicación. Esto es para que la conexión se mantenga activa y pueda recibir mensajes directamente del servidor, incluso cuando el usuario haya enviado la aplicación a segundo plano presionando Inicio.

La aplicación tiene una serie de Actividades, cualquiera de las cuales podría ser la activa cuando se envíe a segundo plano.

Me gustaría permitir que el usuario haga clic en la notificación para restaurar la Actividad actual. Entiendo cómo restaurar una actividad en particular, pero me pregunto si hay una forma de restaurar la última actividad en la que estaba el usuario. Por supuesto, podría hacer un seguimiento de la última, y ​​luego llamar a eso desde la callback de notificación, pero pensé que podría haber una forma en un nivel de tarea.

Gracias por cualquier consejo que pueda ofrecer.

Lo que necesitas es simplemente una actividad simple que no hace nada. Aquí hay un ejemplo:

public class NotificationActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Now finish, which will drop the user in to the activity that was at the top // of the task stack finish(); } } 

Configura tu notificación para comenzar esta actividad. Asegúrese de que en el manifiesto la afinidad de tarea de esta actividad sea la misma que la afinidad de tarea de las otras actividades en su aplicación (de manera predeterminada, si no ha configurado explícitamente android: taskAffinity ).

Cuando el usuario selecciona esta notificación, si su aplicación se está ejecutando, entonces la actividad de notificación se iniciará en la parte superior de la actividad más alta en la tarea de su aplicación y esa tarea se pondrá en primer plano. Cuando la actividad de notificación finalice, simplemente devolverá al usuario a la actividad más alta en su aplicación (es decir: donde el usuario la dejó cuando se quedó en segundo plano).

Esto no funcionará si su aplicación no se está ejecutando. Sin embargo, tienes 2 opciones para lidiar con eso:

  1. Asegúrese de que la notificación no esté presente en la barra de notificaciones cuando su aplicación no se esté ejecutando.

  2. En el método onCreate () de NotificationActivity, compruebe si su aplicación se está ejecutando y, si no se está ejecutando, llame a startActivity () e inicie su aplicación. Si hace esto, asegúrese de configurar el indicador Intent.FLAG_ACTIVITY_NEW_TASK al iniciar la aplicación para que la actividad raíz de la tarea no sea NotificationActivity.

Funciona muy bien, gracias David! La siguiente clase verifica si la aplicación ya se está ejecutando y si no, la inicia antes de finalizar (como sugirió David en la opción 2).

 public class NotificationActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // If this activity is the root activity of the task, the app is not running if (isTaskRoot()) { // Start the app before finishing Intent startAppIntent = new Intent(getApplicationContext(), MainActivity.class); startAppIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(startAppIntent); } finish(); } } 

Hay una solución más simple que no requiere la actividad adicional. Ver esta publicación para más detalles. Básicamente, la notificación inicia la tarea (posiblemente existente) de la misma manera que se inicia al hacer clic en el icono del iniciador mientras la aplicación está en segundo plano.

Mi solución, que emula el comportamiento del iniciador (llevando la tarea al primer plano):

 Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_LAUNCHER); intent.setClassName(MyApplication.class.getPackage().getName(), MainActivity.class.getName()); 
 Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_LAUNCHER); 

Esto funciona, no hay dudas al respecto, pero el problema es cuando configuras tu bash como ACTION_MAIN. Entonces no podrás configurar ningún paquete para la intención. Es decir, tus datos primitivos no se recibirán de la actividad objective porque ACTION_MAIN no puede contener datos adicionales.

En lugar de esto, puede simplemente configurar sus actividades como singleTask y llamar a su intención normalmente sin establecer ACTION_MAIN y recibir el bash del método onNewIntent () de su actividad objective.

Pero tenga cuidado si llama, super.onNewIntent (intención); luego se creará una segunda instancia de la actividad. Simplemente no llame a supermétodo.