前期项目一直用的是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. Vue.js-08:第八章 - 组件的基础知识

    一.前言 在之前的学习中,我们对于 Vue 的一些基础语法进行了简单的了解,通过之前的代码可以清晰的看出,我们在使用 Vue 的整个过程,最终都是在对 Vue 实例进行的一系列操作. 这里就会引出一个 ...

  2. .netcoreapp 发布到 linux 的问题,vs靠不住

    .netcore 2.0 发布后,小版本更新速度惊人 截止目前:2.1.200 最新一个新项目,vs发布到linux@debian9一直报错,反复发布n次依然失败.把本地2.1.100更新到最新2.1 ...

  3. 如何理解Axis?

    前言 只有光头才能变强. 回顾前面: 从零开始学TensorFlow[01-搭建环境.HelloWorld篇] 什么是TensorFlow? TensorFlow读写数据 不知道大家最开始接触到axi ...

  4. HTML 练习js代码位置在head标签

    方式一: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF- ...

  5. SAP HUM事务代码 HUMAT 之初探

    SAP HUM事务代码 HUMAT 之初探 SAP菜单中,该事务代码在这里: 1)如下的inbound delivery号码, Document flow, 已经完成了PGR, 2)执行HUMAT,进 ...

  6. maven pom 引入本地jar包

    maven pom 引入本地jar包 在pom.xml同级目录下新建lib文件夹,并放入本地jar包. 配置Jar包的dependency,包括groupId,artifactId,version三个 ...

  7. pod command

    pod 基础使用命令 创建Podfile文件 1 pod init 使用命令打开Podfile文件 1 open -a Xcode Podfile 搜索pod 库 1 pod search 库名 更新 ...

  8. PHP错误:SQLSTATE[HY000] [2054] The server requested authentication method unknown to the client

    使用PHP连接MySQL 8的时候,可能会发生如标题所示的错误: SQLSTATE[HY000] [2054] The server requested authentication method u ...

  9. 群晖NAS再折腾

    端口转发 两年前我买了一台双盘位的群晖NAS,配置两个4T的硬盘,这玩意儿一度改变了我使用电脑的模式,真是爽爆了!最最主要的功能就是我能用它规整我所有的资料,并且不管何时何地,只要有网就能访问.为了能 ...

  10. Redis 小记

    最近感觉自己像是又回到了起点,知识层面上落人太多,尤其是去年早些时候几乎啥也没干成,觉得什么也不会了,只能再次从零开始,所以决定再喝两个疗程的巩固巩固. 话不多说,我们先来看看 Redis 官方是怎么 ...