1. 程式人生 > >使用PushSharp給iOS應用推送訊息

使用PushSharp給iOS應用推送訊息

PushSharp是一個C#編寫的服務端類庫,用於推送訊息到各種客戶端,支援iOS(iPhone/iPad)、Android、Windows Phone、Windows 8、Amazo、Blackberry等裝置。

主要特點

提供了易於使用的API,支援以下平臺的訊息推送:

100%的託管程式碼完全相容Mono平臺。

安裝

PushSharp主要包含以下程式集:

  • PushSharp.Core:(必選)核心元件
  • PushSharp.Apple:APNS,用於iOS及OSX
  • PushSharp.Android:C2DM及GCM,用於Android裝置
  • PushSharp.Windows:用於Windows 8
  • PushSharp.WindowsPhone:用於WP裝置
  • PushSharp.Amazon.Adm:用於Amazon的裝置
  • PushSharp.Blackberry:用於黑莓裝置
  • PushSharp.Google.Chrome:用於Chrome

其中,PushSharp.Core為必須的元件,其他的可以根據自己需要來選擇對應平臺。

平常使用只需要用NuGet來獲取程式集即可:

Install-Package PushSharp

這樣會把主流平臺的程式集(Apple/Android/Windows/WindowsPhone)都下載下來,可以根據自己需要刪除用不到的平臺元件。

對於Apple平臺,只需要PushSharp.Core和PushSharp.Apple元件即可。

證書配置

官方WIKI提供了詳細的證書配置步驟:

Apple平臺證書建立流程:

  • 建立AppID
  • 為AppID配置用於APP簽名的證書:分別有開發環境(Development)和生產環境(Production)的證書
  • 編輯AppID啟用訊息推送
  • 為AppID建立用於訊息推送(APNS)的證書(包括Development和Production)
  • 下載以上證書並安裝到Key Chain(鑰匙串)
  • 匯出用於訊息推送(APNS)的證書為.p12格式,併為它設定密碼:用於在服務端推送訊息

對於Apple平臺需要特別說明:

  • 對於已經發布的APP要啟用訊息推送功能,需要在Identifiers – App IDs找到對應的ID建立好APNS證書之後,再重新生成用於APP簽名的證書,否則用於註冊訊息推送的程式碼(RegisterForRemoteNotificationTypes)不會正常工作,即返回的deviceToken為null
  • 在使用Development證書除錯應用程式時服務端需要使用Development APNS證書來推送訊息,使用Production證書釋出到AppStore後推送訊息需要使用Production APNS證書來推送訊息

客戶端啟用訊息推送

啟用訊息推送都是在AppDelegate裡註冊來完成的。

對於使用objc語言編寫的客戶端:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    if (application.enabledRemoteNotificationTypes == UIRemoteNotificationTypeNone)
    {
        [application registerForRemoteNotificationTypes:
         UIRemoteNotificationTypeAlert |
         UIRemoteNotificationTypeBadge |
         UIRemoteNotificationTypeSound];
    }
    application.applicationIconBadgeNumber = -1;
    // Override point for customization after application launch.
    return YES;
}

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    NSString *pushToken = [[[[deviceToken description]
                             stringByReplacingOccurrencesOfString:@"<"withString:@""]
                            stringByReplacingOccurrencesOfString:@">" withString:@""]
                           stringByReplacingOccurrencesOfString: @" " withString: @""];
    [[NSUserDefaults standardUserDefaults] setObject:pushToken forKey:@"pushtoken"]; // 儲存起來
}

