【项目实战】接入极光推送SDK,实现从Java服务端后台推送自定义消息到Android车机端

news2024/11/23 8:38:32

一、需求描述

项目中需要接入极光推送SDK,实现从Java服务端推送消息到Android车机端,以下实现的功能主要是安卓端的,IOS端的虽然代码也兼容了,但是不在本次讨论范围内。以下是具体的实现过程。

二、极光推送介绍

极光推送是一款提供高效、安全、可靠的移动推送服务的云端平台,帮助用户快速实现安全的移动消息推送,它能够支持 Android、iOS 和 Web 等多个平台,为客户端 App 提供推送服务。它可以帮助开发者快速开发出一款功能强大、性能卓越的移动 App,为用户提供更便捷的服务。

2.1 如何申请车机key

直接登录https://www.jiguang.cn/ 极光推送的官网,进入开发者平台 - 应用管理,点击新建按钮
在这里插入图片描述

选择消息推送,再点击下一步
在这里插入图片描述
点击产品设置,输入应用包名,这个最好跟开发车机的同事要到。
在这里插入图片描述

最后选择SDK下载即可
回应用的首页,可以看到对应的key+secret
在这里插入图片描述
注意:
AppKey + Master Secret是需要配置到我们Java服务端后台的代码中,AppKey 是需要配置到车机端中的。

2.2 两种通知方式

因为极光推送支持多种推送方式,包括以下四种吧
在这里插入图片描述

2.2.1 通知消息

notification:通知,通知消息会触发安卓系统的通知消息,“通知”对象,是一条推送的实体内容对象之一(另一个是“消息”),是会作为“通知”推送到客户端的。
在这里插入图片描述
测试发送NotificationMessage,

{
	 notificationId=513213292,
	 msgId='18100617073600973', 
	 appkey='appkey', 
	 notificationContent='车机同事,如有疑问,请联系XXX,XXX极光服务端来的推送', 
	 notificationAlertType=7, 
	 notificationTitle='这是XXX极光服务端来的推送', 
	 notificationSmallIcon='', 
	 notificationLargeIcon='', 
	 notificationExtras='{}', 
	 notificationStyle=0, 
	 notificationBuilderId=0, 
	 notificationBigText='', 
	 notificationBigPicPath='', 
	 notificationInbox='', 
	 notificationPriority=0, 
	 notificationCategory='', 
	 developerArg0='', 
	 platform=0, 
	 notificationChannelId='', 
	 displayForeground='', 
	 notificationType=0', 
	 inAppMsgType=1', 
	 inAppMsgShowType=2', 
	 inAppMsgShowPos=0', 
	 inAppMsgTitle=, 
	 inAppMsgContentBody=, 
	 inAppType=0
}

在这里插入图片描述

2.2.2 自定义消息

应用内消息,又称作:自定义消息,透传消息。
此部分内容不会展示到通知栏上,JPush SDK 收到消息内容后透传给 App,需要 App 自行处理。
因为项目往往都会有定制UI的需求,所以此处我们选择的“自定义消息”。
在这里插入图片描述
测试发送CustomMessage,

{
	messageId='18100616954706161', 
	extra='', 
	message='你好,我是XXXX自定义的内容20230220 1724', 
	contentType='', 
	title='', 
	senderId='b1b6d54ffc7d36743d2cd208', 
	appId='com.xxx.xxx.xxx.xxx', 
	platform='0'
}

在这里插入图片描述

2.3 方案流程图

在这里插入图片描述
因为本指引聚焦在Cloud Server端的编程,其他模块不在本文中描述。

三、实现逻辑

3.1 定义测试的Controller

用于触发JiGuangUtil,此处支持两种通知方式,triggerNotificationMessage 、 triggerCustomMessage

@RestController
@RequestMapping("/jpush")
public class JpushController {
    @GetMapping("/triggerNotificationMessage")
    public JSONObject triggerNotificationMessage() {
        //推送内容(标题与内容)
        JSONObject json = new JSONObject();
        json.set("title", "我是XXXX项目的推送title");
        json.set("content", "我是XXXX项目的推送content");
        //单次推送的registerId列表
        List<String> tokenList = new ArrayList<>();
        String regId = "XXXXXXXXXXXXXXXXXXXXXXXX";
        tokenList.add(regId);
        //推送的自定义信息
        String action = "other msg";
        return JiGuangUtil.pushJiGuangOnTokenList(json, tokenList, action);
    }
    @GetMapping("/triggerCustomMessage")
    public JSONObject trigger() {
        //推送内容(标题与内容)
        JSONObject dataJson = new JSONObject();
        dataJson.set("title", "我是XXXX项目的推送title 18:32");
        dataJson.set("message", "我是XXXX项目的推送的自定义message 18:32");
        dataJson.set("contentType", "XXXXX推送类型 18:32");
        //单次推送的registerId列表
        List<String> regIdList = new ArrayList<>();
        String regId = "XXXXXXXXXXXXXXXXXXXXXXXX";
        regIdList.add(regId);
        //推送的自定义信息
        String extrasInfo = "extrasInfo"; 
        return JiGuangUtil.pushJiGuangCustomMessage(dataJson, regIdList, extrasInfo);
    }
}

