证书已经准备完毕,不懂请看我的前一篇文章http://blog.youkuaiyun.com/zhenli312/article/details/16844615
接下来,我们在xcode中新建一个测试工程,注意设置工程的Bundle Identifier必须与上面建的APP ID 里的相同
在didFinishLaunchingWithOptions 中加入一下代码
//注册接收通知类型
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
(UIRemoteNotificationType)(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)pToken {
NSLog(@"regisger success:%@", pToken);
//注册成功,将deviceToken保存到应用服务器数据库中
NSString *tokeStr = [NSString stringWithFormat:@"%@",pToken];
if ([tokeStr length] == 0) {
return;
}
NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString:@"\<\>"];
tokeStr = [tokeStr stringByTrimmingCharactersInSet:set];
tokeStr = [tokeStr stringByReplacingOccurrencesOfString:@" " withString:@""];
NSLog(@"令牌:%@", tokeStr);
const char *s;
s=[tokeStr UTF8String];
GameRecord2::shared()->setdevice(s); //这里我把令牌传给一个类来处理,最后上传服务器
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
// 处理推送消息
UIAlertView *alert=[[UIAlertView alloc]initWithTitle:@"通知" message:[NSString stringWithFormat:@"\n%@",
[[userInfo objectForKey:@"aps"] objectForKey:@"alert"]] delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
[alert show];
[alert release];
NSLog(@"%@", userInfo);
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
NSLog(@"Regist fail%@",error);
}
到这里一切顺利的话我们就可以在真机运行了,注册成功我们会得到iphone 的deviceToken,
regisger success:<740f4707 bebcf74f 9b7c25d4 8e335894 5f6aa01d a5ddb387 462c7eaf 61bb78ad>
如果出现Code=3000 "未找到应用程序的“aps-environment”的权利字符串",说明你的证书错误,重新下个或者看看是否有push的服务。
下面来看我的服务器php代码
<?php
//@header("Content-Type: text/html; charset=gb2312");
// 这里是我们上面得到的deviceToken,直接复制过来(记得去掉空格)
$deviceToken = '484ccd7fe528cc7f1eda2482c161d219a62d14aa4785809d83569dac511c79be';
// Put your private key's passphrase here:
$passphrase = 'pushchat';
// Put your alert message here:
$message = 'weige';
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
// Open a connection to the APNS server
//这个为正是的发布地址
$fp = stream_socket_client('ssl://gateway.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx);
//这个是沙盒测试地址,发布到appstore后记得修改哦
//$fp = stream_socket_client(
//'ssl://gateway.sandbox.push.apple.com:2195', $err,
//$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
if (!$fp)
exit("Failed to connect: $err $errstr" . PHP_EOL);
echo 'Connected to APNS' . PHP_EOL;
// Create the payload body
$body['aps'] = array(
'alert' => $message,
'badge' => 1,
'sound' => 'default'
);
// Encode the payload as JSON
$payload = json_encode($body);
// Build the binary notification
$msg = chr(0).pack('n', 32).pack('H*', $deviceToken).pack('n', strlen($payload)).$payload;
echo $payload ."\n";
// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));
if (!$result)
echo 'Message not delivered' . PHP_EOL;
else
echo 'Message successfully delivered' . PHP_EOL;
// Close the connection to the server
fclose($fp);
?>
之前生成的ck.pem要与该php放在同目录下,上面的开发地址用来开发证书用的,作为测试。如果改为发布证书后需要改为发布地址。
deviceToken是设备口令,message是向用户发送的信息,这些都可以配置,我在这里写死了为了测试。
另外,当你的iPhone收到推送信息后到底会发生什么呢?总共有三种可能性:
- app在前台运行. 接收到推送信息时屏幕上不会有任何显示,也不会有提示音,但你的app delegate会收到这个推送信息。你可以在这里加入代码来处理接收到的信息。
- app不在前台运行。iPhone可能停留在主界面或者另一个app正在运行.一个提示窗口会弹出,可能伴随着提示音。用户可以点击Close按钮来关闭这个窗口或者点击View按钮来打开你的app。如果用户点击的时Close按钮,那你的app不会处理这个推送的信息。
- iPhone在锁屏状态下. 同样一个提示窗口弹出,并伴随着提示音,但是这个窗口不会有Close和View按钮。屏幕解锁后会自动进入你的app。
因为app delegate是接收推送信息的地方,我们对app的最后改动都是在AppDelegate.m文件中。我们需要修改两处:
- application:didFinishLaunchingWithOptions:函数. 如果推送信息到达时你的app不在前台运行,而用户在弹出窗口点击了“View”按钮,你的app会重新运行然后这个信息会作为参数注入到application:didFinishLaunchingWithOptions:函数中。
- application:didReceiveRemoteNotification:函数. 如果信息到达时你的app正在前台运行,那这个函数就会被调用。在iOS4.0或更新的版本,如果你的app从暂停状态进入前台,这个函数也会被调用。你可以用UIApplication的applicationState属性来检查你的app是否是从暂停状态苏醒。
我上面一开始就写了didReceiveRemoteNotification方法里的响应,现在开始对1处理,
在didFinishLaunchingWithOptions加入:
if (launchOptions !=nil) {
NSDictionary* dictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (dictionary !=nil) {
[self addMessageFormRemoteNotification:dictionary updateUI:NO];
}
}
同时写上
- (void)addMessageFormRemoteNotification:(NSDictionary*)userInfo updateUI:(BOOL)updateUI
{
// 处理推送消息
UIAlertView *alert=[[UIAlertView alloc]initWithTitle:@"通知" message:[NSString stringWithFormat:@"\n%@",
[[userInfo objectForKey:@"aps"] objectForKey:@"alert"]] delegate:self cancelButtonTitle:@"取消" otherButtonTitles:nil, nil];
[alert show];
[alert release];
NSLog(@"%@", userInfo);
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
}
处理信息中的[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0]是为了让信息变为0
ok,这样就可以完美实现了!
2013-12-10-----------
消除通知,发现setApplicationIconBadgeNumber为0,没有效果
我就加上UIApplication sharedApplication] cancelAllLocalNotifications 就OK了