對於使用MonoTouch的客戶端:

        public override bool FinishedLaunching(UIApplication app, NSDictionary options)
        {
            app.RegisterForRemoteNotificationTypes(
                UIRemoteNotificationType.Alert |
                UIRemoteNotificationType.Badge |
                UIRemoteNotificationType.Sound);
            app.ApplicationIconBadgeNumber = -1;
            // ...
            return true;
        }
        
        public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
        {
            // 成功接收到用於訊息推送的token
            string tokenStr = token.Description;
            string pushToken = tokenStr.Replace("<", string.Empty).Replace(">", string.Empty).Replace(" ", string.Empty);
            NSUserDefaults.StandardUserDefaults.SetString(pushToken, "pushtoken");
        }
        
        public override void FailedToRegisterForRemoteNotifications(UIApplication application, NSError error)
        {
            // 訊息推送註冊失敗
        }

        public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler)
        {
            // 接收到推送的訊息
            // 在iOS7可能需要開啟Background Modes的Remote Notifications
        }

在接收到deviceToken的時候先儲存在NSUserDefaults中,在使用者登入的時候再取出來一起傳送到服務端:

NSString *pushToken = [[NSUserDefaults standardUserDefaults] stringForKey:@"pushtoken"]; //objc
string pushToken = NSUserDefaults.StandardUserDefaults.StringForKey("pushtoken"); //MonoTouch

服務端在使用者登入成功之後,把接收到使用者的使用者名稱與pushToken關聯起來,在推送訊息的時候就可以針對指定使用者來推送,具體的過程略。

而對於不需要使用者登入的app,可以在接收到deviceToken的時候直接傳送到服務端。

更多的客戶端配置參考PushSharp原始碼的Client.SamplesPushSharp.Client目錄。

服務端推送訊息

var pusher = new PushBroker();
pusher.RegisterAppleService(new ApplePushChannelSettings(File.ReadAllBytes("yourAppId.p12"), "證書的密碼"));
pusher.QueueNotification(
                new AppleNotification()
                    .ForDeviceToken(pushToken) // 從資料庫等地方獲取裝置的pushToken
                    .WithAlert("測試iOS訊息推送 - 囧月")
                    .WithBadge(1)
                    .WithSound("default")
            );

在RegisterAppleService方法中可以註冊多個APNS證書,PushSharp可以自動檢測是Development/Production,這時候需要為證書設定標識:

pusher.RegisterAppleService(new ApplePushChannelSettings(File.ReadAllBytes("yourAppId.p12"), "證書的密碼"), "證書標識如youAppId_development");
pusher.RegisterAppleService(new ApplePushChannelSettings(File.ReadAllBytes("yourAppId.p12"), "證書的密碼"), "證書標識如youAppId_production");

此外,可以註冊各種事件來獲得各種狀態:

pusher.OnDeviceSubscriptionChanged += pusher_OnDeviceSubscriptionChanged;
pusher.OnDeviceSubscriptionExpired += pusher_OnDeviceSubscriptionExpired;
pusher.OnNotificationSent += pusher_OnNotificationSent;
pusher.OnNotificationFailed += pusher_OnNotificationFailed;
pusher.OnNotificationRequeue += pusher_OnNotificationRequeue;
pusher.OnChannelCreated += pusher_OnChannelCreated;
pusher.OnChannelDestroyed += pusher_OnChannelDestroyed;
pusher.OnChannelException += pusher_OnChannelException;
pusher.OnServiceException += pusher_OnServiceException;

static void pusher_OnNotificationFailed(object sender, INotification notification, Exception error)
{
    var n = (AppleNotification)notification;
    //error.Message ...獲取推送出錯的資訊
}

static void pusher_OnNotificationSent(object sender, INotification notification)
{
    //訊息推送成功後
    var n = (AppleNotification)notification;
    //n.Payload.Alert.Body  獲取推送的訊息內容...
}

static void pusher_OnDeviceSubscriptionExpired(object sender, string expiredSubscriptionId, DateTime expirationDateUtc, INotification notification)
{
    // 從資料庫刪除過期的expiredSubscriptionId
}

static void pusher_OnDeviceSubscriptionChanged(object sender, string oldSubscriptionId, string newSubscriptionId, INotification notification)
{
    // 把資料庫中的oldSubscriptionId更新為newSubscriptionId
}

更多請參考原始碼的PushSharp.Sample目錄。

參考