前期项目一直用的是Windows azure NotificationHub+Google Cloud Message 实现消息推送, 但是GCM google已经不再推荐使用,慢慢就不再维护了, 现在Google 主推 FCM, 另一方面,google在android生态中的权限要求越来越严格,不像以前那样将权限声明在AndroidManifest中,在安装的时候做一次提醒就好了, 现在对于一些主要的权限需要动态申请并且用户同意才能使用,比如调用相机,使用电话本等等,同样对于后台的常驻服务也做了一定的限制,旨在提升android系统的用户体验以及提高电池的续航时间,在2018-11-1强制执行编译的Target SDK API Leve必须是26+,否则是不允许上Goolge Play , GCM也只支持到2019-11-1,之后就不再支持,项目老的推送服务要依赖于后台常驻Service。 基于以上原因我对当前的android项目做了一次全面升级。这里分享一下GCM到FCM的迁移过程。

我们的项目用的微软的Azure平台,自然所有的一切技术都围绕着Windows Azure 平台展开。 Web App, Web API 使用的是Azure Cloud Service, Mobile APP 使用的是Xamarin, 数据库使用的是Azure SQL Database, 是不是很微软系。

自然在消息推送的时候想到的还是Azure平台上的技术 Notification Hub。

名词解释:

GCM: Google Cloud Message.

FCM: Firebase Cloud Message.

迁移步骤

1. 创建一个Firebase 项目并且开启Firebase Cloud Messaging功能。

2. 在Azure上创建一个NotificationHub。

3.将Firebase和ConnectionHub关联上。

4.创建一个Xiamarin android APP 并关联上 NotificationHub和 Firebase Cloud Message。

5. 测试消息发送。

注意:由于需要连接到Firebase Cloud Message 牵涉到墙的问题,需要手机能够翻墙, 否则测试将不能成功,另外,在做FCM的设置也是寸步难行。

准备工作

1. 需要一个google账号,用于创建Firebase 项目并开启 Firebase Cloud Message。

2.需要一个azure账号,用于创建NotificationHub。

3.Visual Studio并且要安装Xamarin 插件。

4. 准备一个VPN 用于测试。

创建一个Firebase 项目并且开启Firebase Cloud Messaging功能

打开 Firebase 开发控制台https://console.firebase.google.com/添加一个项目 如图:

这里我创建一个项目叫:XamarinAndroidFCM。创建好后像下面这样:

这一步暂时就创建到这里,我们需要一个android app的Package 名称, 下面我们将创建一个android项目创建好以后再回来设置这个包的名称。

在Azure上创建一个NotificationHub

登录到Azure 在云端在左边的菜单中找到NotificationHub项, 点击想创建一个Notification Hub Namespaces, 然后进入NameSpace并且创建一个NotificaitonHub。

然后点击创建的NotificaitonHub名字进入设置界面,并且点击中间的菜单GCM(google),设置这个API key

这个key 来自上一步创建的Firebase 项目:

这样FCM 和Notifaction Hub就关联好了。

创建一个Xiamarin android APP 并关联上 NotificationHub和 Firebase Cloud Message

打开VS 创建一个xiamarin for Android的项目。创建好后如下:

打开项目将的配置文件:AndroidManifest.xml, 将里面的包名改成小写(这里很重要,如果不改成小写,你将不会收到任何消息,这是个坑,做GCM的时候也是一样, 测试了很多次才找出来这个原因

<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1"
android:versionName="1.0" package="xamarinandroidfcm.xamarinandroidfcm">

这里我们将这个包名“xamarinandroidfcm.xamarinandroidfcm” 填到第一步FCM中去 并保存。

保存完成后点击右边的google-service.json 文件下载到本地并加入到创建的android项目中

这样FCM的相关设置就完了。

在android的项目中做FCM 以及Azure NotificationHub的连接并接收消息

1. 添加相关的依赖包: Xamarin.Firebase.Messaging 和 Xamarin.Azure.NotificationHubs.Android

2. 设置google-service.json 的build action 为“GoogleServicesJson”(如果找不到这一项,重启一下VS重新设置就可以找到了

3. 在AndroidManifest.xmal 的Application节点中加入以下配置:

<receiver android:name="com.google.firebase.iid.FirebaseInstanceIdInternalReceiver" android:exported="false" />
<receiver android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver" android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="${applicationId}" />
</intent-filter>
</receiver>

如下:

4. 配置Notification Hub 账号到代码中。

在项目中创建一个Class 叫:Constants, 并创建两个常量用于保存NotificaiotnHub的连接字符串和名称。打开azrue中创建的Hub 点击左边的Access Policy,看到如下界面:

将DefaultListenSharedAccessSignature的Connection String值拷贝到刚刚创建的那个常量 ListenConnectionString 中。并把Notificaiton Hub的名字保存在

NotificationHubName中。

5.创建MyFirebaseIidService 服务类用于接收和刷新Firebase的token, 并将token以及tag注册到Notificationhub.

using System.Collections.Generic;
using Android.App;
using Android.Util;
using WindowsAzure.Messaging;
using Firebase.Iid; namespace XamarinAndroidFCM
{
[Service]
[IntentFilter(new[] {"com.google.firebase.INSTANCE_ID_EVENT"})]
public class MyFirebaseIidService : FirebaseInstanceIdService
{
private const string Tag = "MyFirebaseIIDService";
NotificationHub _hub; public override void OnTokenRefresh()
{
var refreshedToken = FirebaseInstanceId.Instance.Token;
Log.Debug(Tag, "FCM token: " + refreshedToken);
SendRegistrationToServer(refreshedToken);
} void SendRegistrationToServer(string token)
{
// Register with Notification Hubs
_hub = new NotificationHub(Constants.NotificationHubName,Constants.ListenConnectionString, this); var tags = new List<string>() { "" };
var regID = _hub.Register(token, tags.ToArray()).RegistrationId;
Log.Debug(Tag, $"Successful registration of ID {regID}");
}
}
}

6. 创建接收消息的服务:MyFirebaseMessagingService 用于接收消息并显示给用户:

using System;
using System.Linq;
using Android.App;
using Android.Content;
using Android.Util;
using Android.Widget;
using Firebase.Messaging; namespace XamarinAndroidFCM
{
[Service]
[IntentFilter(new[] {"com.google.firebase.MESSAGING_EVENT"})]
public class MyFirebaseMessagingService : FirebaseMessagingService
{
private const string Tag = "MyFirebaseMsgService";
public override void OnMessageReceived(RemoteMessage message)
{
Log.Debug(Tag, "From: " + message.From);
if (message.GetNotification() != null)
{
//These is how most messages will be received
Log.Debug(Tag, "Notification Message Body: " + message.GetNotification().Body);
SendNotification(message.GetNotification().Body);
}
else
{
//Only used for debugging payloads sent from the Azure portal
CreateNotification("Test FCM", message.Data.Values.First(), "15:30");
}
} void SendNotification(string messageBody)
{
var intent = new Intent(this, typeof(MainActivity));
intent.AddFlags(ActivityFlags.ClearTop);
var pendingIntent = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.OneShot); var notificationBuilder = new Notification.Builder(this)
.SetContentTitle("FCM Message")
.SetSmallIcon(Resource.Drawable.ic_launcher)
.SetContentText(messageBody)
.SetAutoCancel(true)
.SetContentIntent(pendingIntent); var notificationManager = NotificationManager.FromContext(this);
notificationManager.Notify(0, notificationBuilder.Build());
} void CreateNotification(string title, string desc, string time)
{
var notificationManager = GetSystemService(Context.NotificationService) as NotificationManager;
var uiIntent = new Intent(this, typeof(MainActivity));
var notification = new Notification(Resource.Mipmap.ic_launcher, title);
notification.Flags = NotificationFlags.AutoCancel;
notification.Defaults = NotificationDefaults.All;
notification.Vibrate = new long[] { 0, 100, 200, 300 };
if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.JellyBean)
{
var contentView = new RemoteViews(PackageName, Resource.Layout.Custom_Notification);
contentView.SetTextViewText(Resource.Id.txtTitle, title);
contentView.SetTextViewText(Resource.Id.txtTime, time);
contentView.SetTextViewText(Resource.Id.txtContent, desc);
notification.BigContentView = contentView;
}
notification.SetLatestEventInfo(this, title, desc, PendingIntent.GetActivity(this, 0, uiIntent, PendingIntentFlags.UpdateCurrent)); var rnd = new Random();
var notificationId = rnd.Next(10000, 99999); notificationManager.Notify(notificationId, notification);
}
}
}

代码部分全部实现完成。

测试

打开模拟器或手机,设置代理, 调试应用, 并且再次打开Azure Notifiaciton Hub 进入到测试界面进行测试:

手机端接收到的消息如下:

总结,Notificaiton Hub + FCM发送消息比较简单,但是也有许多坑,设置比较多,比如应用包的大小写问题,翻墙的问题都是一些小的阻碍,但是这个消息推送还是比较稳定的, 适合一些国外的项目。 如果做国内的项目可以考虑Notification Hub+ 百度message来做消息推送,当然也可以用一些第三方的SDK来做。

源码下载地址: https://github.com/Xushlin/PushNotificaiton

