Windows Azure NotificationHub+Firebase Cloud Message 实现消息推动(付源码)
前期项目一直用的是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 实现消息推动(付源码)的更多相关文章
- [Xamarin.Android] 結合Windows Azure與Google cloud message 來實現Push Notification (转帖)
這一篇要討論如何使用Xamarin.Android 整合GCM以及Windows Azure來實作Android手機上的推播通知服務. 這篇文章比較著重概念的部分,在開始讀這篇之前,也可以先參考一下X ...
- [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 ...
- RocketMQ中PullConsumer的消息拉取源码分析
在PullConsumer中,有关消息的拉取RocketMQ提供了很多API,但总的来说分为两种,同步消息拉取和异步消息拉取 同步消息拉取以同步方式拉取消息都是通过DefaultMQPullConsu ...
- 一步步实现windows版ijkplayer系列文章之七——终结篇(附源码)
一步步实现windows版ijkplayer系列文章之一--Windows10平台编译ffmpeg 4.0.2,生成ffplay 一步步实现windows版ijkplayer系列文章之二--Ijkpl ...
- 一步步实现windows版ijkplayer系列文章之二——Ijkplayer播放器源码分析之音视频输出——视频篇
一步步实现windows版ijkplayer系列文章之一--Windows10平台编译ffmpeg 4.0.2,生成ffplay 一步步实现windows版ijkplayer系列文章之二--Ijkpl ...
- 微服务架构 | *2.3 Spring Cloud 启动及加载配置文件源码分析(以 Nacos 为例)
目录 前言 1. Spring Cloud 什么时候加载配置文件 2. 准备 Environment 配置环境 2.1 配置 Environment 环境 SpringApplication.prep ...
- windows azure Vm、cloud service、web application 如何选择可用的服务
windows azure 的web应用和虚拟机都经常用.我们经常把我们的网站部署上去.一般选择web应用或者开一个虚拟机.开一个虚拟机就会按照虚拟机的使用时间进行计费. 那么我们选择web部署在哪里 ...
- C# Socket异步实现消息发送--附带源码
前言 看了一百遍,不如动手写一遍. Socket这块使用不是特别熟悉,之前实现是公司有对应源码改改能用. 但是不理解实现的过程和步骤,然后最近有时间自己写个demo实现看看,熟悉熟悉Socket. 网 ...
- mfc 调用Windows的API函数实现同步异步串口通信(源码)
在工业控制中,工控机(一般都基于Windows平台)经常需要与智能仪表通过串口进行通信.串口通信方便易行,应用广泛. 一般情况下,工控机和各智能仪表通过RS485总线进行通信.RS485的通信方式是半 ...
随机推荐
- vue项目使用websocket技术
一.为什么需要websocket? 前端和后端的交互模式最常见的就是前端发数据请求,从后端拿到数据后展示到页面中.如果前端不做操作,后端不能主动向前端推送数据,这也是http协议的缺陷. 因此,一种新 ...
- Vue2.0源码阅读笔记(三):计算属性
计算属性是基于响应式依赖进行缓存的,只有在相关响应式依赖发生改变时才会重新求值,这种缓存机制在求值消耗比较大的情况下能够显著提高性能. 一.计算属性初始化 Vue 在做数据初始化时,通过 in ...
- 【原】使用less实现随机下雪动画
元旦在公司撸码,想起圣诞节的摇摇乐项目有段代码挺有意思的,借着空闲的时间把代码抽出来,沉淀下经验.冬天来了,设计师说摇摇乐的场景需要随机下落的雪花动画,第一时间就想到的方法是canvas比较好,项目非 ...
- CopyOnWriteArrayList你都不知道,怎么拿offer?
前言 只有光头才能变强 前一阵子写过一篇COW(Copy On Write)文章,结果阅读量很低啊...COW奶牛!Copy On Write机制了解一下 可能大家对这个技术比较陌生吧,但这项技术是挺 ...
- EFCore中 join on的不同
当 多条件 left join on 时 LEFT OUTER JOIN on new { u.UserId, ue.ExamId } equals new { sac.UserId, sac.Exa ...
- flex 布局实现固定头部和底部,中间滚动布局
关键词:display: flex,flex: 1, overflow-y: scroll; 实现:head 和footer 固定,中间body多了滚动,少了撑满: head和footer宽度根据内 ...
- 1.App Inventor 2简介
App Inventor 原是Google实验室(Google Lab)的一个子计划,由一群Google工程师和勇于挑战的Google使用者共同参与设计完成.Google App Inventor是一 ...
- SpringCloud警告(Eureka):EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.
警告!Eureka可能存在维护了错误的实例列表(当它们没有启动的时候,Eureka却把它当成启动的了):Renews值小于Threshold值,因此剩下未过期的都是安全的. 原因分析: 这个是Eure ...
- Java面试题:Java中怎么样实现多线程
方法一:继承 Thread 类,覆盖方法 run(),我们在创建的 Thread 类的子类中重写 run() ,加入线程所要执行的代码即可. 下面是一个例子: public class MyThrea ...
- 从壹开始前后端分离 [ Vue2.0+.NET Core2.1] 二十一║Vue实战:开发环境搭建【详细版】
缘起 哈喽大家好,兜兜转转终于来到了Vue实战环节,前边的 6 篇关于Vue基础文章我刚刚简单看了看,感觉写的还是不行呀,不是很系统,所以大家可能看上去比较累,还是得抽时间去润润色,修改修改语句和样式 ...