鉴于服务器稳定的开发难度很大,小团队不建议自己开发,建议使用稳定的第三方推送方案,如个推,蝴蝶等。
要想使用苹果APNS推送消息,首先要把开发app的xcode所用证书上传到服务器上,当然你的证书要用的是hot证书或勾选push选项的发布者,普通研发者证书是收不到push消息的。
客户端设置
开启Remote notifications
需要在Xcode 中修改应用的 Capabilities 开启Remote notifications,请参考下图:
安装证书到服务端
你应该安装SSL证书和私匙到你的provider程序运行的服务器上。
步骤如下:
0.安装该证书到mac电脑的钥匙串。
1.打开钥匙串,在左侧面板上点击我的证书栏。
2.找到这个SSL证书,展开会看到证书和私匙。
3.我们选中证书和私匙,然后导出为”个人信息交换文件”–即扩展名为p12的文件。
4.provider服务器程序最好用Ruby和Perl这类语言,可以方便的处理”个人信息交换文件”里的证书。mac下打开终端输入以下命令以把证书转换为这类语言乐于交流的格式:
openssl pkcs12 -in CertificateName.p12 -out CertificateName.pem -nodes
5.把这pem文件拷到服务器上并安装到某个适当的位置。
说完服务端了就具体说客户端吧,首先在AppDelegate.m(AppDelegate.mm)文件中的- (BOOL)application:(UIApplication )application didFinishLaunchingWithOptions:(NSDictionary )launchOptions加入[AppDelegate registerForRemoteNotification];来重新获取设备相关的token,不要缓存token.
当注销时,本账户在别的设备上登陆时(被踢掉)或者捕获到被拉掉事件时(- (void)applicationWillTerminate:(UIApplication *)application)需要取消推送的注册,代码如[[UIApplication sharedApplication] unregisterForRemoteNotifications];//用户退出登录后,取消推送的注册,登录时register,当然退出到登陆页面后登陆成功后还时需要重新进行推送的注册。
在didReceiveRemoteNotification可以处理收到的消息,可以只记录到全局变量里暂时不操作,也可以播放铃声,震动,弹出对话框,跳转页面等。像这个版本更新的push消息处理就没有告知用户 if([type isEqualToString:@”psy_needUpgrade”])
{
NSString *url = [page objectForKey:@”downloadUrl”];
if(url != nil)
{
g_needUpgrade = 1;
g_downloadUrl = url;
}
return;
}
下面这段代码是对接收的push消息进行处理。
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
FLDDLogDebug(@"push userinfo:%@", userInfo);
NSDictionary *aps = [userInfo objectForKey:@"aps"];
NSInteger count = [[aps objectForKey:@"badge"] toInt];
[application setApplicationIconBadgeNumber:count];
NSString *alert = [aps objectForKey:@"alert"];
NSDictionary *page = [userInfo objectForKey:@"page"];
NSString *actionId = [page objectForKey:@"id"];
NSString *type = [page objectForKey:@"type"];
NSString *title = [page objectForKey:@"title"];
NSString *notifyType = [[page objectForKey:@"notifyType"] toString];
NSString *subType = [[page objectForKey:@"subType"] toString];
NSString *subId = [[page objectForKey:@"subId"] toString];//app消息对应的订单id
NSString *phone = [page objectForKey:@"userTel"];
NSString *userPhone = [User currentUser].phone;
if (![phone isEqualToString:userPhone]) {
return;
}
if([type isEqualToString:@"psy_needUpgrade"])
{
NSString *url = [page objectForKey:@"downloadUrl"];
if(url != nil)
{
g_needUpgrade = 1;
g_downloadUrl = url;
}
return;
}
if ([notifyType isEqualToString:@"1"]) {
type = kFhlappnotify;
}
else if ([notifyType isEqualToString:@"2"]){
type = kFhlordernotify;
}
if ([type isEqualToString:kFhlGrab]) { //set home refresh tag [[NSNotificationCenter defaultCenter] postNotificationName:REFRESH_HOME_NOTIFICATION object:nil]; }
if (application.applicationState == UIApplicationStateActive) {
[application setApplicationIconBadgeNumber:0];
if ([AppManager boolValueForKey:@"shock"]) {
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
}
else {
[self playAudioWithIndex:type];
}
if ([type isEqualToString:kFhllogout]) { g_loginStat = LOGIN_STATE_EXIT_LOGIN; // [AppManager saveCurrentOrderRemind]; [[UIApplication sharedApplication] unregisterForRemoteNotifications]; [[User currentUser] removeUserInfo]; [AppManager setUserDefaultsValue:@"" key:@"telephone"]; [AppManager setUserDefaultsValue:@"" key:@"password"]; UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:alert delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil, nil]; alertView.tag = 1005; [alertView show]; }
else if ([type isEqualToString:kFhlGrab]) { //set home refresh tag // [AppManager setUserBoolValue:YES key:@"NeedRefreshHome"]; }
else if ([type isEqualToString:kFhlSend] || [type isEqualToString:kFhlReceived]) { // Order *order = [[Order alloc] init]; // order.id = actionId; // [[NSNotificationCenter defaultCenter] postNotificationName:REFRESH_ORDER_NOTIFICATION object:nil userInfo:@{@"Order" : order, @"Option" : @(3)}];
}
else if ([type isEqualToString:kFhlBeAppoint]) { Order *order = [[Order alloc] init]; order.id = subId; [[NSNotificationCenter defaultCenter] postNotificationName:REFRESH_ORDER_NOTIFICATION object:nil userInfo:@{@"Order" : order, @"Option" : @(3)}];
}
else {
if ([subType isEqualToString:kFhlSubClosed] || [subType isEqualToString:kFhlSubRejected]) {
Order *order = [[Order alloc] init];
order.id = subId;
if ([subType isEqualToString:kFhlSubRejected]) {
order.state = @"50";
}
[[NSNotificationCenter defaultCenter] postNotificationName:REFRESH_ORDER_NOTIFICATION object:nil userInfo:@{@"Order" : order, @"Option" : @(3)}];
}
if ([type isEqualToString:kFhlcancel]) { Order *order = [[Order alloc] init]; order.id = actionId; [[NSNotificationCenter defaultCenter] postNotificationName:REFRESH_ORDER_NOTIFICATION object:nil userInfo:@{@"Order" : order, @"Option" : @(4)}];
}
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:title
message:alert
delegate:self
cancelButtonTitle:@"忽略"
otherButtonTitles:@"进入", nil];
if (type.length > 0 && actionId.length > 0) { objc_setAssociatedObject(alertView, &AlertAssociatedKey,@{@"type" : type, @"actionId" : actionId}, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
[alertView show];
}
}
else if (application.applicationState == UIApplicationStateInactive){
[self pushViewControllerWithType:type actionId:actionId];
}
}
下面这断代码就是具体的推送的注册:
“`
+ (void)registerForRemoteNotification {
FLDDLogDebug(@"*\n*\n*\nregisterForRemoteNotification\n*\n*\n*\n");
if (IOS8_OR_LATER) {
UIUserNotificationType types = UIUserNotificationTypeSound | UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIRemoteNotificationTypeNewsstandContentAvailability;
UIUserNotificationSettings *notificationSettings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];
} else {
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeNewsstandContentAvailability)];
}
}