3.2 定义极光推送工具类 - JiguangUtil

public class JiGuangUtil {
    private static final Log LOGGER = LogFactory.get();
    private static final int MAX_SIZE = 999;
    private static final String PROD_EVN = "prod";
    private static final String SAND_EVN = "sand";
    private static final char ANDROID_EVN = '0';
    private static final char IOS_EVN = '1';
    private static boolean pushEnvironment = false;
    static {
        Props props = new Props("application.properties");
        String pushEvo = props.getStr("XXXXX.XXXXX", SAND_EVN);
        pushEnvironment = PROD_EVN.equals(pushEvo) ? true : false;
    }

    /**
     * Android沙箱
     */
    private static final String APP_KEY_ANDROID = "XXXXX";
    private static final String SECRET_ANDROID = "XXXXX";
    /**
     * Android生产
     */
    private static final String APP_KEY_ANDROID_PROD = "XXXXX";
    private static final String SECRET_ANDROID_PROD = "XXXXX";
    /**
     * IOS
     */
    private static final String APP_KEY_IOS = "XXXXX";
    private static final String SECRET_IOS = "XXXXX";
    /**
     * 推送地址极光
     */
    private static final String PUSH_URL = "https://api.jpush.cn/v3/push";
    /**
     * 设置生产环境 极光推送只是对ios有效
     */
    private static final boolean PUSH_ENVIRONMENT_PROD = Boolean.TRUE;

    /**
     * 按regIdList进行安卓推送(通知消息)
     */
    public static JSONObject pushJiGuangOnTokenList(JSONObject json, 
   													List<String> regIdList, 
 													String action) {
        List<String> androidReg = regIdList.parallelStream()
                .filter(x -> StrUtil.isNotBlank(x))
                .filter(x -> ANDROID_EVN == x.charAt(2))
                .distinct()
                .collect(Collectors.toList());
        List<String> iosReg = regIdList.parallelStream()
                .filter(x -> StrUtil.isNotBlank(x))
                .filter(x -> IOS_EVN == x.charAt(2))
                .distinct()
                .collect(Collectors.toList());
        List<List<String>> androidRegIdList = CollUtil.split(androidReg, MAX_SIZE);
        List<List<String>> iosRegIdList = CollUtil.split(iosReg, MAX_SIZE);
        LOGGER.info("JiGuang push count user,android={},iOS={}", androidReg.size(), iosReg.size());
        androidRegIdList.stream().filter(x -> CollUtil.isNotEmpty(x)).forEach(x -> {
            if (pushEnvironment) {
                // 安卓推送生产
                pushMessage(json, action, x, APP_KEY_ANDROID_PROD, SECRET_ANDROID_PROD, PlatFormEnum.ANDROID, PUSH_ENVIRONMENT_PROD);
            } else {
                // 安卓推送沙箱
                pushMessage(json, action, x, APP_KEY_ANDROID, SECRET_ANDROID, PlatFormEnum.ANDROID, PUSH_ENVIRONMENT_PROD);
            }
        });
        // IOS推送生产/沙箱
        iosRegIdList.stream().filter(x -> CollUtil.isNotEmpty(x))
                .forEach(x -> pushMessage(json, action, x, APP_KEY_IOS, SECRET_IOS, PlatFormEnum.IOS, pushEnvironment));
        return JSONUtil.createObj().set("code", CommonRespDef.ERROR_CODE_0_DESP);
    }

