APNs消息推送

什么是APNs消息推送

由APNs服务器、ProviderService、iOS系统、App构成的通讯系统,是移动互联网与传统的Web最明显的区别的地方。正因为有了推送,实现了服务端能够反向与用户建立联系,而不是等待用户访问Web服务器。

APNs: Apple Push Notification Service的缩写,是苹果的服务器。

推送流程

分为两阶段:
阶段一
1.app向APNs注册该device。
2. APNs返回device token给app。
3. app将device token 传给app服务端,由服务端保存。

Created with Raphaël 2.1.0 app app APNs APNs app service app service 1.注册 2.device token 3.device token

阶段二
1.device和APNs建立长连接。
2.app服务端将device token + 消息打包发给APNs。
3.APNs将消息发送给divice。

Created with Raphaël 2.1.0 app app APNs APNs app service app service 1.长连接 2.device token + 消息 3.消息

客户端

注册‘通知设置’,以允许你的应用在设备上开启通知

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge categories:nil];
    [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
    return YES;
}

收到‘通知设置’的回调,给你的设备‘注册远程通知’

- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
    if (notificationSettings.types != UIUserNotificationTypeNone) {
        [application registerForRemoteNotifications];
    } else {

    }
}

收到‘注册远程通知’的回调,成功就将device token发到app服务端

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    [self sendToProviderWithDiviceToken:deviceToken];
}

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
    NSLog(@"#error in registration:%@", error);
}

发送device token 的代码如下,这边将设备的其他信息一起发送

