app 整合第三方實現訊息推播功能

2020-10-25 10:02:21

app 整合第三方實現訊息推播功能

國內推播平臺較多,常見的有:

  • 極光推播
  • 阿里雲推播
  • 友盟推播
  • 騰訊雲推播
  • 個推推播

個人目前已經做了兩次推播了,都是用的極光推播,我並不是為極光打廣告啊,是因為極光有免費版的,哈哈,其他的平臺沒用過所以不太清楚有沒有免費版的,這次總結一下我整合極光推播的過程,以後忘了的話還可以再看看

一:註冊登入極光官網(最好是公司賬號,手機號)

二:登入服務中心(頭像下邊),進入開發者平臺,點選訊息推播

在這裡插入圖片描述

三:建立應用,獲取AppKeyMaster Secret,以便之後在你的 yml 組態檔中進行設定

四:推播設定,這時候需要和前端溝通,獲取安卓應用包名及 ios 證書

在這裡插入圖片描述
在這裡插入圖片描述

五:設定完成後,就開始咱們的設定和業務程式碼啦,注意,之下程式碼可以參照,有些推播業務程式碼中可能不包括

pom依賴新增:

<!--極光推播-->
        <dependency>
            <groupId>cn.jpush.api</groupId>
            <artifactId>jpush-client</artifactId>
            <version>3.3.10</version>
        </dependency>
        <dependency>
            <groupId>cn.jpush.api</groupId>
            <artifactId>jiguang-common</artifactId>
            <version>1.1.3</version>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>RELEASE</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

config 組態檔:JPushConfig

package cn.xof.config;

import cn.jpush.api.JPushClient;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;

@Configuration
@Data
@ConfigurationProperties(prefix = "xym.push")
public class JPushConfig {

	private String appkey;
	private String secret;
	private boolean apns;

	private JPushClient jPushClient;

	/**
	 * 推播使用者端
	 * @return
	 */
	@PostConstruct
	public void initJPushClient() {
		jPushClient = new JPushClient(secret, appkey);
	}

	/**
	 * 獲取推播使用者端
	 * @return
	 */
	public JPushClient getJPushClient() {
		return jPushClient;
	}

	/**
	 * 區分開發和線上環境
	 * @return
	 */
	public boolean getApns() {
		return apns;
	}
}

PushService:

package cn.xof.tzy.service;


import cn.xof.tzy.entity.PushBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 推播服務
 * 封裝業務功能相關
 * @author xym
 */
@Service
public class PushService {

	/** 一次推播最大數量 (極光限制1000) */
	private static final int max_size = 800;

	@Autowired
	private JPushService jPushService;

	/**
	 * 推播全部, 不支援附加資訊
	 * @author xym
	 * @return
	 */
	public boolean pushAll(PushBean pushBean){
		return jPushService.pushAll(pushBean);
	}

	/**
	 * 推播全部ios
	 * @author xym
	 * @return
	 */
	public boolean pushIos(PushBean pushBean){
		return jPushService.pushIos(pushBean);
	}

	/**
	 * 推播ios 指定id
	 * @author xym
	 * @return
	 */
	public boolean pushIos(PushBean pushBean, String ... registids){
		registids = checkRegistids(registids); // 剔除無效registed
		while (registids.length > max_size) { // 每次推播max_size個
			jPushService.pushIos(pushBean, Arrays.copyOfRange(registids, 0, max_size));
			registids = Arrays.copyOfRange(registids, max_size, registids.length);
		}
		return jPushService.pushIos(pushBean, registids);
	}

	/**
	 * 推播全部android
	 * @author xym
	 * @return
	 */
	public boolean pushAndroid(PushBean pushBean){
		return jPushService.pushAndroid(pushBean);
	}

	/**
	 * 推播android 指定id
	 * @author xym
	 * @return
	 */
	public boolean pushAndroid(PushBean pushBean, String ... registids){
		registids = checkRegistids(registids); // 剔除無效registed
		while (registids.length > max_size) { // 每次推播max_size個
			jPushService.pushAndroid(pushBean, Arrays.copyOfRange(registids, 0, max_size));
			registids = Arrays.copyOfRange(registids, max_size, registids.length);
		}
		return jPushService.pushAndroid(pushBean, registids);
	}