    /**
     * @param json         推送内容(标题与内容)
     * @param action       自定义内容
     * @param regIds       单次推送的register_id数组
     * @param appKey       app_key
     * @param masterSecret Secret
     * @param systemName   操作系统名称;IOS、安卓
     * @param environment  环境区分(IOS:false 测试环境、true:生产环境)
     * @Description: 推送的内容封装
     */
    private static void pushMessage(JSONObject json, String action, List<String> regIds,
                                    String appKey, String masterSecret,
                                    PlatFormEnum systemName, boolean environment) {
        AppPushParam appPushParam = new AppPushParam();
        // 设置推送的平台
        List<PlatFormEnum> platformList = new ArrayList<PlatFormEnum>();
        platformList.add(systemName);
        appPushParam.setPlatform(platformList);
        // 设置开发环境 极光推送只是对ios有效
        appPushParam.setPushEnvironment(environment);
        // 设置推送目标 如果不设置就是广播模式
        Map<String, String[]> audience = new HashMap<String, String[]>();
        String[] redIdArray = ArrayUtil.toArray(regIds, String.class);
        // 指定设备的registration_id进行发送 "XXXXXXX"
        audience.put("registration_id", redIdArray);
        appPushParam.setAudience(audience);
        // 安卓推送
        JiGuangConfig appPushConfig = new JiGuangConfig(masterSecret, appKey, PUSH_URL);
        // 推送弹窗的信息内容
        appPushParam.setTitle(json.getStr("title"));
        appPushParam.setMessage(json.getStr("content"));
        // 推送的自定义信息
        Map<String, String> homeExtrasInfo = new HashMap<String, String>();
        homeExtrasInfo.put("action", action);
        appPushParam.setExtras(homeExtrasInfo);
        // 设置离线消息保留时长(秒)
        appPushParam.setTimeToLive(60);
        AppPushManger manger = new AppPushManger(new JiGuangPushImpl(appPushConfig));
        manger.push(appPushParam);
    }
    
     /**
     * 按regIdList进行安卓推送(自定义消息推送)
     */
    public static JSONObject pushJiGuangCustomMessage(JSONObject dataJson, 
                                                      List<String> regIdList, 
                                                      String action) {
        List<String> androidReg = regIdList.parallelStream()
                .filter(x -> StrUtil.isNotBlank(x))
                .filter(x -> ANDROID_EVN == x.charAt(2))
                .distinct()
                .collect(Collectors.toList());
        List<List<String>> androidRegIdList = CollUtil.split(androidReg, MAX_SIZE);
        LOGGER.info("JiGuang push count user,android={}", androidReg.size());
        androidRegIdList.stream().filter(x -> CollUtil.isNotEmpty(x)).forEach(x -> {
            if (pushEnvironment) {
                // 安卓推送生产
                pushCustomMessage(dataJson, action, x, APP_KEY_ANDROID_PROD, SECRET_ANDROID_PROD, PlatFormEnum.ANDROID, PUSH_ENVIRONMENT_PROD);
            } else {
                // 安卓推送沙箱
                pushCustomMessage(dataJson, action, x, APP_KEY_ANDROID, SECRET_ANDROID, PlatFormEnum.ANDROID, PUSH_ENVIRONMENT_PROD);
            }
        });
        return JSONUtil.createObj().set("code", CommonRespDef.ERROR_CODE_0_DESP);
    }

    private static void pushCustomMessage(JSONObject dataJson, String action, List<String> regIds,
                                          String appKey, String masterSecret,
                                          PlatFormEnum systemName, boolean environment) {
        AppPushParamCustom appPushParamCustom = new AppPushParamCustom();
        // 设置推送的平台
        List<PlatFormEnum> platformList = new ArrayList<>();
        platformList.add(systemName);
        appPushParamCustom.setPlatform(platformList);
        // 设置开发环境 极光推送只是对ios有效
        appPushParamCustom.setPushEnvironment(environment);
        // 设置推送目标 如果不设置就是广播模式
        Map<String, String[]> audience = new HashMap<>();
        String[] redIdArray = ArrayUtil.toArray(regIds, String.class);
        // 指定设备的registration_id进行发送
        audience.put("registration_id", redIdArray);
        appPushParamCustom.setAudience(audience);
        // 安卓推送
        JiGuangConfig appPushConfig = new JiGuangConfig(masterSecret, appKey, PUSH_URL);
        // 推送Message的内容
        appPushParamCustom.setTitle(dataJson.getStr("title"));
        appPushParamCustom.setMessage(dataJson.getStr("message"));
        appPushParamCustom.setContentType(dataJson.getStr("contentType"));
        // 推送的自定义信息
        Map<String, String> extrasInfo = new HashMap<>();
        extrasInfo.put("action", action);
        appPushParamCustom.setExtras(extrasInfo);

        AppPushManger manger = new AppPushManger(new JiGuangPushImpl(appPushConfig));
        manger.pushCustomMessage(appPushParamCustom);
    }
}

3.3 定义三个domain文件

