Android 集成firebase 推送(FCM)

1,集成firebase 基础

1>googleService文件

2>项目级gradle

3>app级gradle

4>setting 

2,推送相关

重点:

源文档:设置 Firebase Cloud Messaging 客户端应用 (Android) (google.com)

/**
 * 监听推送的消息
 * 三种情况:
 * 1,通知时:
 * 当应用处于前台的时候,推送的消息会走onMessageReceived方法,处于后台时走系统托盘。
 * 2,数据时:
 * 当应用处于前、后台的时候,会走onMessageReceived方法。
 * 3,通知且携带数据:
 * 当应用处于前台的时候,推送的消息会走onMessageReceived方法,处于后台时,通知走系统托盘,数据走Intent 的 extra 中(点击通知栏后)。
 */

1>清单文件

2>MyFirebaseMessagingService类

/**
 * 推送数据对通知的影响
 * 1,如果我们推送的数据 notification 对应的数据 不为空,那么我们接收消息就需要分为两种情况,
 * 前台和后台,如果App当前状态为前台,那么 onMessageReceived 方法就会被调用,
 * 后续我们自己拿到对用的数据进行通知栏的显示,如果App当前状态为后台的话 那么我们无需自己写 sdk会自己弹出。
 *
 *,2,如果我们推送的数据 notification 对应的数据为空,把所有的数据放置到data 字段里面,
 * 那么sdk不会为我们弹出通知,这时候无论App在前台还是后台都会调用 onMessageReceived ,
 * 这时候我们自己需要处理通知栏的ui 显示。这种情况一般用于自定义通知栏ui 的时候。
 */

public class MyFirebaseMessagingService extends FirebaseMessagingService {

    /**
     * 监听推送的消息
     * 三种情况:
     * 1,通知时:
     * 当应用处于前台的时候,推送的消息会走onMessageReceived方法,处于后台时走系统托盘。
     * 2,数据时:
     * 当应用处于前、后台的时候,会走onMessageReceived方法。
     * 3,通知且携带数据:
     * 当应用处于前台的时候,推送的消息会走onMessageReceived方法,处于后台时,通知走系统托盘,数据走Intent 的 extra 中(点击通知栏后)。
     */
    @Override
    public void onMessageReceived(@NonNull RemoteMessage message) {

        String testDemo = "0";//测试数据,后端自定义消息/或控制台测试时输入键值,时传递来 “键”-“值” 中的 值
//        Map<String, String> remoteMessageMap = message.getData();
        if (message.getData() != null && !message.getData().isEmpty()) {//不自定义消息,getData为空
            if (message.getData().size() > 0) {
                testDemo = message.getData().get("testDemo");//“键”-“值” 中的 键

            }
        }

        if (message.getNotification() != null && !message.getNotification().getTitle().isEmpty() && !message.getNotification().getBody().isEmpty()) {
//            sendNotification(message.getNotification().getTitle(), message.getNotification().getBody(), testDemo);
            String click_action = message.getNotification().getClickAction();
            sendNotification(message.getNotification().getTitle(), message.getNotification().getBody(), testDemo, click_action);
        }


    }


    /**
     * 当有新的Firebase token 时的回调
     * 第一次安装app 获取到的 pushtoken
     */
    @Override
    public void onNewToken(@NonNull String token) {
        //token 传递给后端!!
        Log.e("测试", "onNewToken =" + token);
    }

    /**
     * 自定义通知
     *
     * @param messageBody
     */
    private void sendNotification(String messageTitle, String messageBody, String testDemo, String click_action) {
        Intent intent = prepareIntent(click_action);
//    private void sendNotification(String messageTitle, String messageBody, String testDemo) {
//        Intent intent = new Intent(this, MainActivity.class);

        String channelID = getResources().getString(R.string.default_notification_channel_id);//渠道ID
        String channelName = getResources().getString(R.string.default_notification_channel_name);//渠道名称

        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
        if (testDemo != null && !testDemo.isEmpty()) {
            intent.putExtra("testDemo", testDemo);

        }

        int uniqueInt = (int) (System.currentTimeMillis() & 0xff);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, uniqueInt /* Request code */, intent, PendingIntent.FLAG_UPDATE_CURRENT);

        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        NotificationCompat.Builder notificationBuilder;
        //android 8 开始要 创建通知渠道,否则通知栏不弹出
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            notificationBuilder = new NotificationCompat.Builder(this, channelID);
            NotificationChannel channel = new NotificationChannel(channelID, channelName, NotificationManager.IMPORTANCE_HIGH);
            notificationManager.createNotificationChannel(channel);
        } else {
            notificationBuilder = new NotificationCompat.Builder(this);
        }

        //设置title
        if (messageTitle != null && !messageTitle.isEmpty()) {
            notificationBuilder.setContentTitle(messageTitle);
        } else {
            notificationBuilder.setContentTitle(getResources().getString(R.string.app_name));
        }

        //设置body
        if (messageBody != null && !messageBody.isEmpty()) {
            notificationBuilder.setContentText(messageBody);
        }
