Android Firebase通知(FCM)

Android Firebase通知(FCM),android,android-notifications,firebase-cloud-messaging,firebase-notifications,Android,Android Notifications,Firebase Cloud Messaging,Firebase Notifications,我正在我的应用程序中使用FCM。我遵循了Firebase文档,一切似乎都按预期进行 我能够在后台和前台接收应用程序被终止时的消息通知 现在,我想通过添加一些应用程序首选项来完全控制用户 用户可以禁用应用程序设置中的所有通知 用户可以通过应用程序设置更改通知铃声 我有一个想法,如何做到这一点时,应用程序是在死亡或前景。我正在考虑访问FirebaseMessagingService中的SharedPref,查看应用程序是否应显示通知,并检查要使用的铃声。除非有一种通用的方法来设置这些参数,比如“

我正在我的应用程序中使用FCM。我遵循了Firebase文档,一切似乎都按预期进行

我能够在后台和前台接收应用程序被终止时的消息通知

现在,我想通过添加一些应用程序首选项来完全控制用户

  • 用户可以禁用应用程序设置中的所有通知
  • 用户可以通过应用程序设置更改通知铃声
我有一个想法,如何做到这一点时,应用程序是在死亡或前景。我正在考虑访问FirebaseMessagingService中的SharedPref,查看应用程序是否应显示通知,并检查要使用的铃声。除非有一种通用的方法来设置这些参数,比如“取消订阅”所有通知或更改我不知道的应用程序默认通知铃声

但是,我不知道当应用程序处于后台时,如何处理收到的通知,因为通知会发送到设备的系统托盘。
任何人都有任何想法或者可以给我指一些文档。。。我找不到有关此的任何信息?

默认情况下,通知会影响每个用户。如果您希望允许用户选择退出所有通知(或通知的某些子集),您应该使用:默认情况下,您将为所有用户调用
subscribeTopic()
,如果他们选择退出通知,您将调用
unsubscribeTopic()

通过向主题发送通知,只有已订阅的用户才会收到通知

解释了如何包含一个
sound
参数来覆盖Android上的铃声,该参数可以是应用程序
res/raw
目录中捆绑的任何声音


需要注意的是,控制台中不支持这两种功能,但要求您创建自己的

,因为firebase通知服务有两个对象,第一个是“数据”,第二个是“通知”,当您从firebase控制台发送推送时,它会在“通知”对象中发送数据。在FirebaseMessagingService.class中处理通知时,您正在使用NotificationBuilder创建自定义通知。当应用程序位于后台时,您将无法从“通知”对象创建通知。所以,您定制的通知不会出现在通知托盘中,您需要从后端推送通知,并在“数据”对象中发送通知内容。您每次都可以自定义通知。 详情请参阅此页:

用户可以禁用应用程序设置中的所有通知

您可以使用您自己声明的共享首选项。就通用方法而言,您应该研究@ianhanniballake的答案

用户可以通过应用程序设置更改通知铃声

有关默认铃声,请参阅此。此链接中的第三个答案还解释了如何从应用程序的“设置”活动中使用声音选择器。如果您想要自定义声音,请参阅

当然,您必须存储用户首选项,这样您就不会每次都要求用户选择声音

还有一件事,因为您使用的是服务,所以您不必每次都访问共享首选项来查找要播放的声音,您可以将选择存储在任何变量中。每当用户更改notif声音时,您可以设置侦听器或{停止服务->更新首选项->重新启动服务}。确保每次服务启动时都读取首选项

在教程中,您可以找到我们如何更改特定应用程序的铃声,以及当应用程序位于前台而应用程序位于后台时如何处理通知

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

     // Check if message contains a notification payload.
    if (remoteMessage.getNotification() != null) {
        Log.e(TAG, "Notification Body: " + remoteMessage.getNotification().getBody());
        handleNotification(remoteMessage.getNotification().getBody());
    }
}
发送通知类型消息时,firebase会在应用程序处于后台时自动显示通知。如果应用程序位于前台,handleNotification()方法将处理通知消息

private void handleNotification(String message) {
    if (!NotificationUtils.isAppIsInBackground(getApplicationContext())) {
        // app is in foreground, broadcast the push message
        Intent pushNotification = new Intent(Config.PUSH_NOTIFICATION);
        pushNotification.putExtra("message", message);
        LocalBroadcastManager.getInstance(this).sendBroadcast(pushNotification);

        // play notification sound
        NotificationUtils notificationUtils = new NotificationUtils(getApplicationContext());
        notificationUtils.playNotificationSound();
    }else{
        // If the app is in background, firebase itself handles the notification
    }
}
这里您可以处理自定义通知声音-

