前期项目一直用的是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 开发控制台添加一个项目 如图:
这里我创建一个项目叫:xamarinandroidfcm。创建好后像下面这样:
这一步暂时就创建到这里,我们需要一个android app的package 名称, 下面我们将创建一个android项目创建好以后再回来设置这个包的名称。
登录到azure 在云端在左边的菜单中找到notificationhub项, 点击想创建一个notification hub namespaces, 然后进入namespace并且创建一个notificaitonhub。
然后点击创建的notificaitonhub名字进入设置界面,并且点击中间的菜单gcm(google),设置这个api key
这个key 来自上一步创建的firebase 项目:
这样fcm 和notifaction hub就关联好了。
打开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的相关设置就完了。
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
如对本文有疑问, 点击进行留言回复!!
android -- ndk (stack corruption detected)
Android Span富文本图文混排 - ImageSpan(图文垂直居中)
Element DateTimePicker日期时间选择器的使用示例
【Appium踩坑】小米手机,启动报错:exited with code 255 writing to settings requires:android.permission.WRITE_SECUR
android 拍照 预览图与 照片分辨率(可视区域)不一致
[PAT顶级]1025 Keep at Most 100 Characters (35分)
网友评论