热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

GoogleFireBase-fcm推送(CloudMessaging)

要将Firebase添加到您的应用,您需要有一个Firebase项目以及适用于您的应用的Firebase配置文件。如果您还没有Firebase项目,请在Firebase控

要将 Firebase 添加到您的应用,您需要有一个 Firebase 项目以及适用于您的应用的 Firebase 配置文件。

  1. 如果您还没有 Firebase 项目,请在 Firebase 控制台中创建一个。如果您已经有与自己的移动应用相关联的现有 Google 项目,请点击导入 Google 项目。如果没有,请点击添加项目
  2. 点击将 Firebase 添加到您的 Android 应用,然后按设置步骤操作。如果您是导入现有 Google 项目,系统可能会自动执行这些操作,您只需下载配置文件即可。
  3. 出现提示时,输入应用的软件包名称。请务必输入应用在使用的软件包名称;只有在将应用添加到 Firebase 项目时您才能进行此设置。
  4. 最后,您要下载一个 google-services.json 文件。您可以随时重新下载此文件。
  5. 如果尚未将此文件复制到项目的模块文件夹(通常是 app/),请执行此操作。

在“根级别”的build.gradle文件添加一条规则。以包含Google服务插件:

 1 buildscript {
 2     
 3     repositories {
 4         jcenter()
 5     }
 6 
 7     dependencies {
 8         classpath 'com.android.tools.build:gradle:2.3.3'
 9 
10         classpath 'com.google.gms:google-services:3.2.0'
11     }
12 }
13 
14 allprojects {
15     repositories {
16         maven { url 'https://maven.google.com' }
17         mavenCentral()
18         jcenter()
19     }
20 }

然后在模块Gradle文件中(比如app模块下),底部添加apply plugin行,以启用 Gradle 插件:

 1 apply plugin: 'com.android.application'
 2 
 3 android {
 4      // ...
 5 }
 6 
 7 dependencies {
 8     // ...
 9 
10     compile 'com.google.android.gms:play-services-base:11.4.0'
11     // Google Firebase cloud messaging
12     compile 'com.google.firebase:firebase-messaging:11.4.0'
13 
14 }
15 
16 apply plugin: 'com.google.gms.google-services'
自定义 ECFCMMSGService 继承  FirebaseMessagingService , 重写 onMessageReceived方法接收通知消息弹通知栏
FCM有两种消息: Data Message和 Notification Message.
(1)Notification Message :
只有app在前台的时候才会走这个方法,当app在后台的时候由系统弹通知栏,当app被杀死的时候,从Firebase后台发送是收不到的
 1 http请求:
 2 https://fcm.googleapis.com/fcm/send
 3 
 4 Content-Type:application/json
 5 Authorization:key= App Key
 6 {
 7     "notification" : {
 8       "body" : "You have a new message",
 9       "title" : "",
10       "icon" : "app icon"
11     },
12     "to" : "user token"
13 }
(2)Data Message:
不管app在后台还是前台都会走这个方法。
 1 http请求:
 2 https://fcm.googleapis.com/fcm/send
 3 
 4 Content-Type:application/json
 5 Authorization:key= App Key
 6 {
 7     "data" : {
 8       "request" : "1",
 9       "xxx" : "xxx"
10     },
11     "to" : "user token"
12 }

(3)Messages with both notification and data payload:

