firebase推送工具类 (Android iOS通用) java服务端

1 篇文章 0 订阅
1 篇文章 0 订阅

第一步   初始化firebaseAdminSDK

  引入依赖

 <dependency>
            <groupId>com.google.firebase</groupId>
            <artifactId>firebase-admin</artifactId>
            <version>6.8.1</version>
 </dependency>

  初始化

@Component
@Slf4j
@Order(1)
public class FireBaseConfig implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        init();
    }

    private void init() throws IOException {
        //协议开放 克服握手错误
        System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2");
        log.info("协议开放成功:",System.getProperty("https.protocols"));
        //firebase初始化
        ClassPathResource classPathResource = new ClassPathResource("{firebase下发的json}");
        InputStream inputStream = classPathResource.getInputStream();
        FirebaseOptions options = new FirebaseOptions.Builder()
                .setCredentials(GoogleCredentials.fromStream(inputStream))
                .setDatabaseUrl("https://<DATABASE_NAME>.firebaseio.com/")//
                .build();
        FirebaseApp.initializeApp(options);
        log.info("firebase初始化成功!!!");
    }
}

firebaseUtils

package com.hengde.lit.producers.business.common.util;

import com.google.cloud.storage.Blob;
import com.google.cloud.storage.Bucket;
import com.google.common.collect.Lists;
import com.google.firebase.auth.*;
import com.google.firebase.cloud.StorageClient;
import com.google.firebase.messaging.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;

/**
 * @Author fanqiang
 * @Date 2019/7/10 11:56
 **/
@Slf4j
public class FirebaseUtils {
    private static FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();

    /**
     * 系统标识符
     */
    public static final String COLLAPSEKEY_SYSTEM = "collApseKey_system";

    /**
     * 系统主题
     */
    public static final String TOPIC_SYSTEM = "topic_system";

    /*********************************************************************
     *                          用户基本操作
     ********************************************************************/
    /**
     * 功能描述:
     * <根据uid查找firebase用户>
     *
     * @Param: [uid]
     * @return: com.google.firebase.auth.UserRecord
     * @Author: FanQiang
     * @Date: 2019/7/10
     */
    public static UserRecord getUserByUid(Long uid) throws FirebaseAuthException {
        return firebaseAuth.getUser(uid.toString());
    }

    /**
     * 功能描述:
     * <根据email查找firebase用户>
     *
     * @Param: [email]
     * @return: com.google.firebase.auth.UserRecord
     * @Author: FanQiang
     * @Date: 2019/7/10
     */
    public static UserRecord getUserByEmail(String email) throws FirebaseAuthException {
        return firebaseAuth.getUserByEmail(email);
    }

    /**
     * 功能描述:
     * <查询firebase全部用户>
     *
     * @Param: []
     * @return: java.util.List<com.google.firebase.auth.UserRecord>
     * @Author: FanQiang
     * @Date: 2019/7/10
     */
    public static List<UserRecord> findAllUser() throws FirebaseAuthException {
        List<UserRecord> userRecords = new ArrayList<>();
        ListUsersPage page = firebaseAuth.listUsers(null);
        while (page != null) {
            for (ExportedUserRecord user : page.getValues()) {
                userRecords.add(user);
            }
            page = page.getNextPage();
        }
        return userRecords;
    }


    /**
     * 功能描述:
     * <创建firebase用户>
     *
     * @Param: [uid, userName, email, avatar]
     * @return: com.google.firebase.auth.UserRecord
     * @Author: FanQiang
     * @Date: 2019/7/10
     */
    public static UserRecord createUser(Long uid, String userName, String email, String avatar) throws FirebaseAuthException {
        UserRecord.CreateRequest createRequest = new UserRecord.CreateRequest()
                .setDisplayName(userName).setUid(uid.toString()).setEmail(email)
                .setPhotoUrl(avatar).setEmailVerified(false).setDisabled(false);
        return firebaseAuth.createUser(createRequest);
    }

    public static UserRecord updateUser(Long uid, String userName, String email, String avatar) throws FirebaseAuthException {

        UserRecord.UpdateRequest request = new UserRecord.UpdateRequest(uid.toString());
        if (!StringUtils.isEmpty(userName)) {
            request.setDisplayName(userName);
        }
        if (!StringUtils.isEmpty(avatar)) {
            request.setPhotoUrl(avatar);
        }
        if (!StringUtils.isEmpty(email)) {
            request.setEmail(email);
        }
        request.setDisabled(false)
                .setEmailVerified(false);

        return firebaseAuth.updateUser(request);
    }

    /**
     * 功能描述:
     * <删除firebase用户>
     *
     * @Param: [uid]
     * @return: void
     * @Author: FanQiang
     * @Date: 2019/7/10
     */
    public static void deleteUser(Long uid) throws FirebaseAuthException {
        firebaseAuth.deleteUser(uid.toString());
    }


