• 基于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

  • 相关阅读:
    查找数据库表中重复的 Image 类型值
    C#中的引用传递和值传递。
    用JS解决Asp.net Mvc返回JsonResult中DateTime类型数据格式的问题
    根据业务自己设计的.NET工厂模式架构
    封装EF code first用存储过程的分页方法
    2013款MacBook Air装Windows7单系统
    js判断是否在微信浏览器中打开
    EF Code First连接现有数据库
    JS中for循序中延迟加载实现动态效果
    DIV+CSS左右两列自适应高度的方法
  • 原文地址:https://www.cnblogs.com/captainad/p/10872083.html
Copyright © 2020-2023  润新知