以fcm token为设备唯一标识推送
<dependency>
<groupId>com.google.firebase</groupId>
<artifactId>firebase-admin</artifactId>
<version>7.0.1</version>
</dependency>
if(android_tokens.size()>0){
if(!FireBaseUtil.isInit(appName)) {
String dataUrl = "";
//初始化FirebaseApp ,ushConfig.ANDROID_CERT_PATH是证书地址
FireBaseUtil.initSDK(PushConfig.ANDROID_CERT_PATH, dataUrl, appName);
}
FireBaseUtil.pushBatch(android_tokens,appName,pushMsg.getTitle(),pushMsg.getBody(),"OPEN_STOCK_ACTIVITY", pushMsg.getExtendParm());
// FireBaseUtil.pushSingle(appName, token, title, body); //单推
}
工具类
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.alibaba.fastjson.JSON;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;
import com.google.firebase.messaging.*;
import com.google.firebase.messaging.AndroidConfig.Builder;
import com.google.gson.JsonObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
/**
* @program: push
* @description:
* @author: tmh
* @create: 2020-12-22 14:18
**/
public class FireBaseUtil {
public static final Logger LOGGER = LoggerFactory.getLogger(FireBaseUtil.class);
//存放多个实例的Map
private static Map<String,FirebaseApp> firebaseAppMap = new ConcurrentHashMap<>();
//获取AndroidConfig.Builder对象
private static com.google.firebase.messaging.AndroidConfig.Builder androidConfigBuilder=AndroidConfig.builder();
//获取AndroidNotification.Builder对象
private static AndroidNotification.Builder androidNotifiBuilder=AndroidNotification.builder();
@Value("${push.androidcertpath}")
private static String androidcertpath;
/**
* 判断SDK是否初始化
* @param appName
* @return
*/
public static boolean isInit(String appName) {
return firebaseAppMap.get(appName) != null;
}
/**
* 初始化SDK
* @param jsonPath JSON路径
* @param dataUrl firebase数据库
* @param appName APP名字
* @throws IOException
*/
public static void initSDK(String jsonPath, String dataUrl,String appName) throws IOException {
FileInputStream serviceAccount = new FileInputStream(androidcertpath);
FirebaseOptions options = new FirebaseOptions.Builder()
.setCredentials(GoogleCredentials.fromStream(serviceAccount)).build();
// .setDatabaseUrl(dataUrl).build();
//初始化firebaseApp
FirebaseApp firebaseApp = FirebaseApp.initializeApp(options);
//存放
firebaseAppMap.put(appName,firebaseApp);
}
/**
* 单设备推送
* @param appName 应用的名字
* @param token 注册token
* @param title 推送题目
* @param bady 推送内容
* @return
* @throws IOException
* @throws FirebaseMessagingException
*/
public static void pushSingle(String appName, String token, String title, String body) throws IOException, FirebaseMessagingException{
//获取实例
FirebaseApp firebaseApp = firebaseAppMap.get(appName);
//实例为空的情况
if (firebaseApp == null) {
return;
}
//构建消息内容
Message message = Message.builder().setNotification(Notification.builder().setTitle(title).setBody(body).build())
.setToken(token)
.build();
//发送后,返回messageID
String response = FirebaseMessaging.getInstance(firebaseApp).send(message);
System.out.println("单个设备推送成功 : "+response);
}
/**
* 给设备订阅主题
* @param appName 应用的名字
* @param Tokens 设备的token,最大1000个
* @param topic 要添加的主题
* @return
* @throws FirebaseMessagingException
* @throws IOException
*/
public static void registrationTopic(String appName, List<String> tokens, String topic) throws FirebaseMessagingException, IOException {
//获取实例
FirebaseApp firebaseApp = firebaseAppMap.get(appName);
//实例不存在的情况
if(firebaseApp == null) {
return;
}
//订阅,返回主题管理结果对象。
TopicManagementResponse response = FirebaseMessaging.getInstance(firebaseApp).subscribeToTopic(tokens, topic);
System.out.println("添加设备主题,成功:" + response.getSuccessCount() + ",失败:" + response.getFailureCount());
}
/**
* 取消设备的订阅主题
* @param appName 应用的名字
* @param tokens 设备的token,最大1000个
* @param topic 取消的主题
* @return
* @throws FirebaseMessagingException
* @throws IOException
*/
public static void cancelTopic(String appName, List<String> tokens, String topic) throws FirebaseMessagingException, IOException {
//获取实例
FirebaseApp firebaseApp = firebaseAppMap.get(appName);
//实例不存在的情况
if(firebaseApp == null) {
return;
}
//取消订阅,返回主题管理结果对象。
TopicManagementResponse response = FirebaseMessaging.getInstance(firebaseApp).unsubscribeFromTopic(tokens, topic);
System.out.println("取消设备主题,成功:" + response.getSuccessCount() + ",失败:" + response.getFailureCount());
}
/**
* 按主题推送
* @param appName 应用的名字
* @param topic 主题的名字
* @param title 消息题目
* @param body 消息体
* @return
* @throws FirebaseMessagingException
* @throws IOException
*/
public static void sendTopicMes(String appName, String topic, String title, String body) throws FirebaseMessagingException, IOException {
//获取实例
FirebaseApp firebaseApp = firebaseAppMap.get(appName);
//实例不存在的情况
if(firebaseApp == null) {
return;
}
//构建消息
Message message = Message.builder()
// .setNotification(new Notification(title,body))
.setTopic(topic)
.build();
//发送后,返回messageID
String response = FirebaseMessaging.getInstance(firebaseApp).send(message);
System.out.println("主题推送成功: " + response);
}
/**
* 单条Android设备推送消息(和pushSingle方法几乎没有区别)
* @param appName 应用的名字
* @param token 注册token
* @param title 推送题目
* @param bady 推送内容
* @throws FirebaseMessagingException
*/
public static void pushSingleToAndroid(String appName, String token, String title, String body) throws FirebaseMessagingException {
//获取实例
FirebaseApp firebaseApp = firebaseAppMap.get(appName);
//实例为空的情况
if (firebaseApp == null) {
return;
}
androidConfigBuilder.setRestrictedPackageName("com.shierke.umeapp");//
androidNotifiBuilder.setColor("#55BEB7");// 设置消息通知颜色
androidNotifiBuilder.setIcon("https://www.shiku.co/images/favicon.png");// 设置消息图标
androidNotifiBuilder.setTitle(title+"哈哈");// 设置消息标题
androidNotifiBuilder.setBody(body);// 设置消息内容
AndroidNotification androidNotification=androidNotifiBuilder.build();
androidConfigBuilder.setNotification(androidNotification);
AndroidConfig androidConfig=androidConfigBuilder.build();
//构建消息
Message message = Message.builder()
.setToken(token)
.setAndroidConfig(androidConfig)
.build();
//发送后,返回messageID
String response = FirebaseMessaging.getInstance(firebaseApp).send(message);
System.out.println("单个安卓设备推送成功 : "+response);
}
/**
* Android按主题推送(和sendTopicMes方法几乎没有区别)
* @param appName 应用的名字
* @param topic 主题的名字
* @param title 消息题目
* @param body 消息体
* @return
* @throws FirebaseMessagingException
* @throws IOException
*/
public static void sendTopicMesToAndroid(String appName, String topic, String title, String body) throws FirebaseMessagingException, IOException {
//获取实例
FirebaseApp firebaseApp = firebaseAppMap.get(appName);
//实例为空的情况
if (firebaseApp == null) {
return;
}
androidNotifiBuilder.setColor("#55BEB7");// 设置消息通知颜色
androidNotifiBuilder.setIcon("https://www.shiku.co/images/favicon.png");// 设置消息图标
androidNotifiBuilder.setTitle(title);// 设置消息标题
androidNotifiBuilder.setBody(body);// 设置消息内容
AndroidNotification androidNotification=androidNotifiBuilder.build();
androidConfigBuilder.setNotification(androidNotification);
AndroidConfig androidConfig=androidConfigBuilder.build();
//构建消息
Message message = Message.builder()
.setTopic(topic)
.setAndroidConfig(androidConfig)
.build();
String response = FirebaseMessaging.getInstance(firebaseApp).send(message);
System.out.println("安卓主题推送成功: " + response);
}
/**
*
* @param appName 需要开发的appId 这个id和发送消息没有任何关系,只是作为key为了查找app对应的FirebaseApp信息使用
* @param title 你要推送的消息标题
* @param body 消息内容
* @param packageName 这个包名 是ios/android在fcm官网注册获取到的包名
* @param clickAction 这个是点击消息后的触发事件 ,如果想要触发app可以默认设置为OPEN_STOCK_ACTIVITY
* @param ttl 消息过期时间 单位在api要求为ms
* @param channelId 设置发送的频道的id
* @param tokens 用户设备唯一标识列表,其中包含若干个用户设备,官网限制为100个
* @return
* @throws IOException
*/
public static BatchResponse pushBatch(List<String> tokens,String appName, String title, String body, String clickAction,Map<String,Object> data) throws IOException {
BatchResponse batchResponse = null;
//获取实例
FirebaseApp firebaseApp = firebaseAppMap.get(appName);
//实例为空的情况
if (firebaseApp == null) {
return null;
}
try {
if(firebaseApp !=null){
//获取AndroidConfig.Builder对象
AndroidConfig.Builder androidConfigBuilder=AndroidConfig.builder();
//获取AndroidNotification.Builder对象
AndroidNotification.Builder androidNotifiBuilder=AndroidNotification.builder();
//可以存放一个数据信息进行发送,使得app开发客户端可以接受信息
// androidConfigBuilder.putData("test","this is a test data");
androidConfigBuilder.setRestrictedPackageName("com.shierke.umeapp");//设置包名
// androidConfigBuilder.setTtl(3600 * 1000);//设置过期时间 官方文档以毫秒为单位
androidNotifiBuilder.setTitle(title);// 设置消息标题
androidNotifiBuilder.setBody(body);// 设置消息内容
// androidNotifiBuilder.setClickAction(clickAction); //设置触发事件
// androidNotifiBuilder.setChannelId(channelId);
AndroidNotification androidNotification=androidNotifiBuilder.build();
androidConfigBuilder.setNotification(androidNotification);
//将所有的附加参数全部放进去
if (data != null) {
for (Map.Entry<String, Object> map : data.entrySet()) {
// payloadBuilder.addCustomProperty(map.getKey(), map.getValue());
androidConfigBuilder.putData(map.getKey(),map.getValue().toString());
}
}
AndroidConfig androidConfig=androidConfigBuilder.build();
LOGGER.info("androidNotification:"+androidNotification.toString());
LOGGER.info("AndroidConfig:"+androidConfig.toString());
//在进行消息发送之前要设置代理 这个非常重要,因为访问谷歌的服务器需要通过代理服务器在进行访问
// initProxy("yourHost",80,"yourUsername","yourPassword");
//构建消息
MulticastMessage message = MulticastMessage.builder()
.addAllTokens(tokens) //向所有的设备推送消息
.setAndroidConfig(androidConfig)
.build();
// LOGGER.info("android-info:"+ JSON.toJSONString(message));
batchResponse = FirebaseMessaging.getInstance(firebaseApp).sendMulticast(message);
if (batchResponse.getFailureCount() > 0) {
List<SendResponse> responses = batchResponse.getResponses();
List<String> failedTokens = new ArrayList<>();
for (int i = 0; i < responses.size(); i++) {
if (!responses.get(i).isSuccessful()) {
// The order of responses corresponds to the order of the registration tokens.
failedTokens.add(tokens.get(i));
}
}
LOGGER.info("安卓推送失败: " + failedTokens);
}
//处理失败请求
}
} catch (Exception e) {
e.printStackTrace();
}
return batchResponse;
}
}