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