3.3.1 AppPushManger

public class AppPushManger {
    private IAppPush appPush;
    public AppPushManger(IAppPush appPush) {
        this.appPush = appPush;
    }
    public boolean push(AppPushParam appPushParam) {
        return appPush.push(appPushParam);
    }
    public boolean pushCustomMessage(AppPushParamCustom appPushParamCustom) {
        return appPush.pushCustomMessage(appPushParamCustom);
    }
}

3.3.2 定义AppPushParam

@Getter
@Setter
public class AppPushParam {
    /**
     * 推送标题
     */
    private String title;
    /**
     * 推送消息 空字符串,则表示不展示到通知栏。
     */
    private String message;
    /**
     * 发送平台 android ios
     */
    private List<PlatFormEnum> platform;
    /**
     * 推送目标 如果为null,则是广播
     */
    private Map<String, String[]> audience;
    /**
     * 离线消息保留时长(秒)
     */
    private int timeToLive;
    /**
     * True 表示推送生产环境,False 表示要推送开发环境
     */
    private boolean pushEnvironment;
    /**
     * 额外的参数
     */
    private Map<String, String> extras;
}

3.3.3 定义AppPushParamCustom

@Getter
@Setter
public class AppPushParamCustom {
    /**
     * 推送标题
     */
    private String title;
    /**
     * 表示不展示到通知栏。
     */
    private String message;
    /**
     * 发送平台 android ios
     */
    private List<PlatFormEnum> platform;
    /**
     * 推送目标 如果为null,则是广播
     */
    private Map<String, String[]> audience;
    /**
     * 额外的参数
     */
    private Map<String, String> extras;
    /**
     * True 表示推送生产环境,False 表示要推送开发环境
     */
    private boolean pushEnvironment;
    /**
     * 内容类型
     */
    private String contentType;
    /**
     * 离线消息保留时长(秒)
     */
    // private int timeToLive;
}

3.4 定义两个配置文件

3.4.1 定义AppPushConfig文件

public interface AppPushConfig {
    public String getAppKey();
    public String getPushUrl();
    public String getMasterSecret();
} 	 	 	

3.4.2 定义JiGuangConfig文件

@Getter
@Setter
public class JiGuangConfig implements AppPushConfig {
    private String masterSecret = "";
    private String appKey = "";
    private String pushUrl = "";
    public JiGuangConfig(String masterSecret, String appKey, String pushUrl) {
        super();
        this.masterSecret = masterSecret;
        this.appKey = appKey;
        this.pushUrl = pushUrl;
    }
}

3.6 定义推送服务的接口

/** 推送服务的接口 主要用于AppPushManger(门面)调用 */
public interface IAppPush {
    /** app 推送通知消息服务  */
    boolean push(AppPushParam appPushParam);
    /** app 推送自定义消息服务  */
    boolean pushCustomMessage(AppPushParamCustom appPushParamCustom);
}

3.7 定义推送服务的抽象类

推送服务IAppPush的push 方法具体实现类:认证、参数转换、调用推送

 
public abstract class AbstractAppPush implements IAppPush {
    private static Log LOGGER = LogFactory.get();
    protected IAppPushParamConverter appPushParamConverter;
    protected AppPushConfig appPushConfig;

    @Override
    public boolean push(AppPushParam appPushParam) {
        String pushParamsJsonStr = convertAppPushParam(appPushParam);
        String authorization = getAuthorization(appPushConfig);
        String returnJson = post(appPushConfig, authorization, pushParamsJsonStr);
        if (returnJson != null) {
            LOGGER.info("app push success:" + returnJson);
            return true;
        }
        LOGGER.info("app push fail!");
        return false;
    }
    @Override
    public boolean pushCustomMessage(AppPushParamCustom appPushParamCustom) {
        String pushParamsJsonStr = convertCustomMessageAppPushParam(appPushParamCustom);
        String authorization = getAuthorization(appPushConfig);
        String returnJson = post(appPushConfig, authorization, pushParamsJsonStr);
        if (returnJson != null) {
            LOGGER.info("app push custom message success:" + returnJson);
            return true;
        }
        LOGGER.info("app push custom message fail!");
        return false;
    }
    /** 认证信息获取 */
    public abstract String getAuthorization(AppPushConfig appPushConfig);
    /**参数转换 */
    public abstract String convertAppPushParam(AppPushParam appPushParam);
    /**(自定义推送内容)参数转换   */
    public abstract String convertCustomMessageAppPushParam(AppPushParamCustom appPushParamCustom);
    /**调用推送第三方服务 */
    public abstract String post(AppPushConfig appPushConfig, String authorization, String pushParmJsonStr);
}

