乐趣区

关于.net:MASA-MAUI-Plugin-十iOS消息推送原生APNS方式

背景

MAUI 的呈现,赋予了宽广.Net 开发者开发多平台利用的能力,MAUI 是 Xamarin.Forms 演变而来,然而相比 Xamarin 性能更好,可扩展性更强,构造更简略。然而 MAUI 对于平台相干的实现并不残缺。所以 MASA 团队发展了一个实验性我的项目,意在对微软 MAUI 的补充和扩大

我的项目地址https://github.com/BlazorComponent/MASA.Blazor/tree/feature/Maui/src/Masa.Blazor.Maui.Plugin

每个性能都有独自的 demo 演示我的项目,思考到 app 安装文件体积(尽管 MAUI 曾经集成裁剪性能,然而该性能对于代码自身有影响),届时每一个性能都会以独自的 nuget 包的模式提供,不便测试,当初我的项目才刚刚开始,然而置信很快就会有能够交付的内容啦。

前言

本系列文章面向挪动开发小白,从零开始进行平台相干性能开发,演示如何参考平台的官网文档应用 MAUI 技术来开发相应性能。

介绍

Apple 推送告诉服务(Apple Push Notification service),简称 APNs。与之前 Android 应用个推不同,因为 APNs 国内可用,所以咱们能够间接应用 APNs 来实现近程音讯推送,不依赖其余第三方组件和服务。咱们这里推送应用的是 p8 证书,p8 证书绝对 p12 证书来讲,更灵便,而且没有 p12 证书有效期 1 年的限度。

一、实现形式

一、申请 p8 证书

https://developer.apple.com/

1、登录开发者核心,点击右上角 Account,找到 Keys 治理。

2、在顶部点击 + 号。

3、勾选 APNs 服务,并输出 Key 名称,下一步 Continue。

4、点击 Register。

5、记录 Key ID, 并下载证书,失去 AuthKey_xxxxxxxxxx.p8 证书文件。

6、获取 Team ID,Account 界面点击 Membership details

二、编写 MAUI 实现代码

参考官网文档:https://developer.apple.com/documentation/usernotifications/r…

1、首先须要先开启 App 音讯推送的能力

咱们新建一个 iOSPush 文件夹,并在文件夹上面新建 MauiBlazor 我的项目iOSPushSample
(因为受打包长度影响,项目名称和文件夹名称,我这里尽量简短。门路长度超过 255 会导致编译时提醒局部文件找不到。)
咱们找到 Platforms->iOS->Info.plist 文件,双击用默认的 iOS 清单编辑器关上,勾选“启用后盾模式 ”和“ 近程告诉”。这项操作会在 Info.plist 文件中增加如下信息:

    <key>UIBackgroundModes</key>
    <array>
        <string>remote-notification</string>
    </array>

在开发环境,你须要以下的额定配置。

如果你的我的项目曾经应用了 Entitlements.plist 文件,双击关上改文件,并勾选“推送告诉”。

如果没有这个文件,那么新建这个文本文件,内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>aps-environment</key>
    <string>development</string>
</dict>
</plist>

留神:这项配置的目标是在 development 环境反对推送,如果在我的项目公布的时候,MAUI 不会主动革除,须要手动敞开或正文掉这项配置,否则会报错。

2、编写实现代码

参考文档 https://developer.apple.com/documentation/usernotifications/r…

咱们首先须要将 App 注册到 APNs 并获取惟一的 device token。在 iOS 中须要调用 UIApplication 中通过registerForRemoteNotifications() 办法,实现注册,如果注册胜利,就能够在delegateapplication(_:didRegisterForRemoteNotificationsWithDeviceToken:) 办法中获取 device token。如果注册失败,会触发application(_:didFailToRegisterForRemoteNotificationsWithError:) 办法。

Swift 代码
func application(_ application: UIApplication,
           didFinishLaunchingWithOptions launchOptions:
           [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
   // Override point for customization after application launch.you’re         
   UIApplication.shared.registerForRemoteNotifications()
   return true
}

func application(_ application: UIApplication,
            didRegisterForRemoteNotificationsWithDeviceToken 
                deviceToken: Data) {self.sendDeviceTokenToServer(data: deviceToken)
}

func application(_ application: UIApplication,
            didFailToRegisterForRemoteNotificationsWithError 
                error: Error) {// Try again later.}

咱们开始编写代码

向 APNs 注册设施

首先在iOS->AppDelegate.cs 类中,重写FinishedLaunching 办法,在利用启动之后进行注册。

    [Register("AppDelegate")]
    public class AppDelegate : MauiUIApplicationDelegate
    {protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
        public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
        {
            UNUserNotificationCenter center = UNUserNotificationCenter.Current;

            var options = UNAuthorizationOptions.Alert | UNAuthorizationOptions.Sound | UNAuthorizationOptions.CriticalAlert;
             // Request notification permissions from the user
            center.RequestAuthorization(options,
                (bool success, NSError error) =>
                {// Handle approval}
            );
            UIApplication.SharedApplication.RegisterForRemoteNotifications();
            return base.FinishedLaunching(application, launchOptions);
        }
    }

利用启动时应立即申请告诉权限,办法是将以下代码增加到FinishedLaunchingAppDelegate 所需告诉类型 (UNAuthorizationOptions) 的办法:

UNUserNotificationCenter 仅实用于 iOS 10+, 然而思考到根本没人用低于 10 的版本了,这里咱们就不做版本查看了

用户能够批准利用的三个不同级别的告诉申请:
横幅显示 -Alert。
声音警报 -Sound。
对利用图标进行谬误设置 -CriticalAlert。

申请权限完结后咱们通过 UIApplication.SharedApplication.RegisterForRemoteNotifications(); 向 APNs 注册。
注册胜利后咱们通过 application:didRegisterForRemoteNotificationsWithDeviceToken: 办法获取 device token,然而因为这个办法是在UIApplication 下,然而咱们的 AppDelegate 是继承自
MauiUIApplicationDelegate,默认没有这个办法,咱们能够通过Export 个性,导出咱们须要的办法,持续在 AppDelegate 中增加

        [Export("application:didFailToRegisterForRemoteNotificationsWithError:")]
        public void FailedToRegisterForRemoteNotifications(UIKit.UIApplication application, NSError error)
        {Console.WriteLine("FailedToRegisterForRemoteNotifications");
        }
        
        [Export("application:didRegisterForRemoteNotificationsWithDeviceToken:")]
        public void RegisteredForRemoteNotifications(UIKit.UIApplication application,
            Foundation.NSData deviceToken)
        {var token = ExtractToken(deviceToken);
            Preferences.Default.Set("PushToken", token);
            Console.WriteLine(token);
        }

        private string ExtractToken(NSData deviceToken)
        {if (deviceToken.Length == 0)
                return null;
            var result = new byte[deviceToken.Length];
            System.Runtime.InteropServices.Marshal.Copy(deviceToken.Bytes, result, 0, (int)deviceToken.Length);
            return BitConverter.ToString(result).Replace("-", "");
        }

ExtractToken是将返回的 deviceToken 解析为推送可用的字符串。
咱们通过 Preferences.Default.Set 将 token 存储起来,不便在登录等业务中应用。

接管近程推送

接管推送的音讯是通过 application:didReceiveRemoteNotification:fetchCompletionHandler: 实现的

        [Export("application:didReceiveRemoteNotification:fetchCompletionHandler:")]
        public void DidReceiveRemoteNotification(UIKit.UIApplication application, NSDictionary userInfo, Action<UIKit.UIBackgroundFetchResult> completionHandler)
        {foreach (var item in userInfo)
            {var alertMsg = ((NSDictionary)item.Value)["alert"];
                Console.WriteLine($"alertMsg:{alertMsg}");
            }
            Console.WriteLine("DidReceiveRemoteNotification");
        }

其实咱们在办法外部不须要写任何代码,就能够实现根本的推送性能。但如果想解决推送过去的音讯,能够通过 NSDictionary 类型 userInfo 中拿到。这里示例从 alert 中拿到具体的音讯内容,并打印。

三、编写演示代码

咱们批改Index.razor,通过点击按钮获取设施 Token

@page "/"

<button @onclick="GetDeviceToken">Get Device Token</button>
<text>@deviceToken</text>
@code
{private string deviceToken { get; set;}
    private void GetDeviceToken()
    {deviceToken= Preferences.Default.Get("PushToken",string.Empty);
    }
}

四、服务端测试

咱们能够通过个推的在线测试工具,配置好 p8 证书和其余参数。

我这里写了一个命令行的测试程序, 这里应用了第三方的 PushNotifications.Server 包

using PushNotifications.Server.Apple;

Console.WriteLine("Hello, World!");
IApnsClient apnsClient = new ApnsClient(new ApnsJwtOptions
{
    CertContent = "-----BEGIN PRIVATE KEY-----\r\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n-----END PRIVATE KEY-----",
    KeyId = "LUxxxxxxxx",
    TeamId = "V4xxxxxxxx",
    BundleId = "com.iOSPush.Sample",
    UseSandbox = true
});

var apnsRequest = new ApnsRequest(ApplePushType.Alert)
    .AddToken("47006118F8xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
    .AddSound()
    .AddAlert("MASA", $"Message @ {DateTime.Now}", $"Message @ {DateTime.Now}");
var apnsResponse = await apnsClient.SendAsync(apnsRequest);
Console.ReadKey();

五、演示成果

能够看出,利用关上的状态不会收到推送,后盾运行或者划掉敞开都能够收到告诉。


如果你对咱们的 MASA Framework 感兴趣,无论是代码奉献、应用、提 Issue,欢送分割咱们
WeChat:MasaStackTechOps
QQ:7424099

退出移动版