【问题标题】:Firebase on Android - I want to disable firebase notifications on Android clientAndroid 上的 Firebase - 我想在 Android 客户端上禁用 Firebase 通知
【发布时间】:2016-05-29 14:40:45
【问题描述】:

我正在使用 Firebase 控制台向用户发送通知。 但是我想让用户禁用通知。 如何禁用它们?

只有当应用程序处于前台时,我才能通过 FirebaseMessagingService 处理(和停止)通知。但是当应用处于后台时,我无法停止通知。

【问题讨论】:

    标签: android firebase firebase-notifications


    【解决方案1】:

    我还不能发表评论,但racs' comment 帮了我很多忙。

    实际上,Firebase 文档建议使用数据推送而不是 通知,如果您想完全控制它的方式 处理:firebase.google.com/docs/cloud-messaging/... - 引用:“使用 当您希望 FCM 处理在 代表您的客户端应用程序。当您希望您的应用程序使用数据消息时 在您的 Android 客户端上处理显示或处理消息 应用程序...”

    所以基本上,我将推送通知请求的正文从:

    {
       "data": {
           "type" : "mytype"
        },
        "notification": {
            "title": "My Title",
            "body": "My Notification Message"
        },
        "to": "/topics/all"
    }
    

    收件人:

    {
       "data": {
           "type" : "mytype",
           "title": "My Title",
           "body": "My Notification Message"
        },
        "to": "/topics/all"
    }
    

    现在我的应用即使在后台也每次都会调用 onMessageReceived(),我只是更改了方法以在推送数据中使用获得的通知标题和消息。

    【讨论】:

    • 有没有办法使用这种方法,并且推送通知被视为通知,而不仅仅是 Firebase 仪表板中的数据?
    • @Benoit 使用 fcm 控制台将始终发送通知对象
    • @AlvinR​​usli 非常有用的答案,当应用程序被杀死/关闭时我如何处理接收到的数据?
    【解决方案2】:

    不确定为什么会发生这种情况(可能是代码 sn-p?),但有一个重量级的终极解决方案:在清单中定义您自己的 c2dm 接收器并将优先级设置为高(>0)然后停止通知处理。

    GCM 消息作为有序广播处理,因此您可以通过调用此方法停止处理链:

    https://developer.android.com/reference/android/content/BroadcastReceiver.html#abortBroadcast()

    如果您在接收器中不做任何事情,那么下一个接收器将进行处理,这将是 Firebase 接收器。

    请注意:Firebase 正在发送远程配置更改的推送通知。因此,如果您使用远程配置,则不建议禁止任何数据推送。

    【讨论】:

    • 实际上,如果您想完全控制数据的处理方式,Firebase 文档建议使用数据推送而不是通知:firebase.google.com/docs/cloud-messaging/… - 引用:“当您希望 FCM 处理显示代表您的客户端应用通知。当您希望您的应用处理显示或处理 Android 客户端应用上的消息时,请使用数据消息..."
    • 谢谢。使用数据推送(通过 POST 请求),即使应用程序在后台,我也能够处理通知。现在,如何在不指定 JSON 文件中每个设备的令牌的情况下向所有设备发送数据?通过 Firebase 控制台可以指定“用户段”,但如果我没有在 JSON 文件中指定元素“to”,我会收到错误 400。
    • 我不是这个主题的专家,但据我所知,当你进行数据推送时,基本上你会一起跳过 Firebase 功能。因此,无法发送给主题订阅者或分析。在这种情况下,FB 充当 GCM 的中继,根本不与发送的数据交互。
    • 似乎可以向主题发送数据:firebase.google.com/docs/cloud-messaging/…您可以将每个设备注册到一个主题并将数据推送发送到该主题,因此您不需要跟踪设备令牌自己。
    【解决方案3】:

    我遇到了同样的问题。我使用 subscribeToTopic API 订阅通知。

    FirebaseMessaging.getInstance().subscribeToTopic("APP");
    

    我找到另一个 API unsubscribeFromTopic 来取消订阅。

    FirebaseMessaging.getInstance().unsubscribeFromTopic("APP");
    

    也许它对使用主题通知的APP会很有用。它不会在前台和后台收到通知。

    【讨论】:

      【解决方案4】:

      我遇到了这个问题。并通过使用以下代码解决:

      启用 Firebase 通知:

      FirebaseInstanceId.getInstance().getToken();
      

      禁用 Firebase 通知: deleteInstanceId() 是一个阻塞调用。它不能在主线程上调用。

      FirebaseInstanceId.getInstance().deleteInstanceId();
      

      【讨论】:

      • 在哪里设置方法FirebaseInstanceId.getInstance().deleteInstanceId();
      • 我用的是AsyncTask,把FirebaseInstanceId.getInstance().deleteInstanceId();放到doInBackground
      • 请注意 FirebaseInstanceId 已弃用(整个 IID 包已弃用)但 Installations 包已接管它的职责,FirebaseInstallations.getInstance().delete() 应该可以解决问题 (firebase.google.com/docs/reference/android/com/google/firebase/…)
      【解决方案5】:

      您可以处理来自所有不同服务的所有推送事件(使用 Firebase)。先创建YouUniversalFCM extends WakefulBroadcastReceiver

      例如:

      public class YourUniversalFCM extends WakefulBroadcastReceiver {
      
          private static final String ACTION_REGISTRATION
              = "com.google.android.c2dm.intent.REGISTRATION";
          private static final String ACTION_RECEIVE
              = "com.google.android.c2dm.intent.RECEIVE";
      
          @Override
          public void onReceive(Context context, Intent intent) {
              String action = intent.getAction();
              for (String key : intent.getExtras().keySet()) {
                  Log.d(
                          "TAG",
                          "{UniversalFCM}->onReceive: key->"
                                  + key + ", value->" + intent.getExtras().get(key)
                  );
              }
              switch (action) {
                  case ACTION_REGISTRATION:
                      // TODO: 2016-08-06
                      break;
      
                  case ACTION_RECEIVE:
                      // TODO: 2016-08-06
                      break;
      
                  default:
              }
      
              abortBroadcast();
          }
      }
      

      AndroidManifest.xml下一个

      <uses-permission android:name="android.permission.INTERNET"/>
      <uses-permission android:name="android.permission.WAKE_LOCK"/>
      
      <application
          ...>
      
          ...
      
          <receiver
              android:name=".fcm.receivers.UniversalFCM"
              android:permission="com.google.android.c2dm.permission.SEND">
              <intent-filter>
                  <action android:name="com.google.android.c2dm.intent.RECEIVE"/>
                  <action android:name="com.google.android.c2dm.intent.REGISTRATION"/>
                  <category android:name="YOUR_PACKAGE"/>
              </intent-filter>
          </receiver>
      
      </application>
      

      YOUR_PACKAGE 替换为您的应用程序包。就这样。 如果您想订阅其他推送服务,您必须添加YourTokenService

      public class YourTokenService extends FirebaseInstanceIdService {
          @Override
          public void onTokenRefresh() {
              String refreshedToken = FirebaseInstanceId.getInstance().getToken();
              L.d(TokenService.class, "onTokenRefresh() Refreshed token: " + refreshedToken);
              // TODO: 2016-08-06
              super.onTokenRefresh();
          }
      }
      

      并在AndroidManifest.xml中声明

      <service android:name="YourTokenService">
          <intent-filter>
              <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
          </intent-filter>
      </service>
      

      【讨论】:

      • WakefulBroadcastReceiver 现在已弃用。请避免使用此方法并参考 Alvin Rusli 的回答
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-05
      • 1970-01-01
      • 1970-01-01
      • 2015-06-13
      相关资源
      最近更新 更多