这种消息是在Notification Message的基础上加入一些数据,在用户点击通知栏的时候启动对应的activity并传入intent。

 1 public class ECFCMMSGService extends FirebaseMessagingService {
 2 
 3     // 它主要用于处理接收 App 正在运行的时候,接收到的推送
 4 
 5     private static final String TAG = "ECFCMMSGService";
 6 
 7     @Override
 8     public void onMessageReceived(RemoteMessage remoteMessage) {
 9         super.onMessageReceived(remoteMessage);
10 
11         // Check if message contains a data payload.
12         if (remoteMessage.getData().size() > 0) {
13             Log.d(TAG, "Message data payload: " + remoteMessage.getData());
14         }
15 
16         // Check if message contains a notification payload.
17         if (remoteMessage.getNotification() != null) {
18             Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
19 
20             sendNotification(remoteMessage.getNotification().getBody());
21         }
22     }
23 
24     private void sendNotification(String messageBody) {
25 
26         Intent intent = new Intent(this, MainActivity.class);
27         intent.putExtra("key", messageBody);
28         intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
29 
30         PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
31                 PendingIntent.FLAG_ONE_SHOT);
32 
33         Bitmap icon2 = BitmapFactory.decodeResource(getResources(),
34                 R.mipmap.app_logo);
35 
36         Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
37         NotificationCompat.Builder notificatiOnBuilder= new NotificationCompat.Builder(this)
38                 .setSmallIcon(R.mipmap.app_logo)
39                 .setContentTitle("You have a new message.")
40                 .setContentText(messageBody)
41                 .setAutoCancel(true)
42                 .setLargeIcon(icon2)
43                 .setSound(defaultSoundUri)
44                 .setContentIntent(pendingIntent);
45 
46         NotificationManager notificatiOnManager=
47                 (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
48 
49         notificationManager.notify(new Random().nextInt() /* ID of notification */, notificationBuilder.build());
50     }
51 }

自定义 ECFCMTokenRefreshService 集成 FirebaseInstanceIdService.