	/**
	 * 剔除無效registed
	 * @author xym [2016年7月15日 下午4:03:31]
	 * @param registids
	 * @return
	 */
	private String[] checkRegistids(String[] registids) {
		List<String> regList = new ArrayList<String>(registids.length);
		for (String registid : registids) {
			if (registid!=null && !"".equals(registid.trim())) {
				regList.add(registid);
			}
		}
		return regList.toArray(new String[0]);
	}
}

JPushService:

package cn.xof.tzy.service;


import cn.jiguang.common.resp.APIConnectionException;
import cn.jiguang.common.resp.APIRequestException;
import cn.jpush.api.push.PushResult;
import cn.jpush.api.push.model.Options;
import cn.jpush.api.push.model.Platform;
import cn.jpush.api.push.model.PushPayload;
import cn.jpush.api.push.model.audience.Audience;
import cn.jpush.api.push.model.notification.IosNotification;
import cn.jpush.api.push.model.notification.Notification;
import cn.xof.config.JPushConfig;
import cn.xof.tzy.entity.PushBean;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 極光推播
 * 封裝第三方api相關
 * @author xym
 */
@Service
@Slf4j
public class JPushService {
	@Autowired
	private JPushConfig jPushConfig;

	//@Autowired
	//private  TbPushHistoryService pushHistoryService;


	/**
	 * 廣播 (所有平臺,所有裝置, 不支援附加資訊)
	 * @author xym
	 * @param pushBean 推播內容
	 * @return
	 */
	public boolean pushAll(PushBean pushBean){
		return sendPush(PushPayload.newBuilder()
	            .setPlatform(Platform.all())
	            .setAudience(Audience.all())
	            .setNotification(Notification.alert(pushBean.getAlert()))
	            .setOptions(Options.newBuilder().setApnsProduction(jPushConfig.getApns()).build())
	            .build());
	}

	/**
	 * ios廣播
	 * @author xym
	 * @param pushBean 推播內容
	 * @return
	 */
	public boolean pushIos(PushBean pushBean){
		return sendPush(PushPayload.newBuilder()
				.setPlatform(Platform.ios())
				.setAudience(Audience.all())
				.setNotification(Notification.ios(pushBean.getAlert(), pushBean.getExtras()))
				.setOptions(Options.newBuilder().setApnsProduction(jPushConfig.getApns()).build())
                .build());
	}

	/**
	 * ios通過registid推播 (一次推播最多 1000 個)
	 * @author xym
	 * @param pushBean 推播內容
	 * @param registids 推播id
	 * @return
	 */
	public boolean pushIos(PushBean pushBean, String ... registids){
		return sendPush(PushPayload.newBuilder()
				.setPlatform(Platform.ios())
				//.setAudience(Audience.registrationId(registids))
				.setAudience(Audience.alias(registids))
				//.setNotification(Notification.ios(pushBean.getAlert(), pushBean.getExtras()))
                .setNotification(Notification.newBuilder()
                        .addPlatformNotification(IosNotification.newBuilder()
                                .setAlert(pushBean.getAlert())
                                .setBadge(1)
                                .setSound("default")
								.addExtras(pushBean.getExtras())
                                .build())
                        .build())
				.setOptions(Options.newBuilder().setApnsProduction(jPushConfig.getApns()).build())
				.build());
	}


	/**
	 * android廣播
	 * @author xym
	 * @param pushBean 推播內容
	 * @return
	 */
	public boolean pushAndroid(PushBean pushBean){
		return sendPush(PushPayload.newBuilder()
                .setPlatform(Platform.android())
                .setAudience(Audience.all())
                .setNotification(Notification.android(pushBean.getAlert(), pushBean.getTitle(), pushBean.getExtras()))
                .setOptions(Options.newBuilder().setApnsProduction(jPushConfig.getApns()).build())
                .build());
	}


	/**
	 * android通過registid推播 (一次推播最多 1000 個)
	 * @author xym
	 * @param pushBean 推播內容
	 * @param registids 推播id
	 * @return
	 */
	public boolean pushAndroid(PushBean pushBean, String ... registids){
		return sendPush(PushPayload.newBuilder()
                .setPlatform(Platform.android())
				//pushPayloadBuilder.setAudience(Audience.alias(alias.toString()));
                .setAudience(Audience.alias(registids))
               // .setAudience(Audience.registrationId(registids))
                .setNotification(Notification.android(pushBean.getAlert(), pushBean.getTitle(), pushBean.getExtras()))
                .setOptions(Options.newBuilder().setApnsProduction(jPushConfig.getApns()).build())
                .build());
	}
	//PushPayload