//        Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        notificationBuilder
                .setSmallIcon(R.drawable.icon_return)//设置通知栏的小图标,必需设置,否则crash
                .setAutoCancel(true)//点击通知后,通知自动消失
                .setWhen(System.currentTimeMillis())// 设置通知时间,此事件用于通知栏排序
                .setPriority(NotificationCompat.PRIORITY_HIGH)// 设置优先级,低优先级可能被隐藏
//                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);//设置通知栏被点击时的事件

        notificationManager.notify(uniqueInt /* ID of notification */, notificationBuilder.build());

    }

    public Intent prepareIntent(String clickAction) {
        Intent intent;
        boolean isAppInBackground;
        isAppInBackground = ProcessJudgmentHelper.isRunBackground(this);
        if (isAppInBackground) {
            intent = new Intent(this, MainActivity.class);
        } else {
            intent = new Intent(clickAction);
        }

        return intent;
    }

    /**
     * 1,如果未开启通知,则跳转到通知设置界面,点击之后就需要跳转到 APP的通知设置界面,
     * 对应的Action是:Settings.ACTION_APP_NOTIFICATION_SETTINGS, 这个Action是 API 26 后增加的。
     * 2,如果在部分手机中无法精确的跳转到APP对应的通知设置界面,我们就考虑直接跳转到APP信息界面,
     * 对应的Action是:Settings.ACTION_APPLICATION_DETAILS_SETTINGS。
     *
     */

}

4>主启动Activity(清单文件里设置 <action android:name="android.intent.action.MAIN" /> 的Activity)


/**
 * 1,清单文件里设置 <action android:name="android.intent.action.MAIN" /> 的Activity,一般是Splish 闪屏页。
 * 在onCreate() 方法里 获取用户PushToken,调用接口传给自己的后端,以防有变化。
 * 2,如果是自定义消息(当后端或者控制台设置响应的data 键值)在onResume() 方法里 使用intent 获取到对应的值,进行相关操作,
 * 例如:根据约定值 进行响应页面的跳转。
 *
 *
 */
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        requestPer();

        try {
            boolean goolgePlayServiceAvailable = FirebaseManager.getInstance().isGoolgePlayServiceAvailable(this);
            if (goolgePlayServiceAvailable) {
                uploadPushToken();
            } else {
                Log.e("测试", "谷歌服务不可用");
            }
        } catch (Exception e) {
            e.printStackTrace();
            Log.e("测试", "谷歌服务异常");

        }
    }


    @Override
    protected void onResume() {
        super.onResume();
        Intent intent = getIntent();
        //当后端或者控制台设置自定义消息后,点击通知时能获取到对应的值
        String testDemo = intent.getStringExtra("testDemo");

        if (testDemo != null && !testDemo.isEmpty()) {
            //如有特殊情形,要判断是否登录,没登录跳转登录页
//            if(){
//            }
            if (testDemo.equals("66")) {
                Intent intentSeconActivity = new Intent(this, SeconActivity.class);
                startActivity(intentSeconActivity);
                finish();
            }
        }

    }

    /**
     * 上传push token
     * 正常情况下每次启动 都会获取到!
     */
    private void uploadPushToken() {
        FirebaseMessaging.getInstance().getToken()
                .addOnCompleteListener(new OnCompleteListener<String>() {
                    @Override
                    public void onComplete(@NonNull Task<String> task) {
                        if (!task.isSuccessful()) {
                            Log.e("测试", "Fetching FCM registration token failed", task.getException());
                            return;
                        }

                        // Get new FCM registration token
                        String token = task.getResult();
                        Log.e("测试", "MainActivity token =" + token);

                    }
                });
    }

    /**
     * android 高版本请求推送权限
     */
    private void requestPer() {
        XXPermissions.with(this)
                // 申请单个权限
                .permission(Permission.POST_NOTIFICATIONS)
                .request(new OnPermissionCallback() {

                    @Override
                    public void onGranted(List<String> permissions, boolean all) {

                    }

                    @Override
                    public void onDenied(List<String> permissions, boolean never) {
                        if (never) {

                        } else {
                        }
                    }
                });
    }
}