    /**
     * 通用消息推送  单条消息  向单个用户推送
     *
     * @param title
     * @param body
     * @param registrationToken 用户设备令牌
     * @param collapseKey       消息标识符
     * @param datas 额外参数 k-v
     */
    public static String sendMsgToToken(String title, String body, String registrationToken, String collapseKey,Map<String,String> datas) {
        Message message = getBuilder(title, body, collapseKey,datas)
                .setToken(registrationToken)
                .build();
        return send(message);
    }

    /**
     * 通用消息推送  向多个用户推送
     *
     * @param title
     * @param body
     * @param registrationTokens 用户设备令牌
     * @param collapseKey        消息标识符
     * @param datas 额外参数 k-v
     */
    public static void sendMsgToTokens(String title, String body, List<String> registrationTokens, String collapseKey,Map<String,String> datas) throws FirebaseMessagingException {
        MulticastMessage message = getMulticastBuilder(title,body,collapseKey,datas)
                .addAllTokens(registrationTokens)
                .build();
        BatchResponse response = FirebaseMessaging.getInstance().sendMulticast(message);
        if (response.getFailureCount() > 0) {
            List<SendResponse> responses = response.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(registrationTokens.get(i));
                }
            }

            log.info("List of tokens that caused failures: " + failedTokens);
        }
    }

    /**
     * 通用消息推送  主题消息  订阅该主题的用户全部可以接收到
     *
     * @param collapseKey 一组消息的标识符,这组消息可以折叠,以便当恢复传送时只发送最后一条消息。在任意给定时间最多允许 4 个不同的折叠键。
     * @param topic       要将消息发送至的主题名称。该主题名称不能包含 /topics/ 前缀。
     * @param title
     * @param body
     * @param datas 额外参数 k-v
     */
    /*----------------------------------关于anps的headers配置说明---------------------------------------*/
