在实际APP开发过程中,消息推送是一个不可取少的功能,这里我们介绍在Xamarin.IOS项目中如何实现消息推送
首先我们在实现iOS端消息推送的时候,我们需要了解iOS系统的消息推送机制的原理是什么,然后再根据消息推送的原理去实现推送消息以及客户端收到消息后的后续操作,那么首先我们就开始介绍下消息推送的原理:
iOS消息推送原理
消息推送分为本地推送和远程推送两种:
1.本地推送:不需要联网也可以推送,是开发人员在APP内设定特定的时间来提醒用户干什么
2.远程推送:需要联网,用户的设备会于苹果APNS服务器形成一个长连接 ,用户设备会发送uuid和Bundle idenidentifier给苹果服务器,苹果服务器会加密生成一个deviceToken给用户设备,然后设备会将deviceToken发送给APP的服务器,APP服务器会将deviceToken存进他们的数据库,这时候如果有人发送消息给我,服务器端就会去查询我的deviceToken,然后将deviceToken和要发送的信息发送给苹果服务器,苹果服务器通过deviceToken找到我的设备并将消息推送到我的设备上。
Xamarin.iOS的消息推送实现
我们在实际开发过程中,一般我们都需要借助第三方平台的帮我们构建服务器端与APNS服务器的链接,在这里我们讲解极光推送的实现,其它第三方的推送原理也一样。
1.在 JPush的管理Portal 上创建应用并上传APNs证书。如果对APNs证书不太了解 请参考: iOS 证书设置指南
我们需要在Apple开发者官网登录我们的账户,申请iOS开发证书和生产证书上传给极光推送服务器进行审核,审核通过后根据应用分配一个应用的APPKey,这个APPKey在我们后续注册时候会用到。
2.下载最新的极光推送SDK,然后根据Xamarin.iOS转换工具(******Objective Sharpie******),把我们下载的SDK里面的.a文件操作然后生成类库提供给我们的项目进行调用,这里不清楚怎么使用iOS转换工具的可以参考我上一篇文章。
3.建立iOS项目调用我们根据极光推送SDK提供的.a文件和我们通过Objective Sharpie生成的.cs文件建立的类库,然后注册实现推送
接着我们需要给我们应用打开推送功能选项
接着我们就可以开始注册推送了
- 准备注册登录
//iOS10以上的注册方式
if (float.Parse(UIDevice.CurrentDevice.SystemVersion.Split('.')[0]) >= 10.0)
{
UNUserNotificationCenter center = UNUserNotificationCenter.Current;
center.RequestAuthorization((UNAuthorizationOptions.CarPlay | UNAuthorizationOptions.Alert | UNAuthorizationOptions.Sound | UNAuthorizationOptions.Badge), (bool arg1, NSError arg2) => {
if (arg1)
Console.WriteLine("ios 10 request notification success");
else
Console.WriteLine("IOS 10 request notification failed");
});
}
//iOS8以上的注册方式
else if (float.Parse(UIDevice.CurrentDevice.SystemVersion.Split('.')[0]) >= 8.0)
{
UIUserNotificationSettings notiSettings = UIUserNotificationSettings.GetSettingsForTypes(UIUserNotificationType.Badge | UIUserNotificationType.Sound | UIUserNotificationType.Alert, null);
UIApplication.SharedApplication.RegisterUserNotificationSettings(notiSettings);
}
//iOS8以下的注册方式,这里我们最低版本是7.0以上
else
{
UIRemoteNotificationType myTypes = UIRemoteNotificationType.Alert | UIRemoteNotificationType.Sound | UIRemoteNotificationType.Badge;
UIApplication.SharedApplication.RegisterForRemoteNotificationTypes(myTypes);
}
JPUSHService.SetupWithOption(launchOptions, "极光服务器分配的APPKey", "Publish channel", false);
JPUSHService.SetDebugMode();
UIApplication.SharedApplication.RegisterForRemoteNotifications();
if (launchOptions != null)
{
NSDictionary remoteNotification = (NSDictionary)(launchOptions.ObjectForKey(UIApplication.LaunchOptionsRemoteNotificationKey));
if (remoteNotification != null)
{
Console.WriteLine(remoteNotification);
//这里是跳转页面用的
this.goToMessageViewControllerWith(remoteNotification);
}
}
- 开始注册登录
public override void DidRegisterUserNotificationSettings(UIApplication application, UIUserNotificationSettings notificationSettings)
{
application.RegisterForRemoteNotifications();
}
- 注册成功会收到APNS服务器分配的应用的DeviceToken
public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
string token = deviceToken.Description;
token = token.Replace(" ", "");
token = token.Replace(">", "");
token = token.Replace("<", "");
System.Console.WriteLine(token);
JPUSHService.RegisterDeviceToken(token);
}
- 当注册失败是会调用一下方法,打印出错误原因
public override void FailedToRegisterForRemoteNotifications(UIApplication application, NSError error)
{
Console.WriteLine(error);
}
- 获取到DeviceToken成功后,我们需要将它传到极光服务开始推送
public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler)
{
JPUSHService.HandleRemoteNotification(userInfo);
//这里查看我们需要推送消息的内容,可不写
NSDictionary aps = (NSDictionary)userInfo["aps"];
SharedData.Instance.Values["checknum"] = aps["alert"];
application.ApplicationIconBadgeNumber = 0;
//根据推送消息内容的不同跳转到不同页面
this.goToMessageViewControllerWith(userInfo);
//
MsgBoxHelper.ShowMessage("接到到推送的消息", new string(userInfo.SelectMany(kv => string.Format("'{0}':'{1}'\n", kv.Key, kv.Value)).ToArray()));
if (completionHandler != null)
{
completionHandler(UIBackgroundFetchResult.NewData);
}
}
- 跳转页面的方法
private void goToMessageViewControllerWith(NSDictionary remoteNotification)
{
SharedData.Instance.Values["push"] = "push";
//如果推送消息字符串中tupes类型和我们内部匹配即跳转到指定页面
if ( SharedData.Instance.Values["types"] == remoteNotification["types"])
{
CheckPage ck = new CheckPage();
UINavigationController Nav = new UINavigationController(ck);
this.Window.RootViewController = Nav;
}
}
这样我们就可以在极光服务器上进行推送消息,然后客户端就能接收到消息了。
注意问题:
- 我们需要导入libz.tbd (Xcode7以下版本是libz.dylib)、UserNotifications.framework (Xcode8及以上)、libresolv.tbd (JPush 2.2.0及以上版本需要, Xcode7以下版本是libresolv.dylib)这些framework包,这里我们可以通过-gcc_flags方式在Additional mtouch arguments 中添加,也可以通过配置文件添加,如果不添加这些库不会编译通过或者收不到消息。
- 同时在APP Developer官网里面,我们不仅要下载开发证书和生产证书,还需要为推送配置一系列的配置文件,这些配置文件也是保证我们能接收到推送的消息的关键。
- 最后也是一点我开发中遇到的坑,当我们在一台电脑上配置了证书和配置文件后,如果我们换一台电脑采用相同的代码进行推送测试时,我们会发现接收不到推送的消息,因为这里的证书和配置文件只能在一台电脑上使用,如果想多台电脑都能使用的话,需要将证书到处为.p12文件传到另一台电脑进行安装,并且在开发者官网下载安装相应的配置文件。
网友评论
1.Error: linker command failed with exit code 1 (use -v to see invocation) (JPushtest)
2.Error MT5216: Native linking failed
引用的编译的DLL,我尝试了DEBUG和RELEASE都会报错(Release更多),微信我家你了