Clic de notificación: actividad ya abierta

164

Tengo una aplicación con notificaciones que abren una determinada actividad si hago clic en ellas. Quiero eso, si hago clic en la notificación y la actividad ya está abierta, no se inicia de nuevo, sino que se pone al frente.

Pensé que podría hacerlo con la bandera FLAG_ACTIVITY_BROUGHT_TO_FRONTo FLAG_ACTIVITY_REORDER_TO_FRONT, pero sigue abriéndola nuevamente, así que tengo la actividad dos veces.

Este es mi código:

event_notification = new Notification(R.drawable.icon,
            mContext.getString(R.string.event_notif_message), System.currentTimeMillis()); 
Intent notificationIntent = new Intent(mContext, EventListActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
sendNotification(event_notification, notificationIntent, mContext.getString(R.string.event_notif_title),
                body, Utils.PA_NOTIFICATIONS_ID);

¿Puedo administrarlo con banderas o debo almacenar una variable en SharedPreferences para verificar si está abierta o no?

¡Gracias!

Desarrollador PX
fuente
1
Yo uso intent.setFlags (Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NO_HISTORY);
ashraful

Respuestas:

298

Debe establecer el launchModeatributo del Activityque está comenzando singleTop. Esto hará que los intentos entrantes se entreguen a la instancia existente en lugar de comenzar una nueva instancia cuando Activityya está en la parte superior de la pila de la tarea.

Esto se hace en el manifiesto agregando android:launchMode="singleTop"al <activity>elemento. Para acceder a la última intención (si está interesado en algún dato que pueda haber pasado), anule onNewIntent()en su Activity.

Devunwired
fuente
66
Me encontré con muchas respuestas que decían establecer la bandera de la intención a varias cosas. Esto no funcionó. ¿Es esto porque la intención, independientemente de su bandera, es ir a una actividad recién creada? Pregunto porque Devunwired dijo que el atributo launchMode cambia donde se entregan los Intentos.
lululoo
55
La página de documentación está en developer.android.com/guide/topics/manifest/…
Mifeng
1
Veo que si usa este enfoque en la actividad que se inicia desde la pantalla de inicio, cada vez que inicie la aplicación comenzará con la actividad raíz, destruyendo cualquier actividad que se mostrara anteriormente en la parte superior. Ciertamente, este no es un comportamiento esperado para un usuario que pone la aplicación en segundo plano mientras está en una actividad diferente y la vuelve a abrir.
Alemán
38

Intenta configurar las banderas en su Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOPlugar.

De la documentación para FLAG_ACTIVITY_CLEAR_TOP (el énfasis es mío):

Si se establece, y la actividad que se está iniciando ya se está ejecutando en la tarea actual, en lugar de iniciar una nueva instancia de esa actividad, todas las demás actividades se cerrarán y esta intención se entregará al (ahora en arriba) actividad anterior como una nueva intención.

Por ejemplo, considere una tarea que consta de las actividades: A, B, C, D. Si D llama a startActivity () con un Intento que resuelve el componente de la actividad B, entonces C y D finalizarán y B recibirá el Intento dado , dando como resultado que la pila ahora sea: A, B.

La instancia actualmente en ejecución de la actividad B en el ejemplo anterior recibirá la nueva intención que está comenzando aquí en su método onNewIntent (), o se terminará y reiniciará con la nueva intención. Si ha declarado que su modo de inicio es "múltiple" (el valor predeterminado) y no ha configurado FLAG_ACTIVITY_SINGLE_TOP en la misma intención, se finalizará y se volverá a crear; para todos los demás modos de inicio o si FLAG_ACTIVITY_SINGLE_TOP está configurado, esta intención se entregará a la instancia actual onNewIntent ().

quietmint
fuente
1
Esto es lo que necesitaba. Sólo tiene que añadir una descripción que tenemos que añadir esta imagen Indicadores de la intención: new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP).
Morteza Rastgoo
6

Úselo onNewIntent()para manejar nuevos datos de notificaciones, haga clic y actualice la actividad.

Para onNewIntentobtener los nuevos datos de la nueva intención (que sirve la nueva notificación) y capturarlos, por ejemplo:

title = intent.getStringExtra("title")

en onCreateanteriormente :)

Actualizará la actividad actual con nuevos datos de notificación.

También puedes seguir este tutorial.