/*        authorization

       授权APN发送指定主题的推送通知的提供者令牌。令牌采用Base64URL编码的JWT格式,指定为bearer <provider token>。

        使用提供程序证书建立连接时,将忽略此请求标头。

        apns-id

        标识通知的规范UUID。如果发送通知时出错,则APN使用此值来标识通知您的服务器。

        规范形式是32个小写十六进制数字,显示在由8-4-4-4-12形式的连字符分隔的五个组中。示例UUID如下:

        123e4567-e89b-12d3-a456-42665544000

        如果省略此标头,则APN会创建一个新的UUID并在响应中返回。

        apns-expiration

        以星期(UTC)表示的UNIX纪元日期。此标头标识通知不再有效的日期,可以将其丢弃。

        如果此值非零,则APN会存储通知并尝试至少传递一次,如果第一次无法传递通知,则会根据需要重复尝试。如果值为0,则APN将通知视为立即过期,并且不存储通知或尝试重新发送通知。

        apns-priority

        通知的优先级。指定以下值之一:

        10 - 立即发送推送消息。具有此优先级的通知必须在目标设备上触发警报,声音或徽章。将此优先级用于仅包含content-available密钥的推送通知是错误的。

        5 - 在考虑设备功率考虑因素的时间发送推送消息。具有此优先级的通知可能会分组并以突发方式传递。它们受到限制,在某些情况下不会被交付。

        如果省略此标头,则APNs服务器将优先级设置为10。

        apns-topic

        远程通知的主题,通常是应用程序的软件包ID。您在开发人员帐户中创建的证书必须包含此主题的功能。

        如果您的证书包含多个主题,则必须为此标题指定值。

        如果省略此请求标头,并且您的APNs证书未指定多个主题,则APNs服务器将证书的主题用作默认主题。

        如果使用提供者令牌而不是证书,则必须为此请求标头指定值。您应该为开发人员帐户中指定的团队配置您提供的主题。

        apns-collapse-id

        具有相同折叠标识符的多个通知作为单个通知显示给用户。该密钥的值不得超过64个字节。有关更多信息,请参阅服务质量,存储转发和合并通知。*/
    public static void sendMsg(String collapseKey, String topic, String title, String body,Map<String,String> datas) {
        Message message = getBuilder(title, body, collapseKey,datas)
                .setTopic(topic)
                .build();
        send(message);
    }

    /**
     * 安卓消息推送  主题订阅模式
     *
     * @param collapseKey 一组消息的标识符,这组消息可以折叠,以便当恢复传送时只发送最后一条消息。在任意给定时间最多允许 4 个不同的折叠键。
     * @param topic       要将消息发送至的主题名称。该主题名称不能包含 /topics/ 前缀。
     * @param title
     * @param body
     */
    public static void sendMsgByAndroid(String collapseKey, String topic, String title, String body) {
        Message message = Message.builder()
                .setAndroidConfig(AndroidConfig.builder()
                        .setTtl(3600 * 1000)//消息的生存时间
                        .setCollapseKey(collapseKey)
                        .setPriority(AndroidConfig.Priority.HIGH)//消息优先级。必须是 normal 和 high 中的一个。
                        .setNotification(AndroidNotification.builder()
                                .setTitle(title)
                                .setBody(body)
                                .build())
                        .build())
                .setTopic(topic)
                .build();
        send(message);
    }

    private static String send(Message message) {
        String response = null;
        try {
            response = FirebaseMessaging.getInstance().sendAsync(message).get();
            System.out.println("run successful: " + response);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        return response;
    }

    /**
     * IOS推送  主题订阅模式
     *
     * @param collapseKey 一组消息的标识符,这组消息可以折叠,以便当恢复传送时只发送最后一条消息。在任意给定时间最多允许 4 个不同的折叠键。
     * @param topic       要将消息发送至的主题名称。该主题名称不能包含 /topics/ 前缀。
     * @param title
     * @param body
     */
    public static void sendMsgByIOS(String collapseKey, String topic, String title, String body) {
        Message message = Message.builder()
                .setApnsConfig(ApnsConfig.builder()
                        .putHeader("apns-priority", "10")
                        .putHeader("apns-collapse-id", collapseKey)
                        .setAps(Aps.builder()
                                .setAlert(ApsAlert.builder()
                                        .setTitle(title)
                                        .setBody(body)
                                        .build())
                                .setBadge(42)
                                .build())
                        .build())
                .setTopic(topic)
                .build();
        send(message);
    }

    /**
     * 功能描述:
     * <创建主题订阅>
     *
     * @Param: [registrationTokens, topic]
     * @return: com.google.firebase.messaging.TopicManagementResponse
     * @Author: FanQiang
     * @Date: 2019/8/5
     */
    public static void subscribeToTopic(List<String> registrationTokens, String topic) throws
            FirebaseMessagingException {
        List<List<String>> lists = splitList(registrationTokens, 1000);
        for (List<String> tokens : lists) {
            TopicManagementResponse response = FirebaseMessaging.getInstance().subscribeToTopic(tokens, topic);
            log.info(response.getSuccessCount() + " tokens were subscribed successfully");
        }
    }

    /**
     * 功能描述:
     * <退订主题订阅>
     *
     * @Param: [registrationTokens, topic]
     * @return: com.google.firebase.messaging.TopicManagementResponse
     * @Author: FanQiang
     * @Date: 2019/8/5
     */
    public static void unsubscribeFromTopic(List<String> registrationTokens, String topic) throws
            FirebaseMessagingException {
        List<List<String>> lists = splitList(registrationTokens, 1000);
        for (List<String> tokens : lists) {
            TopicManagementResponse response = FirebaseMessaging.getInstance().unsubscribeFromTopic(
                    tokens, topic);
            // See the TopicManagementResponse reference documentation
            // for the contents of response.
            log.info(response.getSuccessCount() + " tokens were unsubscribed successfully");
        }
    }

    private static List<List<String>> splitList(List<String> list, int groupSize) {
        int length = list.size();
        // 计算可以分成多少组
        int num = (length + groupSize - 1) / groupSize; // TODO
        List<List<String>> newList = new ArrayList<>(num);
        for (int i = 0; i < num; i++) {
            // 开始位置
            int fromIndex = i * groupSize;
            // 结束位置
            int toIndex = (i + 1) * groupSize < length ? (i + 1) * groupSize : length;
            newList.add(list.subList(fromIndex, toIndex));
        }
        return newList;
    }

    private static Message.Builder getBuilder(String title, String body, String collapseKey, Map<String,String> map) {
        return Message.builder()
                .setNotification(new Notification(
                        title,
                        body))
                .setAndroidConfig(AndroidConfig.builder()
                        .setTtl(3600 * 1000)
                        .setCollapseKey(collapseKey)
                        .setPriority(AndroidConfig.Priority.HIGH)
                        .setNotification(AndroidNotification.builder()
                                .setTitle(title)
                                .setBody(body)
                                .build())
                        .build())
                .setApnsConfig(ApnsConfig.builder()
                        .putHeader("apns-priority", "10")
                        .putHeader("apns-collapse-id", collapseKey)
                        .setAps(Aps.builder()
                                .setBadge(42)
                                .build())
                        .build()).putAllData(map);
    }

    private static MulticastMessage.Builder getMulticastBuilder(String title, String body, String collapseKey,Map<String,String> map) {
        return MulticastMessage.builder()
                .setNotification(new Notification(
                        title,
                        body))
                .setAndroidConfig(AndroidConfig.builder()
                        .setTtl(3600 * 1000)
                        .setCollapseKey(collapseKey)
                        .setPriority(AndroidConfig.Priority.HIGH)
                        .setNotification(AndroidNotification.builder()
                                .setTitle(title)
                                .setBody(body)
                                .build())
                        .build())
                .setApnsConfig(ApnsConfig.builder()
                        .putHeader("apns-priority", "10")
                        .putHeader("apns-collapse-id", collapseKey)
                        .setAps(Aps.builder()
                                .setBadge(42)
                                .build())
                        .build()).putAllData(map);
    }
}

 

评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值