手把手教你实现iOS 远程推送

为服务端生成APNS pem证书  https://nintendoboy.gitbooks.io/swift-study-note-v2/content/wei-fu-wu-duan-sheng-cheng-apns-pem-zheng-shu.html

使用Nodejs调试iOS的APNS通知推送,如此简单   https://github.com/xlsd/iOSPush

 

 

当我们的手机在关闭状态下仍然能收到各种通知,那是我们下载安装的App主动提示到来的新信息,下面是我手机通知中心的部分截图:

 

IMG_72BF35D8E9A7-1.jpeg

众说周知,iOS远程推送通过APNs实现。APNs是Apple Push Notification service的简称,它由Apple独家提供。远程推送的服务的实现依据的是服务器和客户端的长连接,信息通过服务器主动推送(push)给客户端(我们的手机)。其中Android基于开源的理念,推送策略由第三方自定义,方便的同时也造成了市场上推送技术五花八门的存在。而iOS的推送必须通过Apple的服务器来实现,虽然市面上常用的有极光,环信,融云等第三方的存在,但是它们都是基于Apple的APNs, 优化集成推送的前端工作,最后仍然需要将推送证书和设备标志DeviceToken发送给Apple的服务器来实现远程推送。

制作推送证书

iOS工程开发指引中对推送流程的概括如下

 

image.png

服务端的Provider通过APNs将信息推送给Client App经过两步:

1 Provider -> APNs   //需要苹果机构颁发的证书
2 APNs     -> Client   //需要DeviceToken标志App

制作证书之前,介绍一下iOS的设计理念: 基于闭环和安全的思考,苹果公司要求使用APNs服务的开发者,提供开发时的Mac设备、App的ID和运行App的手机,通过对三者的联合检查,基本上能保证确认App的唯一性,保证对AppStore的管理的安全性和可靠性。

首先,我们在苹果开发者中心,注册自己的App的唯一ID:

image.png


继续直至Done.

 

然后制作和AppID相绑定的CER证书

 

image.png

 

点击continue:

image.png

点击continue,能够看到需要创建CSR证书,下面有详细创建步骤,这一步可以绑定开发设备Mac。英文很简单,和创建发布证书时在「钥匙串访问」中的操作一样。

image.png

在「钥匙串访问」中能得到CSR文件

Snip20171207_21.png

上传CSR文件

 

Snip20171207_22.png

 

直至Done,下载CER文件:

 

image.png


双击安装到本机Mac。

image.png

 

在「钥匙串访问」我的证书中,能看到安装后的结果:

 

image.png


可以将证书导出,单独存放。以后别人需要,方便直接发送。

打开AppID的PushNotification功能

 

image.png

 

Snip20171207_30.png

 

现在,证书已经制作好了,然后我们在对应的工程中愉快的使用了。

在工程中使用证书

确认Target的Identify和Signing:

 

Snip20171207_31.png

iOS10中,改进了推送的代理方法,增加了3DTouch效果。下面以iOS10的新方法在AppDelegate添加接受通知的代码:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    
    if (@available(iOS 10.0, *)) {
        
        [[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:(UNAuthorizationOptionBadge|UNAuthorizationOptionSound|UNAuthorizationOptionAlert) completionHandler:^(BOOL granted, NSError * _Nullable error) {
            NSLog(@"%@", error);
        }];
        UNNotificationCategory* generalCategory = [UNNotificationCategory
                                                   categoryWithIdentifier:@"GENERAL"
                                                   actions:@[]
                                                   intentIdentifiers:@[]
                                                   options:UNNotificationCategoryOptionCustomDismissAction];
        
        // Create the custom actions for expired timer notifications.
        UNNotificationAction* snoozeAction = [UNNotificationAction
                                              actionWithIdentifier:@"SNOOZE_ACTION"
                                              title:@"Snooze"
                                              options:UNNotificationActionOptionAuthenticationRequired];
        
        UNNotificationAction* stopAction = [UNNotificationAction
                                            actionWithIdentifier:@"STOP_ACTION"
                                            title:@"Stop"
                                            options:UNNotificationActionOptionDestructive];
        UNNotificationAction* forAction = [UNNotificationAction
                                            actionWithIdentifier:@"FOR_ACTION"
                                            title:@"forAction"
                                            options:UNNotificationActionOptionForeground];
        
        // Create the category with the custom actions.
        UNNotificationCategory* expiredCategory = [UNNotificationCategory
                                                   categoryWithIdentifier:@"TIMER_EXPIRED"
                                                   actions:@[snoozeAction, stopAction,forAction]
                                                   intentIdentifiers:@[]
                                                   options:UNNotificationCategoryOptionNone];
        
        // Register the notification categories.
        UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
        [center setDelegate:self];
        [center setNotificationCategories:[NSSet setWithObjects:generalCategory, expiredCategory,
                                           nil]];
        
        [[UIApplication sharedApplication] registerForRemoteNotifications];
    } else {

    }
    return YES;
}

#pragma mark - UNUserNotificationCenterDelegate

- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler{ 
    NSLog(@"%s", __func__);
}

- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)(void))completionHandler{
    NSLog(@"%s", __func__);
}

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)pToken {
    //保存deviceToken
    NSLog(@"regisger success:%@",pToken);
}

iOS的远程推送需要在真机上调试,如果注册成功,就能在didRegisterForRemoteNotificationsWithDeviceToken方法中获取APNs返回的DeviceToken,在打印栏可以看到。

使用SmartPush调试

使用SmartPush可以在电脑上方便的模拟APNs推送。运行程序,选择我们生成的证书和填上打印栏获得的DeviceToken,就能在我们的App中看到APNs推送来的带有3DTouch功能的通知。