Afjalur Rahman Rana
fuente
3
Notification.Builder mBuilder =
            new Notification.Builder(this)
            .setSmallIcon(R.drawable.cmplayer)
            .setContentTitle("CoderoMusicPlayer")
            .setContentText("PLayer0!");

    Intent resultIntent = new Intent(this, 

    AndroidBuildingMusicPlayerActivity.class);
        resultIntent.setAction(Intent.ACTION_MAIN);
        resultIntent.addCategory(Intent.CATEGORY_LAUNCHER);

        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
                resultIntent, 0);

        mBuilder.setContentIntent(pendingIntent);
        NotificationManager mNotificationManager =
            (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        mNotificationManager.notify(1, mBuilder.build());

Simplemente copie el código y péguelo en su actividad principal de iniciador.

Aquí está la respuesta original

Comunidad
fuente
0

Creo que debería agregar algo de lógica para que funcione, tal vez esto pueda ayudar:

Por ejemplo, tengo una pantalla de inicio (Iniciador y PRINCIPAL) de la APLICACIÓN:

public class SplashScreen extends AppCompatActivity {
    private final int TIME_OUT = 2000;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_splash_screen);

        // Suscribirse al tema Notificaciones
        FirebaseMessaging.getInstance().subscribeToTopic("NOTA");
        if (getIntent().getExtras() != null) {
            if (getIntent().getExtras().size()>1){
                Intent home_activity = new Intent(getApplicationContext(), Home.class);
                home_activity.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                if (getIntent().getExtras() != null) {
                    for (String key : getIntent().getExtras().keySet()) {
                        String value = "" + getIntent().getExtras().getString(key);
                        Log.d("TAG", key + "=" + value);
                        switch (key) {
                            case "url":
                                home_activity.putExtra("url", value);
                                break;
                        }
                    }
                }
                startActivity(home_activity);
                finish();

            }else{
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            Intent home_activity = new Intent(getApplicationContext(), Home.class);
                            home_activity.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                            startActivity(home_activity);
                            finish();
                        } catch (Exception ex) {
                            ex.printStackTrace();
                        }
                    }
                }, TIME_OUT);
            }


        } else {
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    try {
                        Intent home_activity = new Intent(getApplicationContext(), Home.class);
                        home_activity.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                        startActivity(home_activity);
                        finish();
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
            }, TIME_OUT);
        }

    }

}

Y en mi FirebaseService he hecho lo siguiente:

public class FCMessagingService extends FirebaseMessagingService {

    private final String TAG = "PUSH";
    private String body = "";
    private static String _url = "";
    private static int numMessage = 0;

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);

        String from = remoteMessage.getFrom();
        Log.d(TAG, "Mensaje recibido de: " + from);

        if (remoteMessage.getNotification() != null) {
            Log.d(TAG, "Notificación: " + remoteMessage.getNotification().getBody());

            if (remoteMessage.getData().size() > 0) {
                Log.d(TAG, "Data: " + remoteMessage.getData());
                try {
                    JSONObject data = new JSONObject(remoteMessage.getData());
                    String url = data.getString("url");
                    Log.d(TAG, "onMessageReceived: \n" + "Extra Information: " + url);
                    this._url = url;
                    Log.d("_URL",_url);
                    mostrarNotificacion(remoteMessage.getNotification().getTitle(), remoteMessage.getNotification().getBody());
                    mensaje(url, remoteMessage.getNotification().getTitle(), remoteMessage.getNotification().getBody());
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        }



    }


    private void mensaje(String url, String title, String body){
        boolean acti =  Util.comprobarActivityALaVista(getApplicationContext(), "com.dev.android.subagan.MainActivity");
        if(acti){

            Intent imain = new Intent(MainActivity.URL);

            imain.putExtra("key_url",url);
            imain.putExtra("key_title",title);
            imain.putExtra("key_body",body);

            LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(imain);

        }else{

            Intent ihome = new Intent(Home.URL);

            ihome.putExtra("key_url",url);
            ihome.putExtra("key_title",title);
            ihome.putExtra("key_body",body);
            LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(ihome);

        }

    }




    private void mostrarNotificacion(String title, String body) {

        final int NOTIFICATION_ID = 3000;

        Intent intent = new Intent(this, MainActivity.class);
        intent.putExtra("url",_url);
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);


        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent,PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_ONE_SHOT  );



        Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle(title)
                .setContentText(body)
                .setAutoCancel(true)
                .setSound(soundUri)
                .setTicker(body)
                .setContentIntent(pendingIntent);

        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(0, notificationBuilder.build());

    }

}
Carlos Alberto Gonzalez
fuente
0
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent contentIntent = PendingIntent.getActivity(this, new Random().nextInt(), intent, 0);
Manjunath
fuente
44
Explique cómo su código ayuda a resolver el problema mencionado en la pregunta. Esto podría no ser obvio para otros lectores que enfrentan los mismos problemas / similares.
NOh