- (void)sendToProviderWithDiviceToken:(NSData*)deviceToken {
    NSString *appName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDisplayName"];
    NSString *appVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
    UIDevice *dev = [UIDevice currentDevice];
    NSString *deviceName = dev.name;
    NSString *deviceModel = dev.model;
    NSString *deviceSystemVersion = dev.systemVersion;
    NSString *pushBadge = @"enabled";
    NSString *pushAlert = @"enabled";
    NSString *pushSound = @"enabled";

    NSString *resultToken = [[[[deviceToken description]
                               stringByReplacingOccurrencesOfString:@"<"withString:@""]
                              stringByReplacingOccurrencesOfString:@">" withString:@""]
                             stringByReplacingOccurrencesOfString: @" " withString: @""];

    NSString *host = @"deeepthinking.com";
    NSString *path = [NSString stringWithFormat:@"/push/apns.php?task=%@&appname=%@&appversion=%@&devicetoken=%@&devicename=%@&devicemodel=%@&deviceversion=%@&pushbadge=%@&pushalert=%@&pushsound=%@", @"register", appName, appVersion, resultToken, deviceName, deviceModel, deviceSystemVersion, pushBadge, pushAlert, pushSound];
    NSURL *url = [[NSURL alloc] initWithScheme:@"http" host:host path:[path  stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
    NSLog(@"#request:%@", url);
    NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
    [NSURLConnection sendAsynchronousRequest:request
                                       queue:[NSOperationQueue mainQueue]
                           completionHandler:^(NSURLResponse *urlR, NSData *returnData, NSError *e) {
                               NSLog(@"#response:%@", [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding]);
                           }];

}

第二阶段app服务器发送信息到APNs,然后你的设备就会收到一条推送,点开推送,会回调以下方法

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo {
    NSDictionary *apsInfo = [userInfo objectForKey:@"aps"];

    NSString *alert = [apsInfo objectForKey:@"alert"];
    NSLog(@"Received Push Alert: %@", alert);

    NSString *sound = [apsInfo objectForKey:@"sound"];
    NSLog(@"Received Push Sound: %@", sound);

    NSString *badge = [apsInfo objectForKey:@"badge"];
    NSLog(@"Received Push Badge: %@", badge);
    application.applicationIconBadgeNumber = [[apsInfo objectForKey:@"badge"] integerValue];
}

通知

iOS操作系统的通知包括了App的通知、系统的通知和官方应用的通知,实质上就是推送的数据在iOS操作系统上的表现和本地通知在iOS操作系统的表现,在交互上iOS10的通知大大增强,可定制化UI,增加了更加细分的通知权限管理和更多的通知设定,例如远程通知、时间通知、地理位置通知和日历通知。
很多开发者都知道iOS10中苹果升级推出了 User Notifications FrameworkUser Notifications UI Framework两个框架,但是千万不要跟推送混为一谈,这两个框架升级和打包的是通知的功能增加和通知交互层面上的改进。

推送Push只不过是iOS10通知的一种触发器。

服务端

服务端接收到device token 后就保存到数据库,等有需要的时候就拿出来和推送信息发送到APNs。

可以参考下面的开源代码:
easyapns
ApnsPHP

发送信息到APNs的代码大致如下:

<?php  
// 这里是我们上面得到的deviceToken
$deviceToken=$_POST['deviceToken'];  

// Put your private key's passphrase here:  
$passphrase = 'password';  

// Put your alert message here:  
$message = $_POST['message'];  

$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,  
'forum_id' => 88,  
'topic_id' => 999,  
);  

// Encode the payload as JSON  
$payload = json_encode($body);  

// Build the binary notification   
$msg = chr(0) . pack("n",32) . pack('H*', str_replace(' ', '', $deviceToken)) . pack("n",strlen($payload)) . $payload;  

// 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);  

?>  

证书

服务端和APNs要顺利通讯,还需要配置证书(上面代码中的ck.pem,passphrase是证书的密码),证书生成过程如下:
1.在你的开发者账号上生成你app的推送证书aps_development .cer(开发用开发证书,发布用发布证书)
2.安装推送证书到mac的钥匙串管理器,导出证书的秘钥文件(下拉列表中钥匙形状的那个)为push_key.p12
3.将aps_development .cer转成.pem文件,执行命令:

openssl x509 -in aps_development.cer -inform der -out push_cer.pem

4.将push_key.p12也转成.pem,执行命令:

openssl pkcs12 -nocerts -out push_key.pem -in push_key.p12

期间要输入密码,这个密码就是上面代码中要用的passphrase

5.将push_cer.pem和push_key.pem合成一个,即ck.pem

cat push_cer.pem push_key.pem > ck.pem

APNs地址

测试地址:gateway.sandbox.push.apple.com:2195
发布地址:gateway.push.apple.com:2195
测试的地址用的是沙盒,发布地址是不同的。发布软件的时候记得改过来

发送到APNs的信息格式

json包中除了alert,badge,sound之外,还是是可以自定值的。如:

{
  "aps" :
           { "alert" :
                      {
                        "action-loc-key" : "显示" ,
                        "body" : "This is the alert text"
                       },
             "badge" : 1,
             "sound" : "default" },
  "server" : { "serverId" : 1, "name" : "Server name"}
  }

以前只支持发送256字节,多了APNs不收,现在支持发送4k。

大批量发送

将所有deviceToken在mysql查询出来foreach存入Redis中(包括推送内容),然后编写一个php从Redis中取数据并发送的脚本(每次都建立苹果连接),php脚本每次开启运行5分钟、5分钟以后自动退出。然后编辑个shell脚本,循环执行php脚本20次(次数根据deviceToken多少进行增加),最后将shell脚本编辑到crontab中运行、至于运行时间设置为php脚本执行时间最好、这样就相当于不间断取数据推送。这样做的好处就是预防php超时。

feedback

APNS的feedback是一个非常贴心的服务,他会告诉你近期推送的消息,有哪些设备由于卸载了应用而无法在通知中显示消息。

那么,我们通过定期从feedback中获得这些devicetoken后,在数据库中进行标记,在下次的推送中,从消息队列中剔除这些devicetoken,这样减少了无用功,推送一次会完成的更快。

参考文档:

APNs Overview
一步一步教你做ios推送
苹果推送APNS自己总结
用php搭建apns推送服务器
php实现推送ios消息大数据量的实例
iOS10里的通知与推送
php从苹果apns的feedback服务器获取推送失败的token

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
APNS(Apple Push Notification Service)是苹果公司提供的一种服务,在移动应用开发中广泛应用。下面介绍如何使用C#实现APNS消息。 首先,需要获取APNS证书。具体步骤如下: 1. 登录苹果开发者中心,进入Certificates, Identifiers & Profiles页面。 2. 选择Identifiers选项卡,然后选择App IDs选项,找到你要的App ID。 3. 点击Edit按钮,然后勾选Push Notifications选项,保存。 4. 选择Certificates选项卡,点击左下角的“+”按钮,选择“Apple Push Notification service SSL (Sandbox & Production)”选项,按照提示生成证书。 5. 下载证书并安装到电脑中。 接下来,使用第三方库完成APNS消息。常用的库有apns-sharp、PushSharp等。这里以PushSharp为例。 1. 安装PushSharp库。可以通过NuGet安装,也可以从GitHub上下载源码编译。 2. 创建服务对象。代码如下: ``` ApnsConfiguration config = new ApnsConfiguration(ApnsConfiguration.ApnsServerEnvironment.Production, "your_certificate_path", "your_certificate_password"); ApnsService service = new ApnsService(config); ``` 其中,第一个参数是环境类型,可以选择生产环境或者测试环境;第二个参数是证书路径;第三个参数是证书密码。 3. 创建消息对象。代码如下: ``` ApnsNotification notification = new ApnsNotification(DEVICE_TOKEN, new ApnsPayload("Hello, world!")); ``` 其中,第一个参数是设备的token;第二个参数是消息的内容。 4. 发消息。代码如下: ``` service.QueueNotification(notification); service.Stop(); ``` 其中,QueueNotification方法用于将消息加入发队列;Stop方法用于停止服务。 完整代码示例: ``` using PushSharp; using PushSharp.Apple; using System; namespace APNSDemo { class Program { static void Main(string[] args) { ApnsConfiguration config = new ApnsConfiguration(ApnsConfiguration.ApnsServerEnvironment.Production, "your_certificate_path", "your_certificate_password"); ApnsService service = new ApnsService(config); string DEVICE_TOKEN = "your_device_token"; ApnsNotification notification = new ApnsNotification(DEVICE_TOKEN, new ApnsPayload("Hello, world!")); service.QueueNotification(notification); service.Stop(); Console.WriteLine("Push notification sent."); Console.ReadLine(); } } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值