Clic di notifica: attività già aperta


164

Ho un'applicazione con notifiche che aprono una determinata attività se faccio clic su di esse. Voglio che, se faccio clic sulla notifica e l'attività è già aperta, non viene riavviata, ma appena portata in primo piano.

Pensavo di poterlo fare con la bandiera FLAG_ACTIVITY_BROUGHT_TO_FRONTo FLAG_ACTIVITY_REORDER_TO_FRONT, ma continua ad aprirlo di nuovo, quindi ho l'attività due volte.

Questo è il mio codice:

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

Posso gestirlo con flag o devo archiviare una variabile in SharedPreferences per verificare se è aperto o no?

Grazie!


1
Uso intent.setFlags (Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NO_HISTORY);
ashraful

Risposte:


298

Devi impostare l' launchModeattributo di Activitycui stai iniziando singleTop. Ciò farà in modo che gli Intenti in arrivo vengano consegnati all'istanza esistente anziché avviare una nuova istanza quando si Activitytrova già nella parte superiore dello stack dell'attività.

Questo viene fatto nel manifesto aggiungendo android:launchMode="singleTop"al <activity>elemento. Per accedere all'intento più recente (se sei interessato a dati che potrebbero essere passati con esso), sovrascrivi il onNewIntent()tuo Activity.


6
Ho incontrato molte risposte che dicevano impostare la bandiera dell'intento su varie cose. Questo non ha funzionato. Questo perché l'intento, indipendentemente dalla sua bandiera, sta per un'attività appena creata? Chiedo perché Devunwired ha detto che l'attributo launchMode cambia dove vengono consegnati gli Intenti.
lululoo

5
La pagina della documentazione è su developer.android.com/guide/topics/manifest/…
Mifeng il

1
Vedo che se usi questo approccio sull'attività avviata dalla schermata principale, ogni volta che avvii l'applicazione inizierà con l'attività di root, distruggendo tutte le attività precedentemente visualizzate in alto. Questo non è certamente un comportamento previsto per un utente che mette l'app in background mentre si trova in un'altra attività e la riapre.
Tedesco,

38

Prova invece a impostare le bandiere Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP.

Dalla documentazione per FLAG_ACTIVITY_CLEAR_TOP (sottolineatura mia):

Se impostato e l'attività in corso è già in esecuzione nell'attività corrente, quindi invece di avviare una nuova istanza di tale attività, tutte le altre attività al di sopra di essa verranno chiuse e questo Intento verrà consegnato al (ora in alto) vecchia attività come nuovo Intento.

Ad esempio, considera un'attività consistente nelle attività: A, B, C, D. Se D chiama startActivity () con un Intento che si risolve nel componente dell'attività B, allora C e D saranno finiti e B riceverà l'intento dato , per cui lo stack ora è: A, B.

L'istanza attualmente in esecuzione dell'attività B nell'esempio sopra o riceverà il nuovo intento che si sta iniziando qui nel suo metodo onNewIntent (), oppure sarà esso stesso terminato e riavviato con il nuovo intento. Se ha dichiarato che la sua modalità di avvio è "multipla" (impostazione predefinita) e non hai impostato FLAG_ACTIVITY_SINGLE_TOP nello stesso intento, verrà terminata e ricreata; per tutte le altre modalità di avvio o se è impostato FLAG_ACTIVITY_SINGLE_TOP, questo intento verrà consegnato all'istanza corrente su NewIntent ().


1
Questo è quello di cui avevo bisogno. Basta aggiungere una descrizione che abbiamo bisogno di aggiungere questo bandiere per intenti: new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP).
Morteza Rastgoo,

6

Utilizzare onNewIntent()per gestire i nuovi dati dal clic di notifica e aggiornare l'attività.

Per onNewIntentottenere i nuovi dati dal nuovo intento (che è servito dalla nuova notifica) e catturarli, ad esempio:

title = intent.getStringExtra("title")

in onCreateprecedenza :)

Aggiorna l'attività attuale con nuovi dati di notifica.

Puoi anche seguire questo tutorial.


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

Basta copiare il codice e incollarlo nella tua attività di avvio principale.

Ecco la risposta originale


0

Penso che dovresti aggiungere un po 'di logica per farlo funzionare, forse questo può aiutare:

Ad esempio ho una schermata iniziale (Launcher e MAIN) di APP:

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

    }

}

E nel mio FirebaseService ho fatto quanto segue:

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

    }

}

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

4
Spiegare in che modo il codice aiuta a risolvere il problema menzionato nella domanda. Questo potrebbe non essere ovvio per gli altri lettori che affrontano gli stessi problemi / simili.
NOh,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.