制作推送的证书
1、新建一个工程BackgroundDownload
2、钥匙串访问->证书助理->从证书颁发机构请求证书,将CertificateSigningRequest.certSigningRequest文件存到磁盘上。
3、登陆开发者中心,新建一个AppID,设置好名字等,然后勾选Push Notifications,点continue,点submit
4、在App IDs下找到我们刚刚新建得appid,然后选择,点edit,点Create certificate...,点continue,点choosefile..选择CertificateSigningRequest.certSigningRequest,点submit,现在证书做好了,我们点击Download,下载后点击安装。
现在我们要制作的是获取设备deviceToken的证书
1、在开发者中心点击Provisioning Profiles,下边的Development,然后新建一个provisioning profile,点击ios App Development,然后continue,接着我们选择我刚刚新建的appid,点continue,然后勾选证书,然后勾选设备,然后起名字,点Generate。下载安装到我们的手机。
制作pem文件,用来推送。
进入到钥匙串,点击登陆,我的证书,找到我们刚才从appid下载下来的证书,然后右键导出,最好不要输入密码,起名为cert.p12。
如果你的cert.p12在桌面,那么cd Desktop,执行下面命令:
openssl pkcs12 -in cert.p12 -out apple_push_notification.pem -nodes -clcerts
这样在桌面上生成了一个pem文件。
然后我们下载一个gem包,houston。
下面编写我们的工程
在AppDelegate.m文件中
- (void)applicationDidFinishLaunching:(UIApplication *)application { // ... [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)]; }
上面的代码指明推送的类型。
获得我们设备的DeviceToken,把deviceToken转换为NSString,打印出来然后copy下来。
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { }
进行后台下载配置
//初始化一个NSURLSession - (NSURLSession*)backgroundURLSession { static NSURLSession *session = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken,^{ NSString *identifier = @"identifier"; NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration backgroundSessionConfiguration:identifier]; session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:[NSOperationQueue mainQueue]]; }); return session; } //实现NSURLSessionDelegate - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes { } - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite { } - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location { NSData *data = [NSData dataWithContentsOfURL:location]; UIImage *image = [UIImage imageWithData:data]; UIImageView *imageView = [[UIImageView alloc]initWithImage:image]; [self.viewController.view addSubview:imageView]; } //应用接到通知的时候触发此函数,需要注意的是这里的推送是有要求的必须符合如下格式 { "aps" : { "content-available" : 1 //必须有这项 }, } - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { NSURL *url = [[NSURL alloc] initWithString:@"http://simg.cocoachina.com/201111220746561330.jpg"]; NSURLRequest *request = [[NSURLRequest alloc]initWithURL:url]; NSURLSessionDownloadTask *task = [[self backgroundURLSession] downloadTaskWithRequest:request]; [task resume]; NSLog(@"接到了推送"); completionHandler(UIBackgroundFetchResultNewData); } //在NSURLSessionDelegate触发前会触发先在applicationDelegate - (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler { //实际上我们暂存了一个完成处理程序,等下载完成后执行这个block,生成快照,这个block存在一个字典中 [self addCompletionHandler:completionHandler :identifier]; } - (void)addCompletionHandler :(void (^)())handler :(NSString*)identifier { if([self.completionHandlerDictionary objectForKey:identifier]) { NSLog(@"error"); return; } [self.completionHandlerDictionary setObject:handler forKey:identifier]; } //实现NSURLSessionDelegate的一个methond - (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session { NSLog(@"Background URL session %@ finished events.\n", session); //生成快照 [self callCompletionHandlerForSession:session.configuration.identifier]; } - (void)callCompletionHandlerForSession :(NSString*)identifier { CompletionHandlerType handler = [self.completionHandlerDictionary objectForKey:identifier]; if(handler) { [self.completionHandlerDictionary removeObjectForKey:identifier]; } handler(); }
注意
需要将Capabilities下的Background Modes打开,勾选Background fetch,和Remote notifications。
在命令行进行推送
apn push "<13f01d3e0dbfc75b1c273f6db6af867d36004694597df496cdc562f87e2...>" -c /Users/用户名/Desktop/apple_push_no_download.pem -n -m "hello world"
当应用接到这个通知的时候,会进行后台下载那张图片,这种类型的通知根据苹果的官方文档来说每天最好发送10条以下。
houston是个gem包,所以机器应改配置ruby和rails
demo:https://github.com/aiyuelian/ios7BackgroundDownload