如何使用 Firebase 中的用户令牌向特定用户发送通知?

Posted

技术标签:

【中文标题】如何使用 Firebase 中的用户令牌向特定用户发送通知?【英文标题】:How can I send notification to specific User using the user's token in Firebase? 【发布时间】:2021-06-29 07:47:28 【问题描述】:

我正在开发一个 android 应用程序 (java),我正在使用 Firebase,对于每个注册用户我都有一个设备令牌,我如何使用他的令牌向特定用户发送通知?

【问题讨论】:

请参考enter link description here 我已经在我的一个tutorials中一步一步地解释了如何使用Cloud Firestore向特定用户发送notificationsNode.js。你也可以看看我这个 post 的回答。 我已经尝试过这个指南link,但不知道消息的.builder 【参考方案1】:

在这里使用YouTube link EDMT Dev 在他的 Eat it 新系列中实现了以下内容。如果对您有帮助,请将此标记为正确答案。

添加以下依赖项

 `implementation 'io.reactivex.rxjava2:rxandroid:2.1.1`'

现在创建这些类:

Token Model 该模型用于获取token数据(Token、Phone)。我还有一个电话变量,因为我根据我的数据结构制作了这个类。请根据需要修改代码

public class TokenModel 

private String phone,token;

public TokenModel() 


public TokenModel(String phone, String token) 
    this.phone = phone;
    this.token = token;


public String getPhone() 
    return phone;


public void setPhone(String phone) 
    this.phone = phone;


public String getToken() 
    return token;


public void setToken(String token) 
    this.token = token;

FCM 发送数据模型

  public class FCMSendData 
private String to;
private Map<String,String> data;

public FCMSendData(String to, Map<String, String> data) 
    this.to = to;
    this.data = data;


public String getTo() 
    return to;


public void setTo(String to) 
    this.to = to;


public Map<String, String> getData() 
    return data;


public void setData(Map<String, String> data) 
    this.data = data;

创建 FCM 结果模型

 class FCMResult 
    private String message_id;
    
    public FCMResult() 
    
    
    public String getMessage_id() 
        return message_id;
    
    
    public void setMessage_id(String message_id) 
        this.message_id = message_id;
    

创建 RetrofitFCMClient

public class RetrofitFCMClient 
private static Retrofit instance;
public static Retrofit getInstance()

    if(instance==null)
    
        instance  = new Retrofit.Builder().baseUrl("https://fcm.googleapis.com/")
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
        return instance;
    
    return instance;

现在我们需要实现一个接口 //授权密钥是云消息的服务器密钥

公共接口 IFCMService

@Headers(
        "Content-Type:application/json",

        "Authorization:key=**YOUR_AUTHORIZATION KEY HERE**"

)
@POST("fcm/send")
Observable<FCMResponse> sendNotification(@Body FCMSendData body);

现在我们已经准备好使用 firebase 消息传递,只需要放置数据并使用我们的改造来推送它

TokenModel tokenModel = dataSnapshot.getValue(TokenModel.class);
                                        //("FCM",tokenModel.getToken());
                                        Map<String, String> notiData = new  
