需求背景
我方项目需要支持客户端消息推送,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