前言
執行下列monkey step 前, 請先閱讀 Phonegap/Cordova 的 installation guide 建立一個 Project 出來
我用到的 Phonegap Plugin 是 PushNotification, 及加上 EasyAPNS
1. 先產生 CSR.
2. 在 iOS Provisioning Portal 中 new 一個 APP IDs, 然後 configure, Enable for Development, Enable for Production
3. 下載 aps_development.cer, aps_production.cer, double click 這兩個file 匯進key acess
4. 建立一個 新的 Provisioning profile 選擇剛剛新建的 App IDs.
5. 下載此Provisioning profile.
6. 打開 Xcode, 選擇organizer 把 Provisioning profile 的檔案 拉進去
7. 選擇 Project, 將Build Settings 裡面的Code Signing identity 選擇成 你所建立的 App ID
8. 在Classes 按右鍵選 Add Files to “xxx”, 將這兩個檔案加上去 PushNotification.m, PushNotification.h 這兩個檔案 ( PushNotification 是 Phonegap 的Plugin )
9. 放 PushNotification.js, jquery 及 jquery mobile 的相關檔案 放到 www folder
10. 開啟 Cordova.plist
- 在 ExternalHosts 加上 一筆 * 的 record , key 用default 的即可。
- 在 Plugins 加上一筆 key -> PushNotification, value -> PushNotification
11. 打開 AppDelegate.h 加上
#import <AudioToolbox/AudioToolbox.h> #import "PushNotification.h"
12. 打開 AppDelegate.m
- 在 didFinishLaunchingWithOptions 這個 method 裡上方加上
// Add registration for remote notifications [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)]; // Clear application badge when app launches application.applicationIconBadgeNumber = 0;
- 在 didFinishLaunchingWithOptions 這個 method 裡頭的 [self.window makeKeyAndVisible]; 和 return YES; 中間插
[self.window makeKeyAndVisible]; /* START BLOCK */ // PushNotification - Handle launch from a push notification NSDictionary* userInfo = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]; if(userInfo) { PushNotification *pushHandler = [self.viewController getCommandInstance:@"PushNotification"]; NSMutableDictionary* mutableUserInfo = [userInfo mutableCopy]; [mutableUserInfo setValue:@"1" forKey:@"applicationLaunchNotification"]; [mutableUserInfo setValue:@"0" forKey:@"applicationStateActive"]; [pushHandler.pendingNotifications addObject:mutableUserInfo]; } /* STOP BLOCK */ return YES;
- 在
dealloc
method and the implementation@end
. 中間插入- (void) dealloc { [super dealloc]; } /* START BLOCK */ /** * Fetch and Format Device Token and Register Important Information to Remote Server */ - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)devToken { #if !TARGET_IPHONE_SIMULATOR /* EasyAPNS Start Block */ // Get Bundle Info for Remote Registration (handy if you have more than one app) NSString *appName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDisplayName"]; NSString *appVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]; // Check what Notifications the user has turned on. We registered for all three, but they may have manually disabled some or all of them. NSUInteger rntypes = [[UIApplication sharedApplication] enabledRemoteNotificationTypes]; // Set the defaults to disabled unless we find otherwise... NSString *pushBadge = @"disabled"; NSString *pushAlert = @"disabled"; NSString *pushSound = @"disabled"; // Check what Registered Types are turned on. This is a bit tricky since if two are enabled, and one is off, it will return a number 2... not telling you which // one is actually disabled. So we are literally checking to see if rnTypes matches what is turned on, instead of by number. The "tricky" part is that the // single notification types will only match if they are the ONLY one enabled. Likewise, when we are checking for a pair of notifications, it will only be // true if those two notifications are on. This is why the code is written this way if(rntypes == UIRemoteNotificationTypeBadge){ pushBadge = @"enabled"; } else if(rntypes == UIRemoteNotificationTypeAlert){ pushAlert = @"enabled"; } else if(rntypes == UIRemoteNotificationTypeSound){ pushSound = @"enabled"; } else if(rntypes == ( UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert)){ pushBadge = @"enabled"; pushAlert = @"enabled"; } else if(rntypes == ( UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)){ pushBadge = @"enabled"; pushSound = @"enabled"; } else if(rntypes == ( UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound)){ pushAlert = @"enabled"; pushSound = @"enabled"; } else if(rntypes == ( UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound)){ pushBadge = @"enabled"; pushAlert = @"enabled"; pushSound = @"enabled"; } // Get the users Device Model, Display Name, Unique ID, Token & Version Number UIDevice *dev = [UIDevice currentDevice]; NSString *deviceUuid = dev.uniqueIdentifier; NSString *deviceName = dev.name; NSString *deviceModel = dev.model; NSString *deviceSystemVersion = dev.systemVersion; // Prepare the Device Token for Registration (remove spaces and < >) NSString *deviceToken = [[[[devToken description] stringByReplacingOccurrencesOfString:@"<"withString:@""] stringByReplacingOccurrencesOfString:@">" withString:@""] stringByReplacingOccurrencesOfString: @" " withString: @""]; // Build URL String for Registration // !!! CHANGE "www.mywebsite.com" TO YOUR WEBSITE. Leave out the http:// // !!! SAMPLE: "secure.awesomeapp.com" NSString *host = @"www.example.com/apns"; // !!! CHANGE "/apns.php?" TO THE PATH TO WHERE apns.php IS INSTALLED // !!! ( MUST START WITH / AND END WITH ? ). // !!! SAMPLE: "/path/to/apns.php?" NSString *urlString = [@"/apns.php?"stringByAppendingString:@"task=register"]; urlString = [urlString stringByAppendingString:@"&appname="]; urlString = [urlString stringByAppendingString:appName]; urlString = [urlString stringByAppendingString:@"&appversion="]; urlString = [urlString stringByAppendingString:appVersion]; urlString = [urlString stringByAppendingString:@"&deviceuid="]; urlString = [urlString stringByAppendingString:deviceUuid]; urlString = [urlString stringByAppendingString:@"&devicetoken="]; urlString = [urlString stringByAppendingString:deviceToken]; urlString = [urlString stringByAppendingString:@"&devicename="]; urlString = [urlString stringByAppendingString:deviceName]; urlString = [urlString stringByAppendingString:@"&devicemodel="]; urlString = [urlString stringByAppendingString:deviceModel]; urlString = [urlString stringByAppendingString:@"&deviceversion="]; urlString = [urlString stringByAppendingString:deviceSystemVersion]; urlString = [urlString stringByAppendingString:@"&pushbadge="]; urlString = [urlString stringByAppendingString:pushBadge]; urlString = [urlString stringByAppendingString:@"&pushalert="]; urlString = [urlString stringByAppendingString:pushAlert]; urlString = [urlString stringByAppendingString:@"&pushsound="]; urlString = [urlString stringByAppendingString:pushSound]; // Register the Device Data // !!! CHANGE "http" TO "https" IF YOU ARE USING HTTPS PROTOCOL NSURL *url = [[NSURL alloc] initWithScheme:@"http" host:host path:urlString]; NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url]; NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; NSLog(@"Register URL: %@", url); NSLog(@"Return Data: %@", returnData); /* EasyAPNS End Block */ /* PushNotification Start Block */ PushNotification* pushHandler = [self.viewController getCommandInstance:@"PushNotification"]; [pushHandler didRegisterForRemoteNotificationsWithDeviceToken:devToken]; /* PushNotification End Block */ #endif } - (void)application:(UIApplication*)app didFailToRegisterForRemoteNotificationsWithError:(NSError*)error { PushNotification* pushHandler = [self.viewController getCommandInstance:@"PushNotification"]; [pushHandler didFailToRegisterForRemoteNotificationsWithError:error]; } - (void)application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary*)userInfo { PushNotification* pushHandler = [self.viewController getCommandInstance:@"PushNotification"]; NSMutableDictionary* mutableUserInfo = [userInfo mutableCopy]; // Get application state for iOS4.x+ devices, otherwise assume active UIApplicationState appState = UIApplicationStateActive; if ([application respondsToSelector:@selector(applicationState)]) { appState = application.applicationState; } [mutableUserInfo setValue:@"0" forKey:@"applicationLaunchNotification"]; if (appState == UIApplicationStateActive) { [mutableUserInfo setValue:@"1" forKey:@"applicationStateActive"]; [pushHandler didReceiveRemoteNotification:mutableUserInfo]; } else { [mutableUserInfo setValue:@"0" forKey:@"applicationStateActive"]; [mutableUserInfo setValue:[NSNumber numberWithDouble: [[NSDate date] timeIntervalSince1970]] forKey:@"timestamp"]; [pushHandler.pendingNotifications addObject:mutableUserInfo]; } } /* STOP BLOCK */ @end
13. Build 在你的 device 上吧, 在emulator 沒辦法測 notification.
14. EasyAPNS Server Side 的部份, 我就沒寫了, 請參考下方 1j2 的連結即可
PS:
1.
這只是我個人的筆記, 寫的有點雜亂 XD
所以請搭配下列 ref 一併服用
未來還會再整理一遍, 目前只是先備忘
2.
產生 .pem
openssl pkcs12 -in Dev_Certificates.p12 -out apns-dev-cert.pem -nodes -clcerts
ref:
http://1j2.com/tutorial-implementing-push-notifications-with-easy-apns/
https://github.com/phonegap/phonegap-plugins/tree/master/iOS/PushNotification
http://www.easyapns.com/apple-delegate