Windows Azure NotificationHub+Firebase Cloud Message 实现消息推动(付源码)的更多相关文章

  1. [Xamarin.Android] 結合Windows Azure與Google cloud message 來實現Push Notification (转帖)

    這一篇要討論如何使用Xamarin.Android 整合GCM以及Windows Azure來實作Android手機上的推播通知服務. 這篇文章比較著重概念的部分,在開始讀這篇之前,也可以先參考一下X ...

  2. [Windows Azure] Windows Azure Web Sites, Cloud Services, and VMs: When to use which?

    This document provides guidance on how to make an informed decision in choosing between Windows Azur ...

  3. RocketMQ中PullConsumer的消息拉取源码分析

    在PullConsumer中,有关消息的拉取RocketMQ提供了很多API,但总的来说分为两种,同步消息拉取和异步消息拉取 同步消息拉取以同步方式拉取消息都是通过DefaultMQPullConsu ...

  4. 一步步实现windows版ijkplayer系列文章之七——终结篇(附源码)

    一步步实现windows版ijkplayer系列文章之一--Windows10平台编译ffmpeg 4.0.2,生成ffplay 一步步实现windows版ijkplayer系列文章之二--Ijkpl ...

  5. 一步步实现windows版ijkplayer系列文章之二——Ijkplayer播放器源码分析之音视频输出——视频篇

    一步步实现windows版ijkplayer系列文章之一--Windows10平台编译ffmpeg 4.0.2,生成ffplay 一步步实现windows版ijkplayer系列文章之二--Ijkpl ...

  6. 微服务架构 | *2.3 Spring Cloud 启动及加载配置文件源码分析(以 Nacos 为例)

    目录 前言 1. Spring Cloud 什么时候加载配置文件 2. 准备 Environment 配置环境 2.1 配置 Environment 环境 SpringApplication.prep ...

  7. windows azure Vm、cloud service、web application 如何选择可用的服务

    windows azure 的web应用和虚拟机都经常用.我们经常把我们的网站部署上去.一般选择web应用或者开一个虚拟机.开一个虚拟机就会按照虚拟机的使用时间进行计费. 那么我们选择web部署在哪里 ...

  8. C# Socket异步实现消息发送--附带源码

    前言 看了一百遍,不如动手写一遍. Socket这块使用不是特别熟悉,之前实现是公司有对应源码改改能用. 但是不理解实现的过程和步骤,然后最近有时间自己写个demo实现看看,熟悉熟悉Socket. 网 ...

  9. mfc 调用Windows的API函数实现同步异步串口通信(源码)

    在工业控制中,工控机(一般都基于Windows平台)经常需要与智能仪表通过串口进行通信.串口通信方便易行,应用广泛. 一般情况下,工控机和各智能仪表通过RS485总线进行通信.RS485的通信方式是半 ...

随机推荐

  1. 干货|一个案例学会Spring Security 中使用 JWT

    在前后端分离的项目中,登录策略也有不少,不过 JWT 算是目前比较流行的一种解决方案了,本文就和大家来分享一下如何将 Spring Security 和 JWT 结合在一起使用,进而实现前后端分离时的 ...

  2. 你真的了解字典(Dictionary)吗?

    从一道亲身经历的面试题说起 半年前,我参加我现在所在公司的面试,面试官给了一道题,说有一个Y形的链表,知道起始节点,找出交叉节点. 为了便于描述,我把上面的那条线路称为线路1,下面的称为线路2. 思路 ...

  3. 强化学习(十三) 策略梯度(Policy Gradient)

    在前面讲到的DQN系列强化学习算法中,我们主要对价值函数进行了近似表示,基于价值来学习.这种Value Based强化学习方法在很多领域都得到比较好的应用,但是Value Based强化学习方法也有很 ...

  4. 我们一起来排序——使用Java语言优雅地实现常用排序算法

    破阵子·春景 燕子来时新社,梨花落后清明. 池上碧苔三四点,叶底黄鹂一两声.日长飞絮轻. 巧笑同桌伙伴,上学径里逢迎. 疑怪昨宵春梦好,元是今朝Offer拿.笑从双脸生. 排序算法--最基础的算法,互 ...

  5. Vscode新建html文件

    在Vscode新建html文件 1.点击Open Folder: 2.选择目标文件夹,新建一个拓展名为html的文件: 3.在第1行输入!(英文状态下),按tab键,新建成功.界面如下图所示:

  6. openlayers4 入门开发系列之小区信号扇形图篇

    前言 openlayers4 官网的 api 文档介绍地址 openlayers4 api,里面详细的介绍 openlayers4 各个类的介绍,还有就是在线例子:openlayers4 官网在线例子 ...

  7. emacs 高亮

    用途:让某个单词高亮显示 1,安装 m-x 回车,输入list-packages 在列表中找到highlight-symbol后,鼠标点击它,再点击安装 2,在.emacs中配置 ;;高亮 (requ ...

  8. 计算器模拟器中的情怀——Free42简介

    说到情怀,我首先想聊几句电子计算器的历史.电子计算器这种东西,在最近这几十年的人类发展中,曾经起到过相当重要的作用,尤其是在七十年代到九十年代初这个时期,大型的全功能电脑贵得要命,有钱有时也买不到,而 ...

  9. eShopOnContainers 知多少[1]:总体概览

    引言 在微服务大行其道的今天,Java阵营的Spring Boot.Spring Cloud.Dubbo微服务框架可谓是风水水起,也不得不感慨Java的生态圈的火爆.反观国内.NET阵营,微服务却不愠 ...

  10. Flarum轻量级论坛的安装

    论坛作为互联网中的远古产物,经历了如QQ群.社区和贴吧等新兴社交工具的冲击,依然能够存在,肯定是有着不可替代的用处,像吾爱.远景等论坛依旧火热.一些博客主也喜欢自己搭建一个论坛作为用户聚集之地. 之前 ...