web-dev-qa-db-fra.com

Activité ouverte sur la notification de base de feu reçue au premier plan

Lorsque mon application est ouverte et que je reçois une notification, je souhaite pouvoir ouvrir l'activité associée immédiatement sans que l'utilisateur ait besoin d'appuyer sur la notification. 

Cette question est très similaire: Application ouverte sur la notification firebase reçue (FCM)

Mais il ouvre l'application quand il est en arrière-plan, je dois le faire quand mon application est au premier plan.

À partir de documentation firebase :

Notifications livrées lorsque votre application est en arrière-plan. Dans ce Dans ce cas, la notification est transmise à la barre système du périphérique. UNE L'utilisateur tapant sur une notification ouvre le lanceur d'applications par défaut. Messages avec à la fois des notifications et des données utiles, à la fois en arrière-plan et premier plan. Dans ce cas, la notification est remise au dans la barre d'état système de l'appareil et la charge de données est fournie dans les extras de l'intention de votre activité de lanceur.

Ceci est mon implémentation de onMessageReceived

@Override
    public void onMessageReceived(RemoteMessage remoteMessage) {

       // Check if message contains a data payload.
        if (remoteMessage.getData().size() > 0) {
            Log.d(TAG, "Message data payload: " + remoteMessage.getData());
        }

        // Check if message contains a notification payload.
        if (remoteMessage.getNotification() != null) {
            Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
            sendNotification( remoteMessage);              
        }     
    }

    /**
     * Create and show a simple notification containing the received FCM message.
     *
     * @param remoteMessage FCM message message received.
     */
    private void sendNotification(RemoteMessage remoteMessage) {
        Intent intent = new Intent(this, MyActivity.class);

        Map<String, String> hmap ;
        hmap = remoteMessage.getData();
        hmap.get("data_info");
        intent.putExtra("data_info", hmap.get("data_info"));
        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);


        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
                PendingIntent.FLAG_ONE_SHOT);

    }

Je peux recevoir la notification correctement, mais l'activité ne commence que lorsque je touche la notification dans la barre d'état système.

Existe-t-il un moyen de démarrer l'activité sans appuyer sur la notification en avant-plan?

La méthode onMessageReceived() de la classe MyFirebaseMessagingService qui extends FirebaseMessagingService est appelée correctement en premier plan, mais l'activité ne démarre pas J'ai aussi essayé avec le drapeau FLAG_ACTIVITY_NEW_TASK également sans succès. Merci d'avance.

8
bankode

Vous pouvez y parvenir en enregistrant un récepteur de diffusion dans votre activité de premier plan et en envoyant une diffusion depuis votre méthode onReceiveMessage ().

Premier planActivité

mReceiver = new BroadcastReceiver() {
 @Override
 public void onReceive(Context context, Intent intent) {
     Intent myNewActivity = new Intent(this, MyActivity.class);
     startActivity(myNewActivity);
   }
 };

mIntentFilter=new IntentFilter("OPEN_NEW_ACTIVITY");

@Override
protected void onResume() {
     super.onResume();
     registerReceiver(mReceiver, mIntentFilter);
}



@Override
protected void onPause() {
     if(mReceiver != null) 
            unregisterReceiver(mReceiver);
            mReceiver = null;
     }
     super.onPause();
   }

FirebaseNotificationReceiver

@Override
    public void onMessageReceived(RemoteMessage remoteMessage) {

   // Check if message contains a data payload.
    if (remoteMessage.getData().size() > 0) {
        Log.d(TAG, "Message data payload: " + remoteMessage.getData());
    }

    // Check if message contains a notification payload.
    if (remoteMessage.getNotification() != null) {
        Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
        sendNotification( remoteMessage);  

        Intent broadcast = new Intent();
        broadcast.setAction("OPEN_NEW_ACTIVITY);
        sendBroadcast(broadcast);
    }     
}

Vous pouvez ajouter une vérification pour savoir si l'application est au premier plan ou ne pas choisir entre envoyer une notification ou envoyer une diffusion.

4
cdiazmo

Créer BroadcastReceiver est le meilleur moyen de gérer votre scénario. Mais vous devez savoir quelle activité est utilisée par l'utilisateur. 

Créer BroadcastReceiver dans chaque activité donne un aspect étrange. Donc, créez une BaseActivity qui étend l’activité. BaseActivity aura le code BroadcastReceiver et Toute autre activité étend cette BaseActivity.

open class BaseActivity : AppCompatActivity() {

private lateinit var broadcastReceiver: BroadcastReceiver

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    broadcastReceiver = object : BroadcastReceiver() {
        override fun onReceive(p0: Context?, p1: Intent?) {
            if (p1 != null) {
                handleBroadcastActions(p1)
            }
        }

    }
}

private fun handleBroadcastActions(intent: Intent) {
    when (intent.action) {
        Constants.ACTIVITY_STUFF -> {
            onHandleActivity()
        }
    }
}

protected open fun onHandleActivity() {
    startActivity(intentFor<YourActivity>())
}

override fun onResume() {
    super.onResume()
    registerReceiver(broadcastReceiver, IntentFilter(Constants.ACTIVITY_STUFF))

}

override fun onPause() {
    super.onPause()
    unregisterReceiver(broadcastReceiver)
}}

J'ai ajouté mon code kotlin. J'espère que tu peux comprendre :)

