海外推送接入firebase,实现管理员在app后台推送相关信息,一下主要描述后台接入逻辑以及常见问题
**注意:由于国内防火墙的原因,无法直接访问firebaseApi
1)app接入firebase需要;
2)以下后台管理接入firebase即使不管用,需要在可以直接访问firebase的网络环境下运行;
一、实现基本流程
1)APP端接入firebase的SDK,并在应用启动时候获取registrationToken(对应设备注册token)传入后台;
2)APP后台将获取的token与设备id对应存储,根据需要可以为设备订阅相关主题,群推可进行主题推送;
二、管理员后台接入实现(java)
官方文档:https://firebase.google.com/docs/admin/setup?hl=zh-cn
1)将firebase添加到后台
dependencies {
implementation 'com.google.firebase:firebase-admin:6.5.0'
}
com.google.firebase
firebase-admin
6.5.0
2)初始化SDK(以下为单应用初始化,后面将介绍初始化多应用)
FileInputStream serviceAccount = new FileInputStream("path/to/serviceAccountKey.json");
FirebaseOptions options = new FirebaseOptions.Builder()
.setCredentials(GoogleCredentials.fromStream(serviceAccount))
.setDatabaseUrl("https://.firebaseio.com/")
.build();
FirebaseApp.initializeApp(options);
3)设备主题订阅(主题名称由后台自定义)
// 需要订阅的设备token
List registrationTokens = Arrays.asList(
"YOUR_REGISTRATION_TOKEN_1",
// ...
"YOUR_REGISTRATION_TOKEN_n"
);
// 订阅
// topic.主题名称
TopicManagementResponse response = FirebaseMessaging.getInstance().subscribeToTopicAsync(
registrationTokens, topic).get();
// 返回结果
System.out.println(response.getSuccessCount() + " tokens were subscribed successfully");
4)设备取消主题订阅
// 需要取消的设备token
List registrationTokens = Arrays.asList(
"YOUR_REGISTRATION_TOKEN_1",
// ...
"YOUR_REGISTRATION_TOKEN_n"
);
// 取消订阅
// the topic.
TopicManagementResponse response = FirebaseMessaging.getInstance().unsubscribeFromTopicAsync(
registrationTokens, topic).get();
// 返回结果
System.out.println(response.getSuccessCount() + " tokens were unsubscribed successfully");
5)单个设备推送
// 需要推送的设备token
String registrationToken = "YOUR_REGISTRATION_TOKEN";
// 推送的消息体,data为自定义消息体
Message message = Message.builder()
.putData("score", "850")
.putData("time", "2:45")
.setToken(registrationToken)
.build();
// 发送消息
String response = FirebaseMessaging.getInstance().send(message);
System.out.println("Successfully sent message: " + response);
6)向某个主题推送消息
// 主题名.
String topic = "highScores";
// 消息体
Message message = Message.builder()
.putData("score", "850")
.putData("time", "2:45")
.setTopic(topic)
.build();
// 发送
String response = FirebaseMessaging.getInstance().send(message);
//返回值
System.out.println("Successfully sent message: " + response);
三、多应用初始化以及推送管理
以上为基本的单应用设备推送方案,若需要同时管理多个应用(如多个马甲包情况),需要初始化多个FirebaseApp,以下以代码实现为例:
@Component
public class FireBaseUtil {
@Autowired
private FirebaseConfigMapper configMapper;//查找多个应用秘钥mapp(多应用及秘钥保存于数据库)
//保存多个初始化的FirebaseApp实例,避免多次初始化
private Map firebaseAppMap = new ConcurrentHashMap<>();
private final Logger logger = LoggerFactory.getLogger(FireBaseUtil.class);
/**
* 获取实例
* @param channelCode 渠道名作为应用名,获取初始化配置
* @return
*/
private FirebaseMessaging getMessageInstance(String channelCode){
try {
FirebaseApp firebaseApp = firebaseAppMap.get(channelCode);
if (firebaseApp == null){
FirebaseConfigDO firebaseConfigDO = configMapper.findByChannelCode(channelCode);
if (firebaseConfigDO == null){
return null;
}
FirebaseOptions options = new FirebaseOptions.Builder()
.setCredentials(GoogleCredentials.fromStream(new ByteArrayInputStream(firebaseConfigDO.getAccountJson().getBytes())))
.setDatabaseUrl(firebaseConfigDO.getDatabaseUrl())
.build();
firebaseApp = FirebaseApp.initializeApp(options,channelCode);
firebaseAppMap.put(channelCode,firebaseApp);
}
return FirebaseMessaging.getInstance(firebaseApp);
}catch (Exception e){
throw new ServiceException(e);
}
}
/**
* 主题订阅
* @param channelCode 渠道名,用作实例化的应用名
* @param token
* @param topic
*/
@Async
public void subTopic(String channelCode, String token, FirebaseTopicEnum topic){
List tokens = new ArrayList<>();
tokens.add(token);
subTopic(channelCode,tokens,topic);
}
public void subTopic(String channelCode, List tokends, FirebaseTopicEnum topic){
FirebaseMessaging instance = getMessageInstance(channelCode);
if (instance == null)
return;
try {
instance.subscribeToTopic(tokends, topic.getTopic());
} catch (FirebaseMessagingException e) {
e.printStackTrace();
}
}
/**
* 取消订阅
* @param channelCode 渠道名,用作实例化的应用名
* @param token
* @param topic
*/
public void unSubTopic(String channelCode, String token, FirebaseTopicEnum topic){
List tokens = new ArrayList<>();
tokens.add(token);
unSubTopic(channelCode,tokens,topic);
}
@Async
public void unSubTopic(String channelCode, List tokends, FirebaseTopicEnum topic){
FirebaseMessaging instance = getMessageInstance(channelCode);
if (instance == null)
return;
try {
instance.unsubscribeFromTopic(tokends,topic.getTopic());
} catch (FirebaseMessagingException e) {
e.printStackTrace();
}
}
/**
* 单推
* @param channelCode 渠道号
* @param token 注册token
* @param pushData 推送数据
*/
public void pushSingle(String channelCode, String token, PushDataBO pushData){
FirebaseMessaging messageInstance = getMessageInstance(channelCode);
if (messageInstance == null)
return;
try {
messageInstance.send(messageBuild(pushData, token, null));
logger.info("设备推送成功 : "+token);
} catch (FirebaseMessagingException e) {
e.printStackTrace();
}
}
/**
* 主题推送
* @param channelCode 渠道
* @param topicEnum 主题
* @param pushData 消息内容
*/
@Async
public void pushTopic(String channelCode, FirebaseTopicEnum topicEnum, PushDataBO pushData){
FirebaseMessaging messageInstance = getMessageInstance(channelCode);
if (messageInstance == null)
return;
try {
messageInstance.send(messageBuild(pushData, null, topicEnum));
logger.info("主题推送成功 :" + topicEnum.getName());
} catch (FirebaseMessagingException e) {
e.printStackTrace();
}
}
/**
* 创建消息
* @param pushData 消息内容
* @param token 单设备推送携带,否则未null
* @param topicEnum 主题推送携带,否则未null,自定义的主题枚举
* @return
*/
private Message messageBuild(PushDataBO pushData,String token,FirebaseTopicEnum topicEnum){
Message.Builder builder = Message.builder()
.setNotification(new Notification(pushData.getTitle(), pushData.getBody()))
.putData("pushType", pushData.getPushType().getType())
.putData("openData", pushData.getOpenData()==null?"default":pushData.getOpenData());
if (token != null){//单设备推送
builder.setToken(token);
}else {//订阅主题推送
builder.setTopic(topicEnum.getTopic());
}
return builder.build();
}
}
以上代码应用于个人项目,若有疑问,多多指教!!!