3.8 定义极光推送实现类JiGuangPushImpl

 
public class JiGuangPushImpl extends AbstractAppPush {
    public JiGuangPushImpl(AppPushConfig appPushConfig) {
        super.appPushParamConverter = new JiGuangAppPushParamConverter();
        super.appPushConfig = appPushConfig;
    }

    @Override
    public String getAuthorization(AppPushConfig appPushConfig) {
        String appKey = appPushConfig.getAppKey();
        String masterSecret = appPushConfig.getMasterSecret();
        String base64_auth_string = Base64.encode(StrUtil.concat(true, appKey, ":", masterSecret).getBytes());
        String authorization = "Basic " + base64_auth_string;
        return authorization;
    }

    @Override
    public String convertAppPushParam(AppPushParam appPushParam) {
        String pushParamsJsonStr = appPushParamConverter.convert(appPushParam);
        return pushParamsJsonStr;
    }

    @Override
    public String convertCustomMessageAppPushParam(AppPushParamCustom appPushParamCustom) {
        String pushParamsJsonStr = appPushParamConverter.convertCustomMessage(appPushParamCustom);
        return pushParamsJsonStr;
    }

    @Override
    public String post(AppPushConfig appPushConfig, String authorization, String pushParmJsonStr) {
        HashMap<String, String> headMap = new HashMap<>();
        headMap.put("Authorization", authorization.trim());
        String returnJson = HttpUtil.createPost(appPushConfig.getPushUrl())
                .addHeaders(headMap)
                .timeout(1000)
                .body(pushParmJsonStr)
                .execute().body();
        return returnJson;
    }
}

3.9 定义两个转换工具的接口

public interface IAppPushParamConverter {
    public String convert(AppPushParam appPushParam);
    public String convertCustomMessage(AppPushParamCustom appPushParamCustom);
}

3.10 定义两个转换工具的实现类

极光推送AppPushParam 参数json数据转换类

public class JiGuangAppPushParamConverter implements IAppPushParamConverter {
    private static Log LOGGER = LogFactory.get();

    @Override
    public String convert(AppPushParam appPushParam) {
        JSONObject pushParamJson = new JSONObject();
        List<PlatFormEnum> platformList = appPushParam.getPlatform();
        Map<String, String[]> audienceMap = appPushParam.getAudience();
        Map<String, String> extras = appPushParam.getExtras();
        // 构建推送平台信息
        JSONArray platform = buildPlatform(platformList, new JSONArray());
        // 构建推送目标信息
        JSONObject audience = buildAudience(audienceMap, new JSONObject());
        // 构建安卓的推送信息
        JSONObject notification = new JSONObject();
        buildAndroidInfo(notification, extras, platformList, appPushParam);
        buildIosInfo(notification, extras, platformList, appPushParam);
        // 构建IOS参数信息
        JSONObject options = new JSONObject();
        buildOptions(options, appPushParam);
        // 设置推送平台信息
        setPlatform(platform, pushParamJson);
        // 设置推送目标信息
        setAudience(audience, pushParamJson);
        // 设置推送信息
        pushParamJson.set("notification", notification);
        // 设置options信息
        pushParamJson.set("options", options);
        LOGGER.info("app push json:" + pushParamJson.toString());
        return pushParamJson.toString();
    }

    @Override
    public String convertCustomMessage(AppPushParamCustom appPushParamCustom) {
        JSONObject pushParamJson = new JSONObject();
        // 构建推送平台信息
        List<PlatFormEnum> platformList = appPushParamCustom.getPlatform();
        JSONArray platform = buildPlatform(platformList, new JSONArray());
        // 设置推送平台信息
        setPlatform(platform, pushParamJson);
        // 构建推送目标信息
        Map<String, String[]> audienceMap = appPushParamCustom.getAudience();
        JSONObject audience = buildAudience(audienceMap, new JSONObject());
        // 设置推送目标信息
        setAudience(audience, pushParamJson);
        // 构建安卓的推送信息
        Map<String, String> extras = appPushParamCustom.getExtras();
        pushParamJson.set("message", buildCustomMessageAndroidInfo(extras, platformList, appPushParamCustom));
        LOGGER.info("app push android custom message json:" + JSONUtil.toJsonStr(pushParamJson));
        return pushParamJson.toString();
    }
    private static void setAudience(JSONObject audience, JSONObject pushParamJson) {
        pushParamJson.set("audience", audience == null ? "all" : audience);
    }
    private static void setPlatform(JSONArray platform, JSONObject pushParamJson) {
        pushParamJson.set("platform", platform == null ? "all" : platform);
    }
    private static void buildOptions(JSONObject options, AppPushParam appPushParam) {
        options.set("time_to_live", appPushParam.getTimeToLive());
        options.set("apns_production", appPushParam.isPushEnvironment());
    }
    private static void buildIosInfo(JSONObject notification, Map<String, String> extras,
                                     List<PlatFormEnum> platformList, AppPushParam appPushParam) {
        if (platformList != null && platformList.size() > 0 && platformList.contains(PlatFormEnum.IOS)) {
            // ios通知内容
            JSONObject ios = new JSONObject();
            // ios.set("alert", appPushParam.getMessage());
            ios.set("alert", JSONUtil.createObj().
                    set("title", appPushParam.getTitle()).
                    set("body", appPushParam.getMessage()));
            // 通知提示声音或警告通知
            ios.set("sound", "default");
            // 应用角标
            ios.set("badge", "0");
            // ios额外参数
            JSONObject ios_extras = new JSONObject();
            if (extras != null && extras.size() > 0) {
                for (Map.Entry<String, String> m : extras.entrySet()) {
                    ios_extras.set(m.getKey(), m.getValue());
                }
                // ios额外参数
                ios.set("extras", ios_extras);
            }
            notification.set("ios", ios);
        }
    }
    private static void buildAndroidInfo(JSONObject notification, Map<String, String> extras,
                                         List<PlatFormEnum> platformList, AppPushParam appPushParam) {
        if (platformList != null && platformList.size() > 0 && platformList.contains(PlatFormEnum.ANDROID)) {
            JSONObject android = new JSONObject();
            android.set("alert", appPushParam.getMessage());
            android.set("title", appPushParam.getTitle());
            // 设置通知栏样式
            android.set("builder_id", 1);
            // android额外参数
            JSONObject android_extras = new JSONObject();
            if (extras != null && extras.size() > 0) {
                for (Map.Entry<String, String> m : extras.entrySet()) {
                    android_extras.set(m.getKey(), m.getValue());
                }
            }
            // android额外参数
            android.set("extras", android_extras);
            notification.set("android", android);
        }
    }

    private static JSONObject buildCustomMessageAndroidInfo(Map<String, String> extras,
                                                            List<PlatFormEnum> platformList,
                                                            AppPushParamCustom appPushParamCustom) {
        JSONObject customMessage = new JSONObject();
        if (platformList != null && platformList.size() > 0 && platformList.contains(PlatFormEnum.ANDROID)) {
            customMessage.set("msg_content", appPushParamCustom.getMessage());
            customMessage.set("content_type", appPushParamCustom.getContentType());
            customMessage.set("title", appPushParamCustom.getTitle());
            // android额外参数
            JSONObject extrasJson = new JSONObject();
            if (extras != null && extras.size() > 0) {
                for (Map.Entry<String, String> m : extras.entrySet()) {
                    extrasJson.set(m.getKey(), m.getValue());
                }
            }
            customMessage.set("extras", extrasJson);
        }
        return customMessage;
    }
    /*  构建推送目标  */
    private static JSONObject buildAudience(Map<String, String[]> audienceMap, JSONObject audience) {
        if (audienceMap == null || audienceMap.size() == 0) {
            return null;
        }
        for (Map.Entry<String, String[]> m : audienceMap.entrySet()) {
            String[] value = m.getValue();
            // 平台
            JSONArray audienceArray = new JSONArray();
            for (String str : value) {
                audienceArray.add(str);
            }
            audience.set(m.getKey(), audienceArray);
        }
        return audience;
    }
    /**构建推送平台  */
    private static JSONArray buildPlatform(List<PlatFormEnum> platformList, JSONArray platform) {
        if (platformList != null && platformList.size() > 0) {
            for (PlatFormEnum platFormEnum : platformList) {
                String platformStr = platFormEnum.toString().toLowerCase();
                platform.add(platformStr);
            }
            return platform;
        } else {
            return null;
        }
    }
}

3.11 其他 - 定义消息推送平台枚举

public enum PlatFormEnum {
    ANDROID, IOS;
}

四、功能测试验证

4.1 测试第一种:通知消息

在这里插入图片描述

输出的log 省略,此处选择的是API
在这里插入图片描述

NotificationMessage{
	notificationId=516752241, 
	msgId='18100617394282282', 
	appkey='appkey', 
	notificationContent='我是XXXX项目的推送content', 
	notificationAlertType=-1, 
	notificationTitle='我是XXXX项目的推送title', 
	notificationSmallIcon='', 
	notificationLargeIcon='', 
	notificationExtras='{"action":"other msg"}', 
	notificationStyle=0, 
	notificationBuilderId=1, 
	notificationBigText='', 
	notificationBigPicPath='', 
	notificationInbox='', 
	notificationPriority=0, 
	notificationCategory='', 
	developerArg0='', 
	platform=0, 
	notificationChannelId='',
	displayForeground='', 
	notificationType=0', 
	inAppMsgType=1', 
	inAppMsgShowType=2', 
	inAppMsgShowPos=0', 
	inAppMsgTitle=, 
	inAppMsgContentBody=, 
	inAppType=0
}

4.2 测试第二种:自定义消息

在这里插入图片描述
输出的log 省略,此处选择的是API
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/360815.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《Qt6开发及实例》6-4 显示SVG格式图片

目录 一、简介与设计 1.1 简介 1.2 设计 二、SvgWidget 2.1 鼠标滚轮事件 三、svgwindow 四、MainWindow 一、简介与设计 1.1 简介 1、SVG 的英文全称是 Scalable Vector Graphics&#xff0c;即可缩放的矢量图形。它是由万维网联盟&#xff08;W3C&#xff09;在 200…

什么是循环依赖,spring是如何去解决循环依赖问题的?什么是三级缓存?【spring】

文章目录什么是循环依赖&#xff1f;什么是三级缓存&#xff1f;执行流程什么是循环依赖&#xff1f; 在我们的开发中&#xff0c;会不可避免的遇到Bean之间循环依赖的&#xff0c;所谓循环依赖&#xff0c;就是两个或者两个以上的Bean互相持有对方&#xff0c;这样在程序运行…

几个流畅阅读与标记PDF文件的顶级 PDF 注释器

使用 PDF 注释工具改变您修改 PDF 文档的方式。 PDF 注释器提供了广泛的对象集&#xff0c;用于对内容进行说明。PDF 注释器的目的范围从标记页面内容到添加有洞察力的功能&#xff08;如表单&#xff09;。 您可以在评论表中添加建议&#xff0c;例如 – 便签。注释是指在 P…

【假捻停线需求沟通】

假捻工单上停产按钮: 假捻工单上结批复产按钮: 这是目前MES系统具备的功能,但是MES的生产状态和SAP不同步,也就是说MES的A机台上的B订单还在生产,SAP把B订单结批,但是当你刷新页面时,SAP会取A机台上的最新订单数据,也就是B订单进行显示。 换言之,SAP结批不掉A机台上…

PX4之代码结构

PX4开源飞控是目前主流的开源飞控项目&#xff0c;被很多公司作为飞控开发的参考。也广泛被用于现在流行的evtol验证机的飞控&#xff0c;进行初步的飞行验证。可能大多数AAM以及UAM都离不开PX4。 项目代码可以从github下载 $ git clone --recursive GitHub - PX4/PX4-Autopil…

构建Yocto项目

前言Yocto Project简称YP, 是一个致力于帮助开发者构建自己的Linux嵌入式的项目&#xff0c;除了Yocto还有其它的开源项目例如&#xff1a;Debian&#xff0c;著名的Ubuntu就是基于Debian来构建的发行版。什么是Yocto Project&#xff1f;Yocto Project (YP)是一个开源协作项目…

分类预测 | MATLAB实现WOA-CNN-GRU鲸鱼算法优化卷积门控循环单元数据分类预测

分类预测 | MATLAB实现WOA-CNN-GRU鲸鱼算法优化卷积门控循环单元数据分类预测 目录分类预测 | MATLAB实现WOA-CNN-GRU鲸鱼算法优化卷积门控循环单元数据分类预测分类效果基本描述模型描述程序设计参考资料分类效果 基本描述 1.Matlab实现WOA-CNN-GRU多特征分类预测&#xff0c;…

excel图表设计:有关表头的相关问题汇总

虽然表头很简单&#xff0c;但因为有不同样式需要、不同打印需要&#xff0c;也有很多人在表头上浪费了很多时间。文章总结了8种表头的典型形式和问题&#xff0c;让大家从此不再为表头浪费时间。每个excle表格都有一个表头&#xff0c;适合的表头能够让表格美观、逻辑清晰&…

2023年PMP考试内容有哪些?怎么备考?

PMP考试也叫项目管理专业人士资格认证&#xff0c;要想参加2023年PMP考试&#xff0c;考生还需先对PMP考试内容提前进行了解&#xff0c;那么2023年PMP考试内容有哪些呢&#xff1f;我们先看下官方公告&#xff1a;大白话说就是虽然2023年PMBOK第七版就要在大陆地区正式投入使用…

Android项目如何将同一套代码应用于多个项目(变种打包)

如果你的公司开发了一个项目&#xff0c;但是这个项目应用于不同的客户&#xff0c;根据客户的不同要求&#xff0c;会改动一些东西&#xff0c;之前我们的做法是直接将这套代码复制出来&#xff0c;替换logo,applicationId,以及一些基本配置&#xff08;如baseurl,等配置&…

vue3.2中使用swiper缩略图轮播教程

介绍 在vue3 中使用 swiper 实现缩略图的轮播图效果,具体如下图所示: 使用 切换到项目终端 ,输入命令 npm install swiper --save , 进行安装在 main.js里,引入 swiper.css并使用,具体代码如下;import {createApp } from vue import App from ./App.vue import router…

微信公众号抽奖怎么做_分享微信抽奖小程序制作的好处

在H5游戏中&#xff0c;抽奖是最受消费者喜爱的模式之一。将H5微信抽奖活动结合到营销中&#xff0c;可以带来意想不到的效果&#xff0c;带流量和曝光率&#xff0c;所以许多企业也会在做活动时添加上不同类型的H5微信抽奖活动。编辑那么&#xff0c;新手怎么搭建微信抽奖活动…

前端二面react面试题集锦

react diff 算法 我们知道React会维护两个虚拟DOM&#xff0c;那么是如何来比较&#xff0c;如何来判断&#xff0c;做出最优的解呢&#xff1f;这就用到了diff算法 diff算法的作用 计算出Virtual DOM中真正变化的部分&#xff0c;并只针对该部分进行原生DOM操作&#xff0c;而…

学成在线项目笔记

业务层开发 DAO开发示例 生成实体类对应的mapper和xml文件 定义MybatisPlusConfig&#xff0c;用于扫描mapper和配置分页拦截器 MapperScan("com.xuecheng.content.mapper") Configuration public class MybatisPlusConfig {Beanpublic MybatisPlusInterceptor myb…

Datawhale团队第九期录取名单!

Datawhale团队 公示&#xff1a;Datawhale团队成员Datawhale成立四年了&#xff0c;从一开始的12个人&#xff0c;学习互助&#xff0c;到提议成立开源组织&#xff0c;做更多开源的事情&#xff0c;帮助更多学习者&#xff0c;也促使我们更好地成长。于是有了我们的使命&#…

【Spring Boot 原理分析】- 自动配置

【Spring Boot 原理分析】- 自动配置 Condition 注解 Condition 是 Spring 4.0 增加的条件判断功能&#xff0c;通过这个功能可以实现选择的创建 Bean 操作 &#x1f451; 我们在使用 Spring 的时候&#xff0c;只需导入某个依赖的坐标&#xff0c;就可以直接通过 Autwired 注…

零基础小白如何学会数据分析?

随着数字经济、大数据时代的发展&#xff0c;数据已然成为当下时代最重要的盈利资源&#xff0c;让企业在做决策和计划方案时更有针对性和依据&#xff0c;能提前预测市场发展方向&#xff0c;做好布局。由此而产生的数据分析岗位也逐渐被更多企业重视&#xff0c;特别是中大型…

社招中级前端笔试面试题总结

HTTP世界全览 互联网上绝大部分资源都使用 HTTP 协议传输&#xff1b;浏览器是 HTTP 协议里的请求方&#xff0c;即 User Agent&#xff1b;服务器是 HTTP 协议里的应答方&#xff0c;常用的有 Apache 和 Nginx&#xff1b;CDN 位于浏览器和服务器之间&#xff0c;主要起到缓存…

Notion AI是什么?和chatgpt比哪个好?

最近对于人工智能的热度可谓是前所未有的高涨&#xff0c;毕竟现在的人工智能发展是越来越快&#xff0c;能做的事情也是越来越多&#xff0c;不再是那种低等的假智能小爱同学和siri那种。今天我们主要来聊聊Notion AI和chatgpt吧&#xff0c;Notion AI是什么&#xff1f;和cha…

leaflet 删除所有的marker图层,保留其他图层(085)

第085个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+leaflet项目中清除所有的marker图层,保留其他图层,详情请参考源代码。这里面主要用到了(layer instanceof L.Marker ,注意 L.Marker中Marker首字母要大写。 直接复制下面的 vue+leaflet源代码,操作2分钟即可运行…