Enfin, vous pouvez appeler cette BroadcastReceiver depuis onMessageReceived() dans FirebaseMessagingService.

override fun onMessageReceived(message: RemoteMessage) {
    sendBroadcast(Intent(Constants.ACTIVITY_STUFF))
}
0
dpvmani

Vous devez obtenir des informations sur l'application de premier plan actuelle sur votre appareil. Sur cette base, vous pouvez décider de démarrer l’activité ou d’envoyer une notification.

Pour ce faire, je suggérerai quelque chose comme ceci:

public void onMessageReceived(RemoteMessage remoteMessage) {
    // Check if message contains a data payload.
    if (remoteMessage.getData().size() > 0) {
        Log.d(TAG, "Message data payload: " + remoteMessage.getData());
    }

    // Check if message contains a notification payload.
    if (remoteMessage.getNotification() != null) {
        Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
        handleNotification(remoteMessage);              
    }  
}

private void handleNotification(RemoteMessage remoteMessage){
    Intent intent = new Intent(this, MyActivity.class);
    Map<String, String> hmap ;
    hmap = remoteMessage.getData();
    hmap.get("data_info");

    intent.putExtra("data_info", hmap.get("data_info"));
    intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

    Context context = getApplicationContext();

    //CHECK IF THIS APP IS IN FOREGROUND
    ActivityManager am = (ActivityManager)
    AppService.this.getSystemService(ACTIVITY_SERVICE);

    // The first in the list of RunningTasks is always the foreground task.
    RunningTaskInfo foregroundTaskInfo = am.getRunningTasks(1).get(0);
    String foregroundTaskPackageName = foregroundTaskInfo .topActivity.getPackageName();

    if(foregroundTaskPackageName.equals(context.getPackageName()){
        //THIS STARTS MAINACTIVITY DIRECTLY IF THE FOREGROUND APP IS THIS APP
        startActivity(intent);
    }else{
        //IF THE FOREGROUND APP ISN'T THIS APP THEN SEND A PENDING INTENT TO OPEN MAIACTIVITY WHEN USER TAP ON NOTIFICATION
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
            PendingIntent.FLAG_ONE_SHOT);
        //CREATE A NOTIFICATION IN THE SYSTEM TRAY
        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
                .setContentTitle("TITLE")
                .setContentText("SUBMESSAGE")
                .setPriority(Notification.PRIORITY_MAX)
                .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
                .setContentIntent(pendingIntent)
                .setAutoCancel(true);
        NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);

        // notificationId is a unique int for each notification that you must define
        notificationManager.notify(notificationId, mBuilder.build());
    }
}

Vous devez définir l'ID de notification, le titre et le sous-message qui seront affichés dans la notification.

Vous aurez également besoin de l'autorisation <uses-permission Android:name="Android.permission.GET_TASKS" /> pour être ajouté dans le manifeste de l'application.

0
IronJohn
public class MyFirebaseMessagingService extends FirebaseMessagingService {
 private static final String TAG = "FCM Service";
 @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        // TODO: Handle FCM messages here.
        // If the application is in the foreground handle both data and notification messages here.
        // Also if you intend on generating your own notifications as a result of a received FCM
        // message, here is where that should be initiated.
//     IntentFilter filter = new IntentFilter("OPEN_NEW_ACTIVITY");
//        registerReceiver(new BroadcastNotification(),filter);
//     showNotification(remoteMessage.getNotification().getBody());

        Log.d(TAG, "From: " + remoteMessage.getFrom());
        Log.d(TAG, "Notification Message Body: " + remoteMessage.getNotification().getBody());
     Log.e("Myname","shdjhfghgh");
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Intent in= new Intent(this,MainActivity.class);
        in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(in);
    }
}
0
Devraj Jha

(kotlin) utilisez ce code dans onMessageReceived si vous souhaitez vérifier si l'application est au premier plan ou à l'arrière-plan

    var foreground = false

    try {
        foreground = ForegroundCheckTask().execute(this).get()
    } catch (e: InterruptedException) {
        e.printStackTrace()
    } catch (e: ExecutionException) {
        e.printStackTrace()
    }

utilisez ensuite la variable "foreground" pour effectuer les actions nécessaires

 if (foregroud) { //app in foreground
            intent = Intent(this, ChatAdminActivity::class.Java)
            intent.putExtra("intent_backchat", 1)
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_CLEAR_TASK)
            pendingIntent = PendingIntent.getActivity(this, Integer.valueOf(random) /* Request code */, intent, PendingIntent.FLAG_UPDATE_CURRENT)
            startActivity(intent)      // to directly open activity if app is foreground
        } else { //app in background
            intent = Intent(this, ChatAdminActivity::class.Java)
            intent.putExtra("intent_backchat", 1)
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
            pendingIntent = PendingIntent.getActivity(this, Integer.valueOf(random) /* Request code */, intent, PendingIntent.FLAG_UPDATE_CURRENT)
        }
.....

espère que ça aide ..

et vous pouvez voir mon FCMService complet code

0
firecatmusic

J'ai pu y parvenir en appelant send () sur pendingIntent:

PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
                PendingIntent.FLAG_ONE_SHOT);
try {
       pendingIntent.send();
        } catch (PendingIntent.CanceledException e) {
            e.printStackTrace();
    }
0
bankode