实现iOS消息推送

消息推送过程

实现iOS消息推送_第1张图片

  1. 应用启动时,调用registerUserNotificationSettings:方法与Apple的APNS服务器通信,并注册推送服务。注册成功后,系统会调用应用的didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken方法。其中,deviceToken参数是APNS返回的deviceToken(用来唯一标识一个设备,每个设备上的每个应用的deviceToken都不相同)。在这里,我们需要将这个deviceToken上传到我们自己的服务器中,用来向指定设备发送push消息。

  2. 服务端拿到这个deviceToken后,使用我们申请好的证书和这个deviceToken,向Apple的APNS服务器发送一个JSON串,这个JSON串中包含我们要向iOS设备发送的内容。

  3. APNS服务器收到这个JSON串,并向deviceToken指定的设备发送消息,iOS应用收到消息后,会调用- (void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo方法。

  4. APNS发送完消息后,将消息是否推送成功的状态反馈给我们的服务端。

开发前的准备

这里的准备主要是需要从Apple开发者中心注册好应用ID并申请相应的证书。

注册应用ID

  1. 打开Apple developer member center,如下图所示,点击红框里面的那一项。
    实现iOS消息推送_第2张图片
  2. 点击左侧的Identifiers下的App IDs项,如下图所示,然后点击右上角的加号。
    实现iOS消息推送_第3张图片
  3. 在下图的Name一栏里填入应用名字(可以跟你的iOS应用名字不同)。
    实现iOS消息推送_第4张图片
  4. 继续往下拉,选中App ID Suffix项的Explicit App ID,在Bundle ID栏里填入你的应用的Bundle ID(需要跟你的应用的Bundle Identifier相同)。
    实现iOS消息推送_第5张图片
  5. 不要忘记在下面的App Services里面勾选上Push Notification(不勾选不能使用推送服务)。
    实现iOS消息推送_第6张图片
  6. 继续点击Continue,在新页面中点击submit,最终出现下面的页面,点击Done完成创建应用。
    实现iOS消息推送_第7张图片

生成推送证书

  1. 打开Mac上的钥匙串访问应用,在左上角的状态栏中的钥匙串访问项中选择证书助理,再选择从证书颁发机构请求证书
    实现iOS消息推送_第8张图片
  2. 打开如下图界面后,在用户电子邮件地址栏中填入Apple开发者账号的电子邮件地址,常用名称中填入一个名字,这里起Push
    实现iOS消息推送_第9张图片
  3. 选择保存到磁盘。
  4. 然后点击继续,将证书保存到桌面的push文件夹中。
  5. 现在,push文件夹中有了一个CertificateSigningRequest.certSigningRequest的文件。
  6. 继续回到member center中,在左侧选择Certificates下的All,点击右上角的加号。
    实现iOS消息推送_第10张图片
  7. 在证书类型选择那里像下图那样选择(这里申请的是开发测试证书,正式发布产品的话选择下面Product栏里的证书)。
    实现iOS消息推送_第11张图片
  8. 在下面的App ID项里选择刚才创建的App ID。
    实现iOS消息推送_第12张图片
  9. Upload CSR file那里选择选择刚才保存在桌面的push文件夹中的CertificateSigningRequest.certSigningRequest文件。
    实现iOS消息推送_第13张图片
  10. 点击Generate,出现如下页面,点击Download,把证书保存到刚才的push文件夹中。
    实现iOS消息推送_第14张图片
  11. 此时push文件夹aps_development.cer`CertificateSigningRequest.certSigningRequest两个文件。
  12. 点击aps_development.cer证书,在钥匙串访问中会出现一个Apple Development IOS push services证书,一个公用密钥和一个专用秘钥,秘钥的名称与证书助理中填写的名称一致。
  13. 选中证书,导出为 apns-dev-cert.p12 文件,保存到push文件夹
  14. 选中专有秘钥,导出为apns-dev-key.p12文件,保存到push文件夹
  15. 如果服务端使用PHP开发,则需要在终端中执行以下命令生成PHP需要的pem证书

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

    生成pem证书时需要输入导出证书时设置的密码。
    然后执行下面的命令,将两个证书合成为一个:

    cat apns-dev-cert.pem apns-dev-key.pem > apns-dev.pem

    最终的apns-dev.pem就是服务端所需要的证书。

  16. 如果服务端使用C#JAVA开发,则需要生成p12格式的证书:

    openssl pkcs12 -clcerts -nokeys -out apns-dev-cert.pem -in apns-dev-cert.p12
    openssl pkcs12 -nocerts -out apns-dev-key.pem -in apns-dev-key.p12
    openssl pkcs12 -export -in apns-dev-cert.pem -inkey apns-dev-key.pem  -certfile CertificateSigningRequest.certSigningRequest -name "push" -out push.p12      

    生成.p12证书的过程同样需要输入导出证书时设置的密码。
    最终生成的push.p12证书就是服务端要使用的证书。

生成Provisioning Profiles

  1. Member Center左侧选择Provisioning Profiles栏下的All,然后点击右上角的加号。

  2. 出现下面的页面后,选择iOS App Devleopment项(这里也是开发测试配置文件,实际产品可以选择Distribution栏下的项目),点击Continue
    实现iOS消息推送_第15张图片

  3. 在选择APP ID 页面中选择刚才创建的APP ID,点击Continue
    实现iOS消息推送_第16张图片

  4. 在选择证书页面中选择Select ALl,点击Continue
    实现iOS消息推送_第17张图片

  5. 在选择设备页面中选择Select All,(如果你的设备不在列表中,需要先在Member Center中添加你的设备),点击Continue
    实现iOS消息推送_第18张图片

  6. 在下面的页面中的Name栏中填入这个Provisioning Profiles的名字,这里填的是Blog
    实现iOS消息推送_第19张图片

  7. 在Xcode的偏好设置中的Account标签中点击右下角的View Details按钮。
    实现iOS消息推送_第20张图片

  8. 在出现界面的Provisioning Profiles栏中找到刚才创建的Provisioni Profiles名字,点击后面的Download按钮下载到本机。
    Xcode Download

客户端开发

首先,需要在客户端申请推送权限并获取Device Token,在AppDelegate.m中加入如下代码:

//应用启动完毕
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    UIUserNotificationSettings *notiSetting = [UIUserNotificationSettings
                                               settingsForTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIUserNotificationTypeSound)
                                               categories:nil];
    //申请远程推送权限
    [application registerUserNotificationSettings:notiSetting];

    return YES;
}

- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(nonnull UIUserNotificationSettings *)notificationSettings
{
    //注册远程推送
    [application registerForRemoteNotifications];
}

//成功申请到远程推送权限后将会调用这个方法
//早这个方法中需要将获取到的device token上传到自己的服务器端
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    //upload this device token to your service for send message to this device
    NSLog(@"Device Token : %@",deviceToken);
}

//注册远程推送失败后会执行这个方法
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(nonnull NSError *)error
{
    NSLog(@"Error : %@", [error userInfo]);
}

//收到远程推送时会执行下面的方法
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo
{
    NSString *serinfo = [NSString stringWithFormat:@"%@",userInfo];
    NSLog(@"User info : %@", serinfo);
}

当应用第一次运行时就会弹出下面的提示框询问用户是否同意应用推送消息给他。
实现iOS消息推送_第21张图片

用户选择“好”后,didRegisterForRemoteNotificationsWithDeviceToken:就会被调用,从而获得device token
需要注意的是,当应用正在执行时收到推送通知时会直接调用didReceiveRemoteNotification:方法。
当应用不在执行时,收到通知后点击通知消息冷启动后会首先调用didFinishLaunchingWithOptions:再调用didReceiveRemoteNotification:方法。
当冷启动时,在didFinishLaunchingWithOptions:方法中也可以直接使用下面的代码获取推送过来的消息(与didReceiveRemoteNotification:中传入的userInfo相同)

NSDictionary* userInfo = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];

服务端开发

为了省事,我这里使用了javapns库,代码如下:

public class Puser
{
    public static void main(String[] args)
    {
        //device token
        String token = "d8e5c7668df7c9572ae575afb23c0cec03c0921ab5547a3df6dbb15fdde3541e";
        //证书路径
        String certPath = "cert/push.p12";
        //证书密码
        String passWord = "5555555";
        try
        {
            PushNotificationPayload payLoad = PushNotificationPayload.complex();
            //要推送的消息
            payLoad.addCustomAlertBody("Hello");
            //应用图标显示的角标
            payLoad.addBadge(1);
            //收到推送到达时的声音
            payLoad.addSound("default");

            PushedNotifications notifications =  Push.payload(payLoad, certPath, passWord, false, token);
            System.out.println(notifications);
        }catch(Exception e)
        {
            e.printStackTrace();
        }
    }

}

执行后收到通知:

实现iOS消息推送_第22张图片

Payload简介

上面我们曾说到我们要给用户推送消息,要向Apple的服务器发送一个JSON串,这个JSON串就叫做Payload

Payload是一个指定格式的JSON串,Apple规定Payload中必须包含一个名为apsDictionary属性,并且Payload的大小不能超过2k,否则,APNs将拒绝转发这个Payload。下面的表格列出了aps中的各个属性。

APNs只是“尽最大努力”将Payload交付给用户而不能够保证一定会将Payload交付给用户

aps的属性列表:

值类型 备注
alert String 或 Dictionary 要显示的消息
bage Number 应用图标角标的数字
sound String 通知声音

alert属性值的类型为String时,消息到达时显示默认样式的提示框(带关闭和查看按钮),类型为Dictionary时,各属性参考Apple消息推送服务开发指南。

例如,下面就是一个标准的Payload:

{
    "aps" : {
        "alert" : "You got your emails.",
        "badge" : 1,
        "sound" : "default"
    }
}

当然,我们也可以在Payload中加入自定义的属性,方便客户端根据服务器的推送做出相应的响应。

例如,下面就是一个添加了自定义属性的Payload:

{
    "aps" : {
        "alert" : "You got your emails.",
        "badge" : 1,
        "sound" : "default"
    },
    "acme1" : "bar",
    "acme2" : 42
}

其中,acme1acme2都是自己定义的属性。

自定义的属性必须为JSON的原生属性,例如StringArrayDictionary

当然,为了方便实现应用的国际化,Payload中也添加了一些实现应用国际化的字段,这些都可以去查阅Apple的Apple消息推送服务开发指南,这里只是对Payload的一个简介。

你可能感兴趣的:(ios)