==================结束===============

工具方法:
 

    /** 判断程序是否在后台运行 */
    public static boolean isRunBackground(Context context) {
        ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
        for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
            if (appProcess.processName.equals(context.getPackageName())) {
                if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND) {
                    // 表明程序在后台运行
                    return true;
                } else {
                    return false;
                }
            }
        }
        return false;
    }

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

python netCDF4

NetCDF简介 NetCDF 即 network Common Data Form&#xff08;网络通用数据格式&#xff09;&#xff0c;是一种面向数组型并适于网络共享的数据的描述和编码标准。文件的后缀是 .nc。nc 在气象领域应用很广&#xff0c;因为它可以存储不同波段的长时间观测结果。 NetCDF 文件…

Ncast盈可视高清智能录播系统busiFacade RCE漏洞(CVE-2024-0305)

产品介绍 Ncast盈可视高清智能录播系统是一套新进的音视频录制和播放系统&#xff0c;旨在提供高质量&#xff0c;高清定制的录播功能。 漏洞描述 广州盈可视电子科技有限公司的高清智能录播系统存在信息泄露漏洞(CVE-2024-0305)&#xff0c;攻击者可通过该漏洞&#xff0c;…

vue前端开发自学,子组件传递数据给父组件,使用$emit

vue前端开发自学,子组件传递数据给父组件,使用$emit 父子组件之间互相传递数据的情况非常常见&#xff0c;下面为大家介绍的是&#xff0c;来自子组件&#xff0c;给父组件传递数据的情况。 <template><h3>组件事件demo</h3><Child someEvent"getI…

matplotlib教程(一)—— 入门基础

前言 Matplotlib 是 Python 的绘图库&#xff0c;它能让使用者很轻松地将数据图形化&#xff0c;并且提供多样化的输出格式&#xff1b;它可以绘制线图、散点图、等高线图、条形图、柱状图、3D 图形、甚至是图形动画等 在使用它之前&#xff0c;应导入&#xff1a;import matp…

LeetCode刷题笔记

面试经典150题 1. 数组/字符串 1.1 合并两个有序数组 题目 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2&#xff0c;另有两个整数 m 和 n &#xff0c;分别表示 nums1 和 nums2 中的元素数目。 请你 合并 nums2 到 nums1 中&#xff0c;使合并后的数组同样按 非递减顺…

python 文件夹中 __init__.py

common文件夹下有&#xff1a;project&#xff0c;__init__.py&#xff0c;common1.py project文件夹内有&#xff1a;__init__.py&#xff0c;p.py common文件夹里&#xff0c;project文件夹 各放了一个 __init__.py 这样就可以在p.py内用from导入common1.py内的代码 # p…

Git的简单使用说明

Git入门教程 git的最主要的作用&#xff1a;版本控制&#xff0c;协助开发 一.版本控制分类 ​​ 1.本地版本控制 ​​ 2.集中版本控制 ​​ 所有的版本数据都存在服务器上&#xff0c;用户的本地只有自己以前所同步的版本&#xff0c;如果不连网的话&#xff0c;用户就看不…

第一次在RUST官方论坛上留言发布我的Rust板箱

第一次在RUST官方论坛上发帖子&#xff0c;有点紧张~地址在这里&#xff1a; 【My Rust Crate】obtains linux local information - The Rust Programming Language Forum (rust-lang.org)

设计模式之装饰者模式

装饰者模式 装饰者模式是一种设计巧妙的设计模式&#xff0c;它能够动态的添加对象功能&#xff0c;而对原始对象无干扰。java程序设计中有一个很重要的原则就是尽可能实现复用。逻辑复用只有两种模式&#xff0c;一种是继承&#xff0c;一种是委托。继承模式两者之间是强依赖…

超详细讲解Transformers自然语言处理NLP文本分类、情感分析、垃圾邮件过滤等(附数据集下载)