	/**
	 * 呼叫api推播
	 * @author xym
	 * @param pushPayload 推播實體
	 * @return
	 */
	private boolean sendPush(PushPayload pushPayload){
		//pushHistoryService
		//TbPushHistory pushHistory = new TbPushHistory();
		JsonParser parse =new JsonParser();  //建立json解析器
		JsonObject json=(JsonObject) parse.parse(pushPayload.toString());  //建立jsonObject物件
		log.info("傳送極光推播請求: {}", pushPayload);
		PushResult result = null;
		//PushBean pushBean=new PushBean();
		try{
			result = jPushConfig.getJPushClient().sendPush(pushPayload);
		} catch (APIConnectionException e) {
			log.error("極光推播連線異常: ",e.isReadTimedout());
			return  false;
		} catch (APIRequestException e) {
			log.error("極光推播請求異常: ", e.getErrorMessage());
			return  false;
		}
		String platform = json.get("platform").toString();
		//pushHistory.setCreateTime(new Date());
		//pushHistory.setDeviceType(platform);
	/*	if (platform!="all")
		{
			String alias = json.get("audience").getAsJsonObject().get("alias").toString();
			pushHistory.setAlias(alias);
		}*/
		//String notification = json.get("notification").getAsJsonObject().get("android").getAsJsonObject().get("alert").toString();
		String notification = json.get("notification").toString();
		//pushHistory.setMessage(notification);
		String options = json.get("options").toString();
		//pushHistory.setExtras(options);
		if (result!=null && result.isResultOK()) {
			//pushHistory.setStatus(0);
			//pushHistoryService.insert(pushHistory);
			//String alias2 = json.get("notification").getAsJsonObject().get("android").getAsJsonObject().get("title").toString();
			//String alias3 = json.get("options").getAsJsonObject().get("sendno").toString();
			//String alias4 = json.get("options").getAsJsonObject().get("apns_production").toString();
			//JsonObject result=json.get("result").getAsJsonObject();

			//JSONObject object = JSONObject.parseObject(pushPayload.toString());
		//	JsonObject result=json.get("result").getAsJsonObject();
			//Object platform = object.get("platform");
			//Object audience = object.get("audience");
			//Object notification = object.get("notification");
			//object.get("options");
			log.info("極光推播請求成功: {}", result);
			return true;
		}else {
			//pushHistory.setStatus(1);
			//pushHistoryService.insert(pushHistory);
			log.info("極光推播請求失敗: {}", result);
			return false;
		}
	}
}

PushController:

package cn.xof.tzy.controller;
import cn.xof.common.Result;
import cn.xof.tzy.entity.PushBean;
import cn.xof.tzy.service.PushService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;

@RestController
@RequestMapping("/push")
@Slf4j
@CrossOrigin
@Api(value ="極光推播",description = "極光推播")
public class PushController {

	@Autowired
	private PushService pushService;

	/**
	 * 推播全部(包括ios和android)
	 * @param pushBean
	 * @return
	 */
	@ApiOperation("推播全部(包括ios和android")
	@RequestMapping(value="/all", method= RequestMethod.POST)
	public Result pushAll(@RequestBody PushBean pushBean) {
		if (pushService.pushAll(pushBean)){
			return Result.success("推播成功!");
		}else {
			return Result.failure("推播失敗!");
		}

	}

	/**
	 * 推播全部ios
	 * @param pushBean
	 * @return
	 */
	@ApiOperation("推播全部ios")
	@RequestMapping(value="/ios/all", method= RequestMethod.POST)
	public Result pushIos(PushBean pushBean){
		if (pushService.pushIos(pushBean)){
			return Result.success("推播成功!");
		}else {
			return Result.failure("推播失敗!");
		}
	}

	/**
	 * 推播指定ios
	 * @param pushBean
	 * @return
	 */
	@ApiOperation("推播指定ios,多個別名ID")
	@RequestMapping(value="/ios", method= RequestMethod.POST)
	public Result pushIos(PushBean pushBean, String[] registerids){
		 if(pushService.pushIos(pushBean, registerids)){
			 return Result.success("推播成功!");
		 }else {
			 return Result.failure("推播失敗!");
		 }
	}