用户token的创建,转换和更新,在onTokenRefresh()方法中获取token并上传到服务器。

  1 public class ECFCMTokenRefreshService extends FirebaseInstanceIdService {
  2 
  3     // 它主要用于管理 FCM 的注册令牌(下文简称 FCM_TOKEN ),以及更改等。它可以获取到用户设备唯一的一个 FCM_TOKEN ,向单个用户推送消息的时候使用
  4 
  5     private static final String TAG = "FCMTokenRefreshService";
  6 
  7     private ApiService mService;
  8     private float mRequestTime = 0;
  9     private int mErrorCount = 0;
 10     private int REQUEST_ERROR_MAX = 10;
 11     private TreeMap mParams;
 12 
 13     @Override
 14     public void onCreate() {
 15         super.onCreate();
 16 
 17         if (PreferencesUtils.getInstance().isFCMTokenSendServiceSuccess()) {
 18             return;
 19         }
 20 
 21         String token = PreferencesUtils.getInstance().getFcmToken();
 22 
 23         if (TextUtils.isEmpty(token)) {
 24             token = FirebaseInstanceId.getInstance().getToken();
 25         }
 26 
 27         sendFCMTokenToServer(token);
 28     }
 29 
 30     @Override
 31     public void onTokenRefresh() {
 32         super.onTokenRefresh();
 33 
 34         PreferencesUtils.getInstance().saveFCMTokenSendServiceSuccess(false);
 35 
 36         String token = FirebaseInstanceId.getInstance().getToken();
 37         Log.i(TAG, "onTokenRefresh: " + token);
 38         // Important, send the fcm token to the server
 39         sendFCMTokenToServer(token);
 40     }
 41 
 42     // http://ebike-test.zriot.net/shop-app/push/token
 43     private void sendFCMTokenToServer(final String token) {
 44 
 45         if (TextUtils.isEmpty(token)) {
 46             return;
 47         }
 48 
 49         if (mService == null) {
 50             mService = RetrofitHelper.getInstance().getApiService(ApiService.class);
 51         }
 52 
 53         PreferencesUtils.getInstance().saveFCMToken(token);
 54 
 55         if (!AccountManager.getInstance().isUserLogin()) {
 56             return;
 57         }
 58 
 59         if (mParams == null) {
 60             mParams = new TreeMap<>();
 61         }
 62 
 63         if (mParams.size() == 0) {
 64             mParams.put("uid", AccountManager.getInstance().getUserId());
 65             mParams.put("token", AccountManager.getInstance().getToken());
 66             mParams.put("fcmToken", token);
 67             mParams.put("osType", "1"); // 1: android 2 : ios 70         }
 71 
 72         mService.sendFCMTokenToServer(mParams)
 73                 .subscribeOn(Schedulers.io())
 74                 .unsubscribeOn(Schedulers.io())
 75                 .observeOn(AndroidSchedulers.mainThread())
 76                 .subscribeWith(new DisposableObserverCallBack() {
 77                     @Override
 78                     public void onNext(@NonNull BaseResponse response) {
 79 
 80                         if (respOnse== null) {
 81                             return;
 82                         }
 83 
 84                         if (response.isRequestSuccess()) {
 85                             PreferencesUtils.getInstance().saveFCMTokenSendServiceSuccess(true);
 86                         }
 87 
 88                         mErrorCount = 0;
 89                     }
 90 
 91                     @Override
 92                     public void onError(Throwable e) {
 93                         super.onError(e);
 94 
 95                         if (mErrorCount >= REQUEST_ERROR_MAX) {
 96                             return;
 97                         }
 98 
 99                         if (!allowRequest()) {
100                             return;
101                         }
102 
103                         sendFCMTokenToServer(token);
104 
105                         mErrorCount += 1;
106                     }
107                 });
108     }
109 
110     private boolean allowRequest() {
111 
112         if (mRequestTime == 0) {
113             mRequestTime = System.currentTimeMillis();
114             return true;
115         }
116 
117         if (System.currentTimeMillis() - mRequestTime <3000) {
118 
119             return false;
120         } else {
121 
122             mRequestTime = System.currentTimeMillis();
123             return true;
124         }
125     }
126 
127 }

在android清单文件中:注册service:

 1      <service android:name=".fcm.ECFCMMSGService"
 2             android:stopWithTask="false">
 3             <intent-filter>
 4                 <action android:name="com.google.firebase.MESSAGING_EVENT" />
 5             intent-filter>
 6         service>
 7 
 8         <service android:name=".fcm.ECFCMTokenRefreshService"
 9             android:stopWithTask="false">
10             <intent-filter>
11                 <action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
12             intent-filter>
13         service>

注意:

App 是否运行,决定了推送走的两条线路

App 在运行的时候,推送如果有 Notification ,一般也是我们自己去控制的,所以最终它点击后的效果,我们是可以通过 PendingIntent 做部分定制的。

但是如果是在 App 没有运行的情况下,就完全归 FCM 服务帮你完成这一系列的操作,它点击后的效果,只能将你的 App 调起,并且把你需要的参数传递到你的 SplashActivity(Action 为 android.intent.action.MAIN 的 Activity) 上。

推送服务的 icon 和 字体颜色

FCM 的推送通知,可以配置 icon 以及 App 名称的颜色。对 icon 和 字体颜色的配置,需要在 AndroidManifest.xml 中进行。

还有一点需要注意,通常我们 App 的 Icon 都做的非常的精美,但是这种 Icon 是无法直接使用在 FCM 的推送上的。需要额外的定制,以及对应的尺寸。

FCM Icon 的标准:背景透明,以白色图案填充。(实际上,展开后的效果会将icon 进行着色,所以任何颜色最终都会被着色成我们配置的颜色,不配置默认是个浅灰色)。

当然,它和图标的适配一样,不一定需要全套,只需要配置我们需要的尺寸即可。

将以下代码行添加到 application 标记内,以设置自定义默认图标和app 名称的自定义颜色:



<meta-data
 android:name="com.google.firebase.messaging.default_notification_icon"
    android:resource="@drawable/ic_stat_ic_notification" />



<meta-data
 android:name="com.google.firebase.messaging.default_notification_color"
    android:resource="@color/colorAccent" />

AndroidManifest.xml

如果配置好这些,依然得到的是一个白色的小块,可以尝试升级一下 FCM 的版本,低版本好像是有这个 Bug ,在新版已经解决了。

 

问题:

  • Firebase API initialization failure.
  • Android app not receiving Firebase Notification when app is stopped from multi-task tray
  • Push notification works incorrectly when app is on background or not running
  • Push not received when app is killed

Firebase控制台测试只能发送Notification Message,测试的时候把App从最近列表划掉之后能收到,而且是在没FQ的情况下都能收到。当然当进程被完全杀死就收不到了。

Data Message则需要通过server api调用,前台后台都能收到透传消息。

Android Push Notifications using Firebase Cloud Messaging FCM & PHP

 


推荐阅读
  • 本文介绍了OpenStack的逻辑概念以及其构成简介,包括了软件开源项目、基础设施资源管理平台、三大核心组件等内容。同时还介绍了Horizon(UI模块)等相关信息。 ... [详细]
  • 如何查询zone下的表的信息
    本文介绍了如何通过TcaplusDB知识库查询zone下的表的信息。包括请求地址、GET请求参数说明、返回参数说明等内容。通过curl方法发起请求,并提供了请求示例。 ... [详细]
  • 本文记录了在vue cli 3.x中移除console的一些采坑经验,通过使用uglifyjs-webpack-plugin插件,在vue.config.js中进行相关配置,包括设置minimizer、UglifyJsPlugin和compress等参数,最终成功移除了console。同时,还包括了一些可能出现的报错情况和解决方法。 ... [详细]
  • GreenDAO快速入门
    前言之前在自己做项目的时候,用到了GreenDAO数据库,其实对于数据库辅助工具库从OrmLite,到litePal再到GreenDAO,总是在不停的切换,但是没有真正去了解他们的 ... [详细]
  • 概述H.323是由ITU制定的通信控制协议,用于在分组交换网中提供多媒体业务。呼叫控制是其中的重要组成部分,它可用来建立点到点的媒体会话和多点间媒体会议 ... [详细]
  • SpringBoot uri统一权限管理的实现方法及步骤详解
    本文详细介绍了SpringBoot中实现uri统一权限管理的方法,包括表结构定义、自动统计URI并自动删除脏数据、程序启动加载等步骤。通过该方法可以提高系统的安全性,实现对系统任意接口的权限拦截验证。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • baresip android编译、运行教程1语音通话
    本文介绍了如何在安卓平台上编译和运行baresip android,包括下载相关的sdk和ndk,修改ndk路径和输出目录,以及创建一个c++的安卓工程并将目录考到cpp下。详细步骤可参考给出的链接和文档。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 使用正则表达式爬取36Kr网站首页新闻的操作步骤和代码示例
    本文介绍了使用正则表达式来爬取36Kr网站首页所有新闻的操作步骤和代码示例。通过访问网站、查找关键词、编写代码等步骤,可以获取到网站首页的新闻数据。代码示例使用Python编写,并使用正则表达式来提取所需的数据。详细的操作步骤和代码示例可以参考本文内容。 ... [详细]
  • 本文介绍了如何使用JSONObiect和Gson相关方法实现json数据与kotlin对象的相互转换。首先解释了JSON的概念和数据格式,然后详细介绍了相关API,包括JSONObject和Gson的使用方法。接着讲解了如何将json格式的字符串转换为kotlin对象或List,以及如何将kotlin对象转换为json字符串。最后提到了使用Map封装json对象的特殊情况。文章还对JSON和XML进行了比较,指出了JSON的优势和缺点。 ... [详细]
  • 本文详细介绍了cisco路由器IOS损坏时的恢复方法,包括进入ROMMON模式、设置IP地址、子网掩码、默认网关以及使用TFTP服务器传输IOS文件的步骤。 ... [详细]
  • 本文介绍了Windows Vista操作系统中的用户账户保护功能,该功能是为了增强系统的安全性而设计的。通过对Vista测试版的体验,可以看到系统在安全性方面的进步。该功能的引入,为用户的账户安全提供了更好的保障。 ... [详细]
  • 基于移动平台的会展导游系统APP设计与实现的技术介绍与需求分析
    本文介绍了基于移动平台的会展导游系统APP的设计与实现过程。首先,对会展经济和移动互联网的概念进行了简要介绍,并阐述了将会展引入移动互联网的意义。接着,对基础技术进行了介绍,包括百度云开发环境、安卓系统和近场通讯技术。然后,进行了用户需求分析和系统需求分析,并提出了系统界面运行流畅和第三方授权等需求。最后,对系统的概要设计进行了详细阐述,包括系统前端设计和交互与原型设计。本文对基于移动平台的会展导游系统APP的设计与实现提供了技术支持和需求分析。 ... [详细]
  • 工作经验谈之-让百度地图API调用数据库内容 及详解
    这段时间,所在项目中要用到的一个模块,就是让数据库中的内容在百度地图上展现出来,如经纬度。主要实现以下几点功能:1.读取数据库中的经纬度值在百度上标注出来。2.点击标注弹出对应信息。3 ... [详细]
author-avatar
Yunir_944
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有