超详细讲解Transformers自然语言处理NLP文本分类、情感分析、垃圾邮件过滤等(附数据集下载) 什么是自然语言处理 (NLP) ? 自然语言处理 (NLP) 是计算机科学的一个分支,更具体地说,是人工智能 (AI) 的分支,旨在让计算机能够以与人类大致相同的方式理解文本和语音。 自然语…

程序员如何写高水平简历?(附模板)

Q&#xff1a;什么是高水平的简历&#xff1f; A&#xff1a;满足HR需求的同时&#xff0c;最大化的体现自身价值的简历是高水平的简历 HR的需求是什么&#xff1f; ✅ HR想看到清晰专业的简历模板 ——家人们每天看几百份简历谁懂啊&#xff01;花里胡哨真看不下去一点&…

FPGA:我的零基础学习路线(2022秋招已上岸)持续更新中~

可内推简历&#xff0c;丝我即可 前言 初次接触FPGA是在2022年3月左右&#xff0c;正处在研二下学期&#xff0c;面临着暑假找工作&#xff0c;周围的同学大多选择了互联网&#xff0c;出于对互联网的裁员形势下&#xff0c;我选择了FPGA&#xff0c;对于硬件基础知识我几乎是…

Mysql-排序查询方法

接上篇Mysql数据库的基础操作-CSDN博客 25. 基础-SQL-DCL-权限控制-_哔哩哔哩_bilibili 1、排序语法 2、查询结果示例 这个查询结果&#xff0c;因为特意选的age18 的数据来统计&#xff0c;所以当每一条数据的age一样时&#xff0c;使用worknno进行排序。可以看到work的升序和…

19_注解

文章目录 注解注解的作用注解的语法注解的使用 元注解注解处理器案例 注解VS配置文件注解的应用 注解 Annotation是代码里的特殊标记&#xff0c;这些标记可以在编译、类加载、运行时被读取&#xff0c;并执行相应的处理可以把Annotation理解为一个标签注解是不允许继承的 注…

鸿蒙开发笔记(一):ArkTS概述及声明式UI的使用

ArkTS是HarmonyOS优选的主力应用开发语言。ArkTS围绕应用开发在TypeScript&#xff08;简称TS&#xff09;生态基础上做了进一步扩展&#xff0c;继承了TS的所有特性&#xff0c;是TS的超集。 ArkTS在TS的基础上主要扩展了如下能力&#xff1a; 基本语法&#xff1a;ArkTS定义…

C++内存管理机制(侯捷)笔记3

C内存管理机制&#xff08;侯捷&#xff09; 本文是学习笔记&#xff0c;仅供个人学习使用。如有侵权&#xff0c;请联系删除。 参考链接 Youtube: 侯捷-C内存管理机制 Github课程视频、PPT和源代码: https://github.com/ZachL1/Bilibili-plus 第三讲&#xff1a;malloc和…

波动,热传导,扩散方程建立

数学物理方程是从自然科学的各个领域和工程技术领域中导出的偏微分方程和积分方程.在这些以偏微分方程为基础的数学模型中&#xff0c;二阶线性偏微分方程中的三个典型方程与定解条件的建立、解法及其应用&#xff0e;描述振动和波动过程的波动方程、描述输运过程的热传导&…

【笔记】Blender4.0建模入门-1、2

Blender入门 ——邵发 1.1 课程介绍 Blender&#xff0c;一款3D建模软件&#xff0c;小乔、免费、全流程 常见的3D建模软件&#xff1a; - 3DsMax/Maya/Blender/Cinema4D/ZBrush...游戏影视 - Proe/Solidworks/Inventor/UG...工业建模 - SketchUp/Rhino/Revit...建筑设计 …

想要简化重复订单吗?不妨考虑一揽子采购订单

企业想提高采购流程效率&#xff0c;简化大批量采购是一个很好的开始。财务、会计和采购部门通过系统化订购大量物品&#xff08;如纸张、打印机墨水和墨粉、清洁用品、纸制品和其他易重复采购的消耗品&#xff09;可以节省时间和金钱。借助正确的采购订单&#xff08;PO&#…

俩万字详解C++STL期末复习知识点(C++STL课本源码私信可得)

邸老师复习建议 复习注意事项 1 不考死记硬背的题&#xff0c;比如名词解释。 2 选择题重点考核宏观性、综合性的问题&#xff0c;比如&#xff1a;把电话通讯录存入容器&#xff0c;该选哪一个容器&#xff1f; 3 选择题重点考核理解性的问题&#xff0c;比如&#xff0c;…