image.png

IMG_0039.PNG

喜欢和关注都是对我的鼓励和支持~

为服务端生成APNS pem证书

1.用mac OS系统钥匙串创建CertificateSigningRequest.certSigningRequest

2.去Apple开发者Certificates, Identifiers & Profiles页面创建推送证书

1).先在App ID下创建应用的ID

一定要勾选Push Notifications

2).创建Certificates

开发版本选择Apple Push Notification service SSL (Sandbox)

发布版本选择Apple Push Notification service SSL (Sandbox & Production)

创建完毕后下载Certificates

3.打开下载的Cer证书,创建P12证书

回来到钥匙串

在1的位置点右键,导出apns-dev-cert.p12(命名为apns-dev-cert)

在1的位置打开小三角,在2的位置导出apns-dev-key.p12(命名为apns-dev-key)

导出p12时可以设置一个密码

4.导出pem证书

打开终端

定位到2个p12证书所在的路径

执行以下命令

1)导出apns-dev-cert.pem

openssl pkcs12 -clcerts -nokeys -out apns-dev-cert.pem -in apns-dev-cert.p12 

2)导出apns-dev-key.pem

 openssl pkcs12 -in apns-dev-key.p12 -out apns-dev-key.pem -nodes

转换证书需要输入创建p12时创建的密码

这样就创建好了2个pem证书

5.验证证书

继续在终端输入

 

如上图:

以“-----BEGIN CERTIFICATE-----”开头

以“-----END CERTIFICATE-----”结尾

即说明证书转换是正确的

同样可以验证

 

看到验证结果包含:

-----BEGIN CERTIFICATE-----

-----END CERTIFICATE-----

-----BEGIN PRIVATE KEY-----

-----END PRIVATE KEY-----

即说明转换成功

现在得到key.pem和cert.pem文件了,无论服务是NodeJS, Python还是Ruby,这只需要这两个文件

下面把2个pem教给服务端的同学就行了,如果还需要2个pem合成的pem

执行命令:

 

 

openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert apns-dis-cert.pem -key apns-dis-key.pem

 

测试环境调试iOS的APNS服务时,可以使用nodejs

需要Mac支持Node js,如果没有安转Node环境可以自行查阅如何安转。

如何写调试js文件:

1.下载推送代码iOSPush

2.其中需要.pem.pkey文件,将配置好的推送证书放在该目录下。image.png

3.使用文本编辑器如Sublime打开APNS.js文件。

image.png

①需要替换成自己手机的deviceToken(是NSString类型而不是NSData)

②填写.pem.pkey

③按照APNS的要求填写对应的字段内容

##推送的格式如下(照抄自苹果)

Class: apn.Notification

Notification encapsulates data to be sent to a device and handles JSON encoding for transmission. See the payload documentation for more details.

Initialization

When initializing a Notification you can optionally pass an object to pre-populate properties as they are defined below.

 

Payload

notification.payload

This Object is JSON encoded and sent as the notification payload. When properties have been set on notification.aps(either directly or with convenience setters) these are added to the payload just before it is sent. If payload already contains an aps property it is replaced.

Example:

 

Output:

 

notification.rawPayload

If supplied this payload will be encoded and transmitted as-is. The convenience setters will have no effect on the JSON output.

Example:

 

Output:

 

Convenience Setters

The setters below provide a cleaner way to set properties defined by the Apple Push Notification Service (APNS).

This table shows the name of the setter, with the key-path of the underlying property it maps to and the expected value type.

Setter NameTarget PropertyType
alertaps.alertString or Object
bodyaps.alert.bodyString
locKeyaps.alert.loc-keyString
locArgsaps.alert.loc-argsArray
titleaps.alert.titleString
titleLocKeyaps.alert.title-loc-keyString
titleLocArgsaps.alert.title-loc-argsArray
actionaps.alert.actionString
actionLocKeyaps.alert.action-loc-keyString
launchImageaps.launch-imageString
badgeaps.badgeNumber
soundaps.soundString
contentAvailableaps.content-available1
mutableContentaps.mutable-content1
urlArgsaps.url-argsArray
categoryaps.categoryString
threadIdaps.thread-idString
mdmmdmString

When the notification is transmitted these properties will be added to the output before encoding.

For each convenience setter there is also a chainable method which invokes the setter and returns this. These are predictably named: propertyName -> setPropertyName().

It is also possible to set properties directly on aps if the setters above do not meet your needs.

Example:

 

Output:

 

Properties

The properties below are sent alongside the notification as configuration and do not form part of the JSON payload. As such, they are not counted against the payload size limit.

notification.topic

Required: The destination topic for the notification.

notification.id

A UUID to identify the notification with APNS. If an id is not supplied, APNS will generate one automatically. If an error occurs the response will contain the id. This property populates the apns-id header.

notification.expiry

A UNIX timestamp when the notification should expire. If the notification cannot be delivered to the device, APNS will retry until it expires. An expiry of 0 indicates that the notification expires immediately, therefore no retries will be attempted.

notification.priority

Provide one of the following values:

  • 10 - The push notification is sent to the device immediately. (Default)

    The push notification must trigger an alert, sound, or badge on the device. It is an error to use this priority for a push notification that contains only the content-available key.

  • 5 - The push message is sent at a time that conserves power on the device receiving it.

notification.collapseId

Multiple notifications with same collapse identifier are displayed to the user as a single notification. The value should not exceed 64 bytes.

如何使用

  • 打开终端,cd命令到指定下载的文件夹的根目录。
  • 使用node命令运行APNS.js文件,如node APNS.js。 推送即可。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值