基于FCM的消息推送功能


需求背景

我方项目需要支持客户端消息推送,iOS终端可以借由苹果本身的apns很方便的实现,但是对于Android来说,必须集成第三方的SDK来处理。考虑到项目需要以及成本,我们选择使用谷歌的FCM框架来实现,因为我们项目针对消息的可到达率要求并不高,而且推送消息的性质是业务低关注度的,重点是我们的项目还是海外项目,所以一番评估之后发现FCM完全能够满足我们的需求。

文档分析

1、Firebase云消息传递服务器简介

2、FCM服务器协议

3、使用旧版HTTP协议发送

4、使用HTTP方式构建服务器

5、请求授权说明

6、向旧版协议发送请求提供授权

7、使用HTTP旧版协议模式发送请求

8、举例

项目运用

Capation&D的这个项目基于SpringBoot,JDK1.8进行开发。

1、Maven依赖

1 <dependency>
2     <groupId>com.google.api-client</groupId>
3     <artifactId>google-api-client</artifactId>
4     <version>1.24.1</version>
5 </dependency>

2、编写工具类

 1 /**
 2  * @Project:captainad-supply-chain
 3  * @PackageName:com.captainad.supply-chain.common.push
 4  * @Author:Captainad
 5  * @blogsite:https://www.cnblogs.com/captainad/
 6  * @DateTime:2018/8/9 15:52.
 7  * @Description: 基于Google Firebase框架实现的实时消息推送功能,目前仅支持Android设备
 8  */
 9 @Slf4j
10 @Component
11 public class FcmPushService {
12 
13     @Autowired
14     private GetSetCacheService getSetCacheService;
15 
16     @Autowired
17     private HttpAskInterface httpAskInterface;
18 
19     /**
20      * 消息推送,推送的消息用于提示,并且点击提示消息将会跳转链接至指定页面
21      * A: Captain&D
22      * W: https://www.cnblogs.com/captainad/
23      * @param deviceToken
24      * @param title
25      * @param body
26      * @param route
27      * @throws Exception
28      */
29     @Async
30     public void push(final String deviceToken, final String title, final String body,
31                      final String route, final Integer dataType, final String dataMsg) 
32             throws Exception {
33         log.info("[START]开始推送FCM消息");
34         // 请求标头
35         Map<String, String> requestHeader = new HashMap<>();
36         requestHeader.put("Content-Type", "application/json; UTF-8");
37         requestHeader.put("Authorization", "Bearer " + getAccessToken());
38 
39         // 请求体
40         JSONObject json = new JSONObject();
41 
42         JSONObject message = new JSONObject();
43         message.put("token", deviceToken);
44         JSONObject data = new JSONObject();
45 
46         // 发送弹窗提示信息
47         if(!StringUtils.isEmpty(title) && !StringUtils.isEmpty(body)) {
48             JSONObject notification = new JSONObject();
49             notification.put("title", title);
50             notification.put("body", body);
51             message.put("notification", notification);
52 
53             data.put("route", route);
54             // flag: 0-无需跳转,1-需要跳转
55             data.put("routeFlag", StringUtils.isEmpty(route) ? "0" : "1");
56         }
57 
58         // 发送数据
59         if(!StringUtils.isEmpty(dataMsg)) {
60             data.put("dataType", String.valueOf(dataType));
61             data.put("params", dataMsg);
62         }
63 
64         message.put("data", data);
65         json.put("message", message);
66 
67         log.info("请求json内容===> {}", json.toString());
68         // https://fcm.googleapis.com/v1/projects/bluepay-tesla/messages:send
69         String fcmApiUrl = getSetCacheService.getConfigValue("fcm_api_path");
70         HttpResponse httpResponse = httpAskInterface.synSendPost(fcmApiUrl, json.toString(), requestHeader);
71         log.info("fcm响应内容===> {}", httpResponse);
72         log.info("[END]推送FCM消息结束");
73     }
74 
75     /**
76      * 获取定时刷新的令牌
77      * A: Captain&D
78      * W: https://www.cnblogs.com/captainad/
79      * @return
80      * @throws IOException
81      */
82     private String getAccessToken() throws Exception {
83         String jsonPath = getSetCacheService.getConfigValue("fcm_access_token_json");
84         URL url = new URL(jsonPath);
85         HttpURLConnection conn = (HttpURLConnection)url.openConnection();
86         InputStream inputStream = conn.getInputStream();
87 
88         GoogleCredential googleCredential = GoogleCredential
89                 .fromStream(inputStream)
90                 .createScoped(Arrays.asList("https://www.googleapis.com/auth/firebase.messaging"));
91         googleCredential.refreshToken();
92         if(inputStream != null) {
93             inputStream.close();
94         }
95         return googleCredential.getAccessToken();
96     }
97 
98 }

使用总结

我们只需要申请一个Google开发者账号以及自身企业的一些相关信息,就能够很方便的使用Firebase云消息传递(FCM)提供的众多消息传递选项和功能,上面基于项目的需要实现了Android支持的版本,值得提及的时候,给特定设备推送消息时,需要提前获取到设备的deviceToken,因为它指代了一台唯一特定的设备。另外,如果想批量发送消息的,可以自行扩展出来。

参考资料

1、https://firebase.google.cn/docs/cloud-messaging/concept-options?hl=zh-cn


作者:Captain&D,发布于:2019/05/15
原文:https://www.cnblogs.com/captainad/p/10872083.html