// Playing notification sound
public void playNotificationSound() {
    try {
        Uri alarmSound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE
                + "://" + mContext.getPackageName() + "/raw/notification");
        Ringtone r = RingtoneManager.getRingtone(mContext, alarmSound);
        r.play();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

当你的应用程序处于后台或被杀死时,Firebase不会调用你的onMessageReceived,并且你不能自定义你的通知。系统生成的通知将显示

使firebase库在任何情况下都能调用您的OnMessageRived

a) 前景

b) 背景

c) 杀死

您不能将json键“通知”放在对firebase api的请求中,而是使用“数据”,见下文

例如,以下消息将不会调用onMessagereceived()

但这会奏效的

  {
  "to": "/topics/test",
   "data": {
       "text":"text",
       "title":"",
       "line1":"testline",
       "line2":"test"
   }
} 
请参阅此链接: 它详细描述了firebase消息类型 例如:

@Override
public void onMessageReceived(RemoteMessage remoteMessage) {

    Log.d(TAG, "From: " + remoteMessage.getFrom());

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

    if(remoteMessage.getData().get("state").toString().equals("Request")){
        sendNotification(remoteMessage.getData().get("body").toString(), remoteMessage.getData().get("message").toString(), remoteMessage.getData().get("state").toString(),Activity_name.class);
    }
}

    private void sendNotification(String messageBody, String data, String state,Class<?> activityCompat) {
        int requestID = (int) System.currentTimeMillis();
        Intent intent = new Intent(this, activityCompat);
        Bundle bundle = new Bundle();
        bundle.putString("message", data);
        bundle.putString("state", state);
        intent.putExtras(bundle);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, requestID, intent, PendingIntent.FLAG_UPDATE_CURRENT);

        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.small_logo)
                .setContentTitle("Title")
                .setContentText(messageBody).setContentIntent(pendingIntent)
                .setAutoCancel(true)
                .setStyle(new NotificationCompat.BigTextStyle()
                        .bigText(messageBody))
                .setTicker(messageBody);

        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        notificationBuilder.getNotification().flags |= Notification.FLAG_AUTO_CANCEL;
        Notification notification = notificationBuilder.build();

        notificationManager.notify((int) Calendar.getInstance().getTimeInMillis(), notification);

    }
@覆盖
收到消息时公共无效(RemoteMessage RemoteMessage){
Log.d(标记“From:”+remoteMessage.getFrom());
//检查消息是否包含数据有效负载。
如果(remoteMessage.getData().size()>0){
Log.d(标记,“消息数据有效负载:”+remoteMessage.getData());
}
if(remoteMessage.getData().get(“state”).toString().equals(“Request”)){
sendNotification(remoteMessage.getData().get(“正文”).toString(),remoteMessage.getData().get(“消息”).toString(),remoteMessage.getData().get(“状态”).toString(),Activity_name.class);
}
}
私有void sendNotification(字符串消息体、字符串数据、字符串状态、类activityCompat){
int requestID=(int)System.currentTimeMillis();
意向意向=新意向(此为activityCompat);
Bundle=新Bundle();
bundle.putString(“消息”,数据);
bundle.putString(“state”,state);
意向。额外支出(捆绑);
PendingEvent PendingEvent=PendingEvent.getActivity(this,requestID,intent,PendingEvent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder notificationBuilder=新建NotificationCompat.Builder(此)
.setSmallIcon(可拉深的右小标志)
.setContentTitle(“标题”)
.setContentText(messageBody).setContentIntent(PendingContent)
setAutoCa先生
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {

    Log.d(TAG, "From: " + remoteMessage.getFrom());

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

    if(remoteMessage.getData().get("state").toString().equals("Request")){
        sendNotification(remoteMessage.getData().get("body").toString(), remoteMessage.getData().get("message").toString(), remoteMessage.getData().get("state").toString(),Activity_name.class);
    }
}

    private void sendNotification(String messageBody, String data, String state,Class<?> activityCompat) {
        int requestID = (int) System.currentTimeMillis();
        Intent intent = new Intent(this, activityCompat);
        Bundle bundle = new Bundle();
        bundle.putString("message", data);
        bundle.putString("state", state);
        intent.putExtras(bundle);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, requestID, intent, PendingIntent.FLAG_UPDATE_CURRENT);

        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.small_logo)
                .setContentTitle("Title")
                .setContentText(messageBody).setContentIntent(pendingIntent)
                .setAutoCancel(true)
                .setStyle(new NotificationCompat.BigTextStyle()
                        .bigText(messageBody))
                .setTicker(messageBody);

        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        notificationBuilder.getNotification().flags |= Notification.FLAG_AUTO_CANCEL;
        Notification notification = notificationBuilder.build();

        notificationManager.notify((int) Calendar.getInstance().getTimeInMillis(), notification);

    }