当前位置: 移动技术网 > 移动技术>移动开发>Android > Windows Azure NotificationHub+Firebase Cloud Message 实现消息推动(付源码)

Windows Azure NotificationHub+Firebase Cloud Message 实现消息推动(付源码)

2018年12月18日  | 移动技术网移动技术  | 我要评论

前期项目一直用的是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 牵涉到墙的问题,需要手机能够fq, 否则测试将不能成功,另外,在做fcm的设置也是寸步难行。

准备工作

1. 需要一个google账号,用于创建firebase 项目并开启 firebase cloud message。

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

3.visual studio 并且要安装xamarin 插件。

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

创建一个firebase 项目并且开启firebase cloud messaging功能

打开 firebase 开发控制台添加一个项目 如图:

 

这里我创建一个项目叫: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>() { "1" };
            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发送消息比较简单,但是也有许多坑,设置比较多,比如应用包的大小写问题,fq的问题都是一些小的阻碍,但是这个消息推送还是比较稳定的, 适合一些国外的项目。 如果做国内的项目可以考虑notification hub+ 百度message来做消息推送,当然也可以原则一些第三方的sdk来做。

源码下载地址: https://github.com/xushlin/pushnotificaiton

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网