HashMap<>();
             notiData.put(Common.NOTI_TITLE, "YOUR NOTIFICATION TITLE");
             notiData.put(Common.NOTI_CONTENT,"YOUR_NOTFICATION CONTENT );

    FCMSendData sendData = new FCMSendData(tokenModel.getToken(), 
notiData);
                                        
  compositeDisposable
 .add(ifcmService.sendNotification(sendData)
  .subscribeOn(Schedulers.io()).
                                           


  observeOn(AndroidSchedulers.mainThread())
      .subscribe(new Consumer<FCMResponse>() 
                                        @Override
                                        public void accept(FCMResponse 
fcmResponse)              

     throws Exception 
                                            if (fcmResponse.getSuccess()  
== 1) 

                                                 
Toast.makeText(getContext(),     

    "Success", Toast.LENGTH_LONG).show();
                                             else 
                                                 
Toast.makeText(getContext(), "Failed  
       to Notify", Toast.LENGTH_LONG).show();
                                            
                                        
                                    , new Consumer<Throwable>() 
                                        @Override
                                        public void accept(Throwable 
throwable) throws Exception 
                                            Toast.makeText(getContext(),   
throwable.getMessage(), Toast.LENGTH_LONG).show();

                                        
                                    ));




    

在这里使用YouTube link EDMT Dev 在他的 Eat it 新系列中实现了以下内容

【讨论】:

创建界面报错,不识别 Headesr 和 Post 这两个字,应该在哪里创建界面?另外,RetrofitFCMClient中的Retrofit类也无法识别 请在您的应用级别 gradle 中添加改造的依赖项【参考方案2】:

要向用户发送通知,唯一需要的是该用户的令牌。您可以使用 FCM 发送通知。 在这里,我分享了我的 FCM 类,它可以用于这个目的。它正在使用 Okhttp3 请求,因此请确保添加它的依赖项。

    implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.2'

添加这个依赖后,你所要做的就是使用这个FCM类。

FCMMessages.java

public class FCMMessages 

    private Context context;

    public void sendMessageSingle(Context context, final String recipient, final String title, final String body, final Map<String, String> dataMap)
    
        this.context = context;

        Map<String, Object> notificationMap = new HashMap<>();
        notificationMap.put("body", body);
        notificationMap.put("title", title);

        Map<String, Object> rootMap = new HashMap<>();
        rootMap.put("notification", notificationMap);
        rootMap.put("to", recipient);
        if (dataMap != null)
            rootMap.put("data", dataMap);

        new SendFCM().setFcm(rootMap).execute();
    


    public void sendMessageMulti(Context context, final JSONArray recipients, final String title, final String body, final Map<String, String> dataMap) 
        this.context = context;

        Map<String, Object> notificationMap = new HashMap<>();
        notificationMap.put("body", body);
        notificationMap.put("title", title);
        Map<String, Object> rootMap = new HashMap<>();
        rootMap.put("notification", notificationMap);
        rootMap.put("registration_ids", recipients);
        if (dataMap != null)
            rootMap.put("data", dataMap);

        new SendFCM().setFcm(rootMap).execute();
    

    @SuppressLint("StaticFieldLeak")
    class SendFCM extends AsyncTask<String, String, String> 

        private String FCM_MESSAGE_URL = "https://fcm.googleapis.com/fcm/send";
        private Map<String, Object> fcm;

        SendFCM setFcm(Map<String, Object> fcm) 
            this.fcm = fcm;
            return this;
        

        @Override
        protected String doInBackground(String... strings) 
            try 
                MediaType JSON = MediaType.parse("application/json; charset=utf-8");
                RequestBody body = RequestBody.create(JSON, new JSONObject(fcm).toString());
                Request request = new Request.Builder()
                        .url(FCM_MESSAGE_URL)
                        .post(body)
                        .addHeader("Authorization","key=" + StaticConfig.myMessagingAuth)
                        .build();
                Response response = new OkHttpClient().newCall(request).execute();
                return response.body().string();

             catch (Exception e) 
                e.printStackTrace();
                return null;
            
        

        @Override
        protected void onPostExecute(String result) 
            try 
                JSONObject resultJson = new JSONObject(result);
                int success, failure;
                success = resultJson.getInt("success");
                failure = resultJson.getInt("failure");
            //Toast.makeText(context, "Sent: " + success + "/" + (success + failure), Toast.LENGTH_LONG).show();
             catch (JSONException e) 
                e.printStackTrace();
//                Toast.makeText(context, "Message Failed, Unknown error occurred.", Toast.LENGTH_LONG).show();
            
        
    


确保从您的 firebase 项目设置中获取消息传递身份验证。要获取messagingAuth 令牌,请按以下步骤操作:

Open Firebase Project > Project Settings > Cloud Messaging > Server key

复制服务器密钥的值并将其作为messagingAuth粘贴到您的android项目中。

要向单个用户令牌发送通知,请使用sendMessageSingle 方法。就像

String user_token = "wiubd92uhe91dik-q";
String notification_title = "This is notification title";
String notification_des = "This is notification description";
new FCMMessages().sendMessageSingle(MainActivity.this, user_token, notification_title, notification_des, null);

要向多个用户令牌发送通知,请使用sendMessageMulti 方法。就像

ArrayList<String> user_tokens = new ArrayList<>();
user_tokens.add(token_1);
user_tokens.add(token_2);
user_tokens.add(token_3);
String notification_title = "This is notification title";
String notification_des = "This is notification description";
new FCMMessages().sendMessageMulti(MainActivity.this, new JSONArray(user_tokens), notification_title, notification_des, null);

【讨论】:

我试图通知单个用户,我将我的服务器密钥和要通知的用户的令牌放在变量 user_token 中,当我尝试运行该方法时,没有收到通知用户的设备 @LucaOrlandi 你输入正确的令牌了吗? 是的,我放了正确的令牌,发送通知的功能需要放在哪里?在一个简单的类中? 我应该放什么上下文?如果我把我的类,例如 (SendMessage.this) 生成错误

以上是关于如何使用 Firebase 中的用户令牌向特定用户发送通知?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 iOS 中使用 Google Firebase 向特定用户发送推送通知?

如何使用swift更新firebase中的令牌?

如何在 Firebase Firestore 中获取内部集合

按用户属性向用户发送 Firebase Cloud Messaging 通知

Firebase 存储:向匿名签名用户提供内容,无需令牌

Firebase 令牌在 1 小时内过期后如何保留用户?