181 votes

Clic de notification : activité déjà ouverte

J'ai une application avec des notifications qui ouvrent une certaine activité si je clique dessus. Je veux que, si je clique sur la notification et que l'activité est déjà ouverte, ce soit no recommencé, mais juste amené à l'avant.

Je pensais que je pouvais le faire avec le drapeau FLAG_ACTIVITY_BROUGHT_TO_FRONT o FLAG_ACTIVITY_REORDER_TO_FRONT mais il continue à l'ouvrir à nouveau, ce qui fait que j'ai l'activité deux fois.

Voici mon code :

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

Puis-je le gérer avec des drapeaux ou dois-je stocker une variable dans SharedPreferences pour vérifier s'il est ouvert ou non ?

Merci !

1 votes

J'utilise intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP|Intent.FLAG_ACTIVITY_NO_HISTORY ) ;

317voto

Devunwired Points 27023

Vous devez définir le launchMode de l'attribut Activity vous commencez à singleTop . Ainsi, les intents entrants seront livrés à l'instance existante plutôt que de démarrer une nouvelle instance lorsque l'intent est en cours. Activity est déjà au sommet de la pile de la tâche.

Ceci est fait dans le manifeste en ajoutant android:launchMode="singleTop" à la <activity> élément. Pour accéder au dernier Intent (si vous êtes intéressé par les données qui ont pu être transmises avec lui), remplacez onNewIntent() dans votre Activity .

6 votes

Je suis tombé sur de nombreuses réponses qui disaient de définir le drapeau de l'intention à diverses choses. Cela n'a pas fonctionné. Est-ce parce que l'intention, indépendamment de son drapeau, va vers une activité nouvellement créée ? Je demande parce que Devunwired a dit que l'attribut launchMode change l'endroit où les intentions sont livrées.

5 votes

La page de documentation se trouve à l'adresse suivante developer.Android.com/guide/topics/manifest/

1 votes

Je constate que si vous utilisez cette approche sur l'activité lancée à partir de l'écran d'accueil, chaque fois que vous lancerez l'application, elle commencera par l'activité racine, détruisant toutes les activités qui étaient précédemment affichées en haut. Ce n'est certainement pas le comportement attendu d'un utilisateur qui met l'application en arrière-plan alors qu'il est dans une autre activité et qui la rouvre.

41voto

user113215 Points 4402

Essayez de mettre les drapeaux à Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP à la place.

Desde el documentation pour FLAG_ACTIVITY_CLEAR_TOP (c'est moi qui souligne) :

S'il est défini, et que l'activité en cours de lancement est déjà en cours d'exécution dans le système de gestion de l'information. tâche actuelle, au lieu de lancer une nouvelle instance de cette activité activité, toutes les autres activités situées au-dessus seront fermées et l'activité en cours de lancement est déjà en cours d'exécution dans la tâche actuelle. nouvel Intent.

Par exemple, considérons une tâche composée des activités : A, B, C, D. Si D appelle startActivity() avec une Intent qui se résout à la composante de l'activité B, alors C et D seront terminés et B recevra la tâche. composant de l'activité B, alors C et D seront terminés et B recevra l'intention donnée. l'Intent donné, ce qui fait que la pile est maintenant composée de : A, B.

L'instance de l'activité B en cours d'exécution dans l'exemple ci-dessus sera soit recevoir la nouvelle intention que vous lancez ici dans sa méthode onNewIntent(), ou bien elle sera elle-même terminée et redémarrée avec la nouvelle intention. Si elle a déclaré que son mode de lancement est "multiple" (la valeur par par défaut) et que vous n'avez pas défini FLAG_ACTIVITY_SINGLE_TOP dans la même même intention, il sera terminé et recréé ; pour tous les autres modes de lancement ou de lancement ou si FLAG_ACTIVITY_SINGLE_TOP est défini, alors cette intention sera livrée à la onNewIntent() de l'instance actuelle.

1 votes

C'est ce dont j'avais besoin. Il suffit d'ajouter une description que nous avons besoin d'ajouter ces drapeaux à l'intention : new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP) .

7voto

Utilice onNewIntent() pour traiter les nouvelles données provenant du clic de notification et rafraîchir l'activité.

En onNewIntent obtenir les nouvelles données de la nouvelle intention (qui est servie par la nouvelle notification) et les attraper, par exemple :

title = intent.getStringExtra("title")

sur onCreate précédemment :)

Il rafraîchira l'activité actuelle avec les nouvelles données de notification.

Vous pouvez également suivre ce tutoriel.

6voto

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

Copiez simplement le code et collez-le dans l'activité principale de votre lanceur.

Voici la réponse originale

0voto

Je pense que vous devriez ajouter une certaine logique pour que cela fonctionne, peut-être que ceci peut aider :

Par exemple, j'ai un Splash Screen (Launcher et MAIN) de 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);
        }

    }

}

Et dans mon FirebaseService, j'ai fait ce qui suit :

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

    }

}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X