	/**
	 * 推播全部android
	 * @param pushBean
	 * @return
	 */
	@ApiOperation("推播全部android")
	@RequestMapping(value="/android/all", method= RequestMethod.POST)
	public Result pushAndroid(PushBean pushBean){
		if(pushService.pushAndroid(pushBean)){
			return Result.success("推播成功!");
		}else {
			return Result.failure("推播失敗!");
		}
	}

	/**
	 * 推播指定android
	 * @param pushBean
	 * @return
	 */
	@ApiOperation("推播指定android,多個別名ID")
	@RequestMapping(value="/android", method= RequestMethod.POST)
	public Result pushAndroid(PushBean pushBean, String[] registerids){
		if(pushService.pushAndroid(pushBean, registerids)){
			return Result.success("推播成功!");
		}else {
			return Result.failure("推播失敗!");
		}
	}

	@ApiOperation("多個別名ID,全裝置推播")
	@RequestMapping(value="/allbyids", method= RequestMethod.POST)
	public Result pushAllbyids(@RequestBody PushBean pushBean, String[] registerids){
		if(pushService.pushAndroid(pushBean, registerids)){
			log.info(registerids.toString()+"指定別名Android推播成功");

			log.error(registerids.toString()+"指定別名Android推播失敗!");
		}
		if(pushService.pushIos(pushBean, registerids)){
			log.info(registerids.toString()+"指定別名Android推播成功");
		}else {
			log.error(registerids.toString()+"指定別名Android推播失敗!");
		}
		return Result.success("推播成功!");
	}
	

	//定時任務,每天下午2點,推播全部(包括ios和android)
	@Scheduled(cron = "0 0 14 * * ?")
	public void pushing(){
		PushBean pushBean = new PushBean();
		//可選,通知標題
		pushBean.setTitle("");
		//必填, 通知內容
		pushBean.setAlert("速~來~賺~錢~一大波任務來襲!");
		if (pushService.pushAll(pushBean)){
			log.info("{},推播成功!", LocalDateTime.now());
		}else {
			log.error("{},推播失敗!", LocalDateTime.now());
		}
	}
}

PushBean:

package cn.xof.tzy.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Map;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class PushBean {

	// 必填, 通知內容, 內容可以為空字串,則表示不展示到通知欄。
	private String alert;
	// 可選, 附加資訊, 供業務使用。
	private Map<String, String> extras;
	//android專用// 可選, 通知標題	如果指定了,則通知裡原來展示 App名稱的地方,將展示成這個欄位。
	private String title;

}

yml 新增設定:

  #極光推播
  push:
    appkey: bdbdabc57feec51b567620xx
    secret: a291ae194a16e7166575f1xx
    apns: false

記得在你的 config 組態檔裡把 xym 改成你自己的:@ConfigurationProperties(prefix = 「xym.push」)

六:測試
你可以在開發者服務裡測試(分類:1、tag 2、alias 3、全部 , 發推播的時候在下方有選擇),也可以在程式碼中進行測試,不過如果你還未購買的話,建議使用指定 android 或者指定 ios 介面測試,比如 JPushService 裡的 :

public boolean pushAndroid(PushBean pushBean, String ... registids){
		return sendPush(PushPayload.newBuilder()
                .setPlatform(Platform.android())
				//pushPayloadBuilder.setAudience(Audience.alias(alias.toString()));
                .setAudience(Audience.alias(「666」))
               // .setAudience(Audience.registrationId(registids))
                .setNotification(Notification.android(pushBean.getAlert(), pushBean.getTitle(), pushBean.getExtras()))
                .setOptions(Options.newBuilder().setApnsProduction(jPushConfig.getApns()).build())
                .build());
	}

點選高階功能
點選高階功能

在這裡插入圖片描述
在這裡插入圖片描述
各位多試試,挺好玩的,接下來就坐等 android 和 ios 端的小夥伴整合了

之前極光能按月收費,也挺划算的,現在是按年48000,折扣0.6折後28800,這個看公司買不買了,不買的話就用免費版的,不過到時候需要技術的小夥伴設定傳送類別了,另外有興趣的可以看看其他平臺的價格,歡迎留言評論