Xamarin.iOS使用極光JPush進行推送

【備註(轉載請說明出處,"http://www.cnblogs.com/RedSky/p/6679443.html","若是本文對你有幫助,請給個贊")】html

本文將教你如何在Xamarin中使用極光JPush對IOS進行推送。ios

要開發iOS應用程序,你須要一臺mac,Xamarin並不能支持在Windows上單獨開發iOS;要進行推送測試,這隻能在真機上進行測試,因此你還須要一部iPhone手機。xcode

 

簡要步驟app

  1. 配置開發環境及工具
  2. 申請蘋果開發者證書,App IDs,推送開發版證書,以及配置文件
  3. 配置極光環境
  4. 使用Xcode創建靜態類庫配置極光sdk
  5. 將靜態類庫生成.a文件庫
  6. 將靜態類庫生成ApiDefinition.cs和StructsAndEnums.cs
  7. 在Xcode創建應用項目
  8. 創建Xamarin.iOS項目
  9. 創建Native Library
  10. 引用Native Library
  11. 測試

 

1.配置開發環境及工具框架

 

這咱們的開發環境及工具:iphone

 

    • Visual Studio 2013 Update 5
    • Xamarin for Visual Studio 4.3.0.784
    • Xcode 8.3
    • 手機iPhone 4 A1332
    • JPush iOS sdk 3.0.2
    • Objective Sharpie(下載連接:https://xamarin.azureedge.net/objective-sharpie/ObjectiveSharpie.pkg)
    • Windows 10
    • macOS 10.12.3

  這裏內容過長不做詳細講解,可到網上參考其餘資料進行。ide

 

2.申請蘋果開發者證書,App IDs,推送開發版證書,以及配置文件函數

  這裏內容過長不做詳細教學,可到網上參考其餘資料進行。這步驟完成後下載配置文件到mac本機。工具

 

3.配置極光環境測試

  註冊極光開發者帳號,新建應用,將推送開發版證書上傳到應用,下載客戶端iOS sdk。具體步驟可在極光官網查看。

 

4.使用Xcode創建靜態類庫配置極光sdk

  在mac裏打開Xcode新建項目,這裏咱們選擇Static Library,點擊Next。

    

 

  項目名稱咱們隨便填一個,這裏咱們使用PushLibrary,而後完成,完成後會進入到項目界面。

  接下來咱們給項目引入極光官網的iOS sdk,引入後項目結構以下,注意,這裏咱們要將sdk的Lib文件夾複製到項目目錄下後在添加到項目中,再將JPUSHService.h複製到PushLibrary.h同一目錄下,引用jcore-ios-1.1.1.a, jpush-ios-3.0.2.a, JPUSHService.h要引用複製到項目目錄裏的文件。

  

  這裏有兩個文件注意一下(libresolv.9.dylib, libz.1.dylib),官方是libz.tbd和libresolv.tbd,若是你添加這兩個文件後嘗試編譯未經過,請按下面方法。

  引用libz.tbd與引用libresolv.tbd方法相同,這裏咱們以libz.tbd爲例。點擊你的libz.tbd文件,在右側文檔裏看見install-name: 

  

  這裏咱們要添加libz.1.dylib,若是你的跟圖片上不同,請使用你本身的。在linking Binary中添加

  

  在彈出窗口中選擇左下角And Other...

  

  在新彈出窗口內右側搜索框裏咱們填上libz.1.dylib

  

  這裏咱們選擇其中一個,Open。

  這就完成了,libresolv.tbd的處理方法同樣。

  咱們進行編譯,編譯經過。

 

5.將靜態類庫生成.a文件庫

  這裏咱們能夠參考Xamarin官方文檔,參考連接:https://developer.xamarin.com/guides/ios/advanced_topics/native_interop/。

  咱們須要生成arm64, armv7, armv7s三個版本的.a文件庫,而後再將它們合併成一個文件庫。

  首先找到咱們靜態類庫項目目錄,經過右鍵項目>Show in Finder;右鍵項目文件>取得資訊(繁體版系統會顯示取得資訊,若是你的是簡體版可能不同,就是查看文件信息的意思)。

  

  

 

  咱們選擇「位置「複製路徑,在mac命令器裏輸入項目目錄

  

cd /mydir/mydir

 

  回車進入項目目錄;接着輸入命令生成arm64的.a文件:

  

/Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -project PushLibrary.xcodeproj -target PushLibrary -sdk iphoneos -arch arm64 -configuration Release clean build

  成功後進入build目錄iphoneos目錄裏找到libPushLibrary.a文件,重命名爲libPushLibrary-arm64.a。

 

  生成armv7命令:  

/Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -project PushLibrary.xcodeproj -target PushLibrary -sdk iphoneos -arch armv7 -configuration Release clean build

    成功後進入build目錄iphoneos目錄裏找到libPushLibrary.a文件,重命名爲libPushLibrary-armv7.a。

 

  生成armv7s命令:  

/Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -project PushLibrary.xcodeproj -target PushLibrary -sdk iphoneos -arch armv7s -configuration Release clean build

    成功後進入build目錄iphoneos目錄裏找到libPushLibrary.a文件,重命名爲libPushLibrary-armv7s.a。

 

  好,到這裏咱們經過」cd「命令進入到這三個文件所在目錄,輸入以下命令:

lipo -create -output libPushLibrary.a libPushLibrary-arm64.a libPushLibrary-armv7.a libPushLibrary-armv7s.a

  回車後就會生成咱們須要的libPushLibrary.a文件。

  

 

6.將靜態類庫生成ApiDefinition.cs和StructsAndEnums.cs

  這裏咱們須要用到Objective Sharpie,下載連接在上文已經提供,下載後安裝在mac中。

  如今咱們在mac命令器中使用sharpie生成ApiDefinition.cs和StructsAndEnums.cs。

sharpie bind -sdk=iphoneos10.2 [項目目錄]/PushLibrary/*.h

  -sdk是iphoneos版本號,這裏你能夠經過命令

 

sharpie bind -sdks

 

  獲取本身已安裝的sdk版本號,在這裏咱們使用已安裝的iphoneos10.2。

 

  若是沒有錯誤的話,你會獲得ApiDefinition.cs和StructsAndEnums.cs。

  如今你獲得三個文件libPushLibrary.a, ApiDefinition.cs和StructsAndEnums.cs。

  

  

7.在Xcode創建應用項目

  這裏咱們選擇Single View Application就能夠。

  

  點擊Next>

  

  上面圖片裏注意命名規則,若是註冊App IDs時Bundle Identifier是com.XXX.xxx,那麼Product Name就是對應的xxx。填寫完成點擊Next。

  在項目配置裏添加以前申請開發者證書時下載的配置文件:

      

 

  編譯項目

      

 

  在mac機上的操做到這裏算結束。

 

8.創建Xamarin.iOS項目

  在Visual Studio裏新建一個項目,項目名稱隨意,生成後咱們打開項目屬性。

    

  平臺選擇iPhone,應用名稱和識別碼填寫對應Bundle Identifier;滾動條往下拖。

    

  勾選中啓用背景模式,遠端通知。勾選後才能得到通知權限。

  在iOS Bundle Signing選擇身份和配置文件:

      

 編譯項目。

 

9.創建Native Library

  右鍵解決方案新建項目,選擇

    

  項目名稱隨意命名,新建Native Library後將以前生成的libPushLibrary.a文件添加到項目中。

    

  添加後會在.a文件下自動生成個libPushLibrary.linkwith.cs文件,咱們打開這個文件,"[assembly: ..."一行替換爲:

[assembly: LinkWith("libPushLibrary.a", Frameworks="AdSupport CFNetwork CoreFoundation CoreGraphics CoreTelephony UIKit Foundation Security SystemConfiguration UserNotifications", LinkerFlags="-ObjC -lz.1 -lresolv.9", LinkTarget = LinkTarget.Arm64 | LinkTarget.ArmV7 | LinkTarget.ArmV7s, ForceLoad = true, SmartLink = true)]

  注意這裏-lz.1 -lresolv.9要對應以前你添加的libz和libresolv,libz寫做lz,前有'-'。

  完成後再將ApiDefinition.cs和StructsAndEnums.cs裏的代碼複製到對應cs文件裏,注意命名空間引用。在ApiDefinition.cs裏找到有Verify標籤([Verify(...)])的行,將這些行刪掉,將[IOS(...)]標籤註釋掉

    

  註釋或刪除函數SetTags(NSSet tags, string alias, Selector cbSelector, NSObject theTarget);這個方法重複了,註釋掉過時的函數。

    

  StructsAndEnums.cs裏nuint替換成uint。

    

  編譯項目,到這裏就完成了Native Library的建立,完成了極光sdk的引用。

 

10.引用Native Library

  如今在咱們的Xamarin.iOS應用項目裏引用Native Library項目。

  咱們建立兩個類文件用來註冊極光推送id和接收推送消息的類:

    

  代碼以下:

  JPushInterface.cs:

 

using Foundation;
using IOSNativeLibrary;
using System;
using System.Collections.Generic;
using System.Text;
using UserNotifications;

namespace App1.iOS.Notification.JPush
{
    public class JPushInterface : IOSNativeLibrary.JPUSHRegisterDelegate
    {
        internal static string JPushAppKey = "個人極光AppKey";
        internal static string Channel = "";
        JPushRegisterEntity entity { get; set; }
        public void Register(AppDelegate app, NSDictionary options)
        {
            //註冊apns遠程推送
            string advertisingId = AdSupport.ASIdentifierManager.SharedManager.AdvertisingIdentifier.AsString();
            this.entity = new JPushRegisterEntity();
            this.entity.Types = 1 | 2 | 3;//entity.Types = (nint)(JPAuthorizationOptions.Alert) | JPAuthorizationOptions.Badge | JPAuthorizationOptions.Sound;
            JPUSHService.RegisterForRemoteNotificationConfig(entity, this);
            JPUSHService.SetupWithOption(options, JPushAppKey, Channel, true, advertisingId);
            JPUSHService.RegistrationIDCompletionHandler(app.GetRegistrationID);
        }

        /// <summary>
        /// 前臺收到通知,IOS10 support
        /// </summary>
        /// <param name="center"></param>
        /// <param name="notification"></param>
        /// <param name="completionHandler"></param>
        public override void WillPresentNotification(UserNotifications.UNUserNotificationCenter center, UserNotifications.UNNotification notification, Action<nint> completionHandler)
        {
            Console.WriteLine("WillPresentNotification:");
            var content = notification.Request.Content;
            var userInfo = notification.Request.Content.UserInfo;
            if (typeof(UserNotifications.UNPushNotificationTrigger) == notification.Request.Trigger.GetType())
            {//遠程通知
                System.Console.WriteLine(" 收到遠程通知,Title:{0} -SubTitle:{1}, -Body:{2}", content.Title, content.Subtitle, content.Body);
                this.AddNotificationToView(content);

                JPUSHService.HandleRemoteNotification(userInfo);
            }
            else
            {//本地通知

            }

            if (completionHandler != null)
            {
                completionHandler(2);//UNNotificationPresentationOptions: None = 0,Badge = 1,Sound = 2,Alert = 4,
            }
        }

        /// <summary>
        /// 後臺收到通知
        /// </summary>
        /// <param name="center"></param>
        /// <param name="response"></param>
        /// <param name="completionHandler"></param>
        public override void DidReceiveNotificationResponse(UNUserNotificationCenter center, UNNotificationResponse response, Action completionHandler)
        {
            Console.WriteLine("DidReceiveNotificationResponse:");
            var content = response.Notification.Request.Content;
            var userInfo = response.Notification.Request.Content.UserInfo;
            if (typeof(UserNotifications.UNPushNotificationTrigger) == response.Notification.Request.Trigger.GetType())
            {//遠程通知
                System.Console.WriteLine(" 收到遠程通知,Title:{0} -SubTitle:{1}, -Body:{2}", content.Title, content.Subtitle, content.Body);
                this.AddNotificationToView(content);
                JPUSHService.HandleRemoteNotification(userInfo);
            }
            else
            {//本地通知

            }

            if (completionHandler != null)
            {
                completionHandler();
            }
        }

        /// <summary>
        /// 通知添加到視圖
        /// </summary>
        /// <param name="content"></param>
        public void AddNotificationToView(UNNotificationContent content)
        {
            App1.ViewModel.PushsPageViewModel.Item item = new ViewModel.PushsPageViewModel.Item()
            {
                Id = content.CategoryIdentifier,
                Text = content.Title,
                Detail = content.Body,
            };
            App1.ViewModel.PushsPageViewModel.Instance.AddItem(item);
        }
    }
}
View Code

 

  JPushRegisterEntity.cs:

using Foundation;
using IOSNativeLibrary;
using System;
using System.Collections.Generic;
using System.Text;

namespace App1.iOS.Notification.JPush
{
    public class JPushRegisterEntity : JPUSHRegisterEntity
    {
        public override NSSet Categories
        {
            get
            {
                return base.Categories;
            }
            set
            {
                base.Categories = value;
            }
        }

        public override nint Types
        {
            get
            {
                return base.Types;
            }
            set
            {
                base.Types = value;
            }
        }
    }
}
View Code

  你發現這兩個類都是繼承自Native Library。

  

  如今轉到AppDelegate.cs中,咱們先建立個字段jPushRegister,用來實例化極光註冊和推送接收:

    

  FinishedLaunching方法裏咱們這麼寫:

    

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
        {
            global::Xamarin.Forms.Forms.Init();

            LoadApplication(new App(Model.BasePlatform.Instance));

    
            //註冊apns遠程推送
            if (options == null) options = new NSDictionary();
            jPushRegister = new JPushInterface();
            jPushRegister.Register(this, options);
            this.RegistLogin(options);

            return base.FinishedLaunching(app, options);
        }
View Code

  這裏咱們使用的是Xamarin.Forms框架,若是你的項目不是,那可能看起來會不太同樣。

 

  目前極光推送是經過APNS向iOS推送通知的,那麼咱們要想推送成功就得還須要註冊APNS獲取APNS的推送設備id。

  咱們在AppDelegate類下添加以下代碼實現註冊:

        /// <summary>
        /// 註冊apns遠程推送
        /// </summary>
        /// <param name="launchOptions"></param>
        protected void RegistLogin(NSDictionary launchOptions)
        {
            string systemVersion = UIDevice.CurrentDevice.SystemVersion.Split('.')[0];
            Console.WriteLine("System Version: " + UIDevice.CurrentDevice.SystemVersion);

            //iOS10以上的註冊方式
            if (float.Parse(systemVersion) >= 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(systemVersion) >= 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);
            }
            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();
        }
        
        /// <summary>
        /// 註冊成功得到token
        /// </summary>
        /// <param name="application"></param>
        /// <param name="deviceToken"></param>
        public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
        {
            JPUSHService.RegisterDeviceToken(deviceToken);

            // Get current device token
            var DeviceToken = deviceToken.Description;
            if (!string.IsNullOrWhiteSpace(DeviceToken))
            {
                DeviceToken = DeviceToken.Trim('<').Trim('>');
            }

            // Get previous device token
            var oldDeviceToken = NSUserDefaults.StandardUserDefaults.StringForKey("PushDeviceToken");

            // Has the token changed?
            if (string.IsNullOrEmpty(oldDeviceToken) || !oldDeviceToken.Equals(DeviceToken))
            {
                //TODO: Put your own logic here to notify your server that the device token has changed/been created!
            }

            // Save new device token 
            NSUserDefaults.StandardUserDefaults.SetString(DeviceToken, "PushDeviceToken");

            System.Console.WriteLine(DeviceToken);

        }

        /// <summary>
        /// 註冊token失敗
        /// </summary>
        /// <param name="application"></param>
        /// <param name="error"></param>
        public override void FailedToRegisterForRemoteNotifications(UIApplication application, NSError error)
        {
            new UIAlertView("註冊通知失敗", error.LocalizedDescription, null, "OK", null).Show();
        }

        public void GetRegistrationID(int resCode, NSString registrationID)
        {
            if (resCode == 0)
            {
                Console.WriteLine("RegistrationID Successed: {0}", registrationID);

                App1.ViewModel.UserCenterPageViewModel.Instance.RegistId = registrationID;
            }
            else
                Console.WriteLine("RegistrationID Failed. ResultCode:{0}", resCode);
        }
View Code

 

到了這裏你就能夠在手機上進行測試了。

 【備註(轉載請說明出處,"http://www.cnblogs.com/RedSky/p/6679443.html","若是本文對你有幫助,請給個贊")】

相關文章
相關標籤/搜索