V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
getui
V2EX  ›  阅读

手把手教你搞定个推 iOS 推送 SDK 集成

  •  
  •   getui · 2019-08-27 18:26:36 +08:00 · 9327 次点击
    这是一个创建于 1675 天前的主题,其中的信息可能已经有所发展或是发生改变。

    一次偶然的机会,公司的项目要用到推送,我自己本来就很懒,不愿意去弄整套 APNS 的流程,刚好之前跟朋友聊起过他们的产品中集成了个推的 Android 推送,说是体验还可以,那这次我就试一下他们的 iOS 推送。于是抱着试一试的心态,我先建个 demo,试着去集成一下个推 iOS 推送 SDK,摸索着完成了整个流程,言归正传,直接上硬菜!

    ##如何集成个推 iOS SDK

    看了个推的官网,发现他们集成的方式有两种,分别是 XCode 集成和 CocoaPods 集成。本人比较懒,越简单越好,越轻松越好,毫不犹豫的选择了 Cocoapods 集成方式,程序猿么,就是要想尽办法的懒,搞起!

    ###CocoaPods 集成

    1.安装 CocoaPods

    安装方式简单, Mac 下都自带 ruby,使用 ruby 的 gem 命令即可下载安装:

    $ sudo gem install cocoapods
    $ pod setup
    

    2.准备 Podfile 文件

    在我们的工程目录下,新建一个名为 Podfile 的文件,如下格式,将依赖的库名字依次列在文件中即可:

    作者这里使用的是标准版本:

    target 'GeTuipush' do
        platform :ios, "7.0"
        pod 'GTSDK'
    end
    
    target 'NotificationService' do
        platform :ios, "10.0"
        pod 'GTExtensionSDK'
    end
    

    3.完成 GTSDK 导入

    在项目根目录中执行如下命令:

    $ pod install
    

    执行完成后,项目目录结构如下图所示:

    注意:在 pod install 之前,首先你的工程必须创建好,并且如果 Podfile 文件里面如果有 target:NotificationService,那在 pod install 之前需要创建好通知扩展的 Target。

    4.开启推送功能:既然是推送,当然是要开推送功能啦!:

    5.后台运行权限设置:看个推的官网上面说是为了更好的支持消息推送,提供更多的推送样式,提高消息到达率,既然这么说了,那就不管三七二十一先开了再说,如下图所示:

    6.XCode10 建议开启 WiFi 信息授权:在 Xcode 10.x 以上,找到应用 Target 设置中的 Capabilities -> Access WiFi Information,确认开关已经设为 ON 状态。如下图所示:

    注意:主 Target 和通知扩展的 Target 都需要打开

    7.代码部分,下来就是我们程序猿最喜欢的部分了,粘贴复制。由于是第一次集成个推 SDK 的代码,我还是仔细的研究了下。

    ####初始化 SDK 注册 APNs 并获取 CID

    1.为 AppDelegate 增加回调接口类:

    #import <UIKit/UIKit.h>
    #import <GTSDK/GeTuiSdk.h>
    
    // iOS10 及以上需导入 UserNotifications.framework
    #if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
    #import <UserNotifications/UserNotifications.h>
    #endif
    
    @interface AppDelegate : UIResponder <UIApplicationDelegate, GeTuiSdkDelegate, UNUserNotificationCenterDelegate>
    
    @property (strong, nonatomic) UIWindow *window;
    
    
    @end
    

    2.初始化 SDK 并注册 APNs:

    #import "AppDelegate.h"
    
    /// 个推开发者网站中申请 App 时,注册的 AppId、AppKey、AppSecret
    #define kGtAppId           @"GVZZTqh7lu6S4VLMacneZ7"
    #define kGtAppKey          @"RRYDFjGzO17TJXZfGeTuq3"
    #define kGtAppSecret       @"7BXDJ0IgWF6a8M0xCgo4G"
    
    @interface AppDelegate ()
    
    @end
    
    @implementation AppDelegate
    
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        // Override point for customization after application launch.
        [GeTuiSdk startSdkWithAppId:kGtAppId appKey:kGtAppKey appSecret:kGtAppSecret delegate:self];
        // 注册 APNs
        [self registerRemoteNotification];
        return YES;
    }
    

    注册 APNs 获取 DeviceToken:

    /** 注册 APNs */
    - (void)registerRemoteNotification {
     
            UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
            center.delegate = self;
            [center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionCarPlay) completionHandler:^(BOOL granted, NSError *_Nullable error) {
                if (!error) {
                    NSLog(@"request authorization succeeded!");
                }
            }];
            
            [[UIApplication sharedApplication] registerForRemoteNotifications];
    }
    

    个推 demo 里面给开发者提供演示代码,根据 APP 支持的 iOS 系统不同,进行修改。我们的工程最低支持 iOS10。

    获取 CID 信息:

    /** SDK 启动成功返回 cid */
    - (void)GeTuiSdkDidRegisterClient:(NSString *)clientId {
        
        NSLog(@"clientId:%@", clientId);
    }
    

    这三个参数 kGtAppId、kGtAppKey、kGtAppSecret 是干啥用的,这三个参数如何获取?回头又看了下个推的官网才搞明白,正好记录下如何申请者三个参数,跟我应用的 bundleID 绑定。

    ####如何获取 kGtAppId、kGtAppKey、kGtAppSecret

    1.创建个推开发者账号

    访问个推开发者中心,申请个推账号

    2.登记新应用

    注意:登记新应用是在应用管理页面而不是消息推送页面。

    在登记应用界面填写应用名和应用表示,勾选个推产品,勾选 iOS,填写包名和 bundleID,如下图所示:

    这里我有点疑惑。创建应用的时候想勾选 iOS,但是看到默认选择了 Android 平台,并要填写 Android 签名,这签名是 what,这如何搞?看到跟前有个提示如何获取,点了一下,发现里面有 SHA256 的签名,抱着试一试的态度,直接 copy 过来,呦呵,能用哦,心里美滋滋。

    提交成功后就可以获取到 kGtAppId、kGtAppKey、kGtAppSecret,将三个参数填入我们的工程中,然后运行工程,在 GeTuiSdkDidRegisterClient 的回调方法中获取到 cid 了,嗯,看来我们已经成功了一一小部分了,距离成功还要继续加油。

    ####注册 DeviceToken 并统计 APNs 通知的点击数

    1.向个推服务器注册 DeviceToken:

    /** 远程通知注册成功委托 */
    - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
        //向个推服务器注册 deviceToken 为了方便开发者,建议使用新方法
        NSLog(@"deviceToken:%@",deviceToken);
        [GeTuiSdk registerDeviceTokenData:deviceToken];
    }
    

    2.处理 APNs 通知点击事件:

    因为我们的工程最低适配到 iOS10,这里我就只添加了 iOS10 及以后版本的通知点击事件,要是想兼容 iOS10 以下的,可以在个推的 demo 中找到。

    iOS 10 及以后版本,处理 APNs 通知点击事件

    //  iOS 10: 点击通知进入 App 时触发,在该方法内统计有效用户点击数
    - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler {
    
        NSLog(@"didReceiveNotification:%@", response.notification.request.content.userInfo);
    
        // [ GTSdk ]:将收到的 APNs 信息传给个推统计
        [GeTuiSdk handleRemoteNotification:response.notification.request.content.userInfo];
    
        completionHandler();
    }
    
    

    3.接受个推通道下发的透传消息:

    /** SDK 收到透传消息回调 */
    - (void)GeTuiSdkDidReceivePayloadData:(NSData *)payloadData andTaskId:(NSString *)taskId andMsgId:(NSString *)msgId andOffLine:(BOOL)offLine fromGtAppId:(NSString *)appId {
        //收到个推消息
        NSString *payloadMsg = nil;
        if (payloadData) {
            payloadMsg = [[NSString alloc] initWithBytes:payloadData.bytes length:payloadData.length encoding:NSUTF8StringEncoding];
        }
    
        NSString *msg = [NSString stringWithFormat:@"taskId=%@,messageId:%@,payloadMsg:%@%@",taskId,msgId, payloadMsg,offLine ? @"<离线消息>" : @""];
        NSLog(@"\n>>>[GexinSdk ReceivePayload]:%@\n\n", msg);
    }
    

    获取到了透传消息,但是当应用在后台或者应用杀死的情况下,我们如何获取到 APNs 消息,这里我们就需要在个推平台用到推送证书,如何获取推送证书?因为本人也是第一次搞推送这书,而且也踩了不少的坑,为了下次不再踩同样的坑,所以在这里就对如何制作推送证书进行了一次规整。

    ####如何制作推送证书?

    1.进入苹果开发者中心,选择证书选项,如下图所示:

    2.创建推送证书之前必须创建一个 APPID,因为推送证书是和 APPID 绑定在一起的,如下图所示:

    在下面的 App Services 中选择允许推送(Push Notifications),如下图所示:

    3.APPID 创建好了之后,这个时候需要去创建推送证书,而且还要根据需要的环境选择对应的推送证书,包括开发环境推送证书和生产环境推送证书,然后还要跟刚才创建好的 APPID 相关联,如下图所示:

    这个时候需要上传 CSR 文件,我们回到桌面,打开钥匙串,从颁发机构申请证书并保存到本地磁盘,如下图所示:

    这样 CSR 文件就创建好了,我们回到苹果开发者中心,继续创建我们的推送证书,选择保存到本地的 CSR 文件,如下图所示:

    这样,我们的推送证书就创建完成了,在本地下载中找到下载的推送证书并双击添加到钥匙串中,然后打开钥匙串找到创建好的推送证书,右键导出 P12 证书,并输入证书密码,如下图所示:

    4.打开我们的个推开发者中心,在个推·消息推送-应用列表-应用配置”中上传正确的 APNs 证书,如下图所示:

    接下来最重要的时刻来了,那就是测试了,看看我们的推送能不能成功。

    ###推送测试

    本人是在个推平台上面进行推送测试的,在应用列表里面点击之前创建的应用上的创建推送按钮,如下图所示:

    进入后,我有点懵逼,因为之前没有了解过个推 SDK 的逻辑,在询问了个推技术支持后,技术支持告诉我怎么在个推平台上面去推,也是自己太粗心了,人家进去第一句话就写的很清楚,推送通知目前仅支持安卓用户,iOS 请使用透传消息。尴尬!那就透传消息页面试试推。如下图所示:

    透传消息测试:

    APNs 消息测试

    NICE 啊,这下应用在前台、应用在后台和应用被杀死的情况下都可以收到推送消息了,爽歪歪啊!看来我们已经成功看了百分之九十了!

    ###Notification Service Extension

    正在沾沾自喜的时候,突然发现个推的官网上面还有多媒体推送,我靠,还有这种操作,好奇心的趋势下,让我重新审视如何去做多媒体推送。因为我们之前已经把通知扩展的 target 创建好了,所以,直接上代码。

    1.Notification Service Extension 添加成功后会在项目中自动生成 NotificationService.h 和 NotificationService.m 两个类,包含以下两个方法:

    - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent *_Nonnull))contentHandler {
        self.contentHandler = contentHandler;
        self.bestAttemptContent = [request.content mutableCopy];
    
        // [ 测试代码 ] TODO:用户可以在这里处理通知样式的修改,eg:修改标题,开发阶段可以用于判断是否运行通知扩展
        //self.bestAttemptContent.title = [NSString stringWithFormat:@"%@ [WillIn]", self.bestAttemptContent.title];
    
        // [ GTSDK ] 统计 APNs 到达情况和多媒体推送支持接口, 建议使用该接口
        [GeTuiExtSdk handelNotificationServiceRequest:request withAttachmentsComplete:^(NSArray *attachments, NSArray *errors) {
            
            // self.bestAttemptContent.title = [NSString stringWithFormat:@"%@ [Success]", self.bestAttemptContent.title];
            
            self.bestAttemptContent.attachments = attachments;      // 设置通知中的多媒体附件
            self.contentHandler(self.bestAttemptContent);           
        }];
    }
    

    我们可以在这个方法中处理我们的 APNs 通知,并个性化展示给用户。APNs 推送的消息送达时会调用这个方法,此时你可以对推送的内容进行处理,然后使用 contentHandler 方法结束这次处理。但是如果处理时间过长,将会进入 serviceExtensionTimeWillExpire 方法进行最后的紧急处理。

    - (void)serviceExtensionTimeWillExpire {
     // [ GTSDK ] 销毁 SDK,释放资源
        [GeTuiExtSdk destory];
        
        //self.bestAttemptContent.title = [NSString stringWithFormat:@"%@ [Timeout]", self.bestAttemptContent.title];
        
        self.contentHandler(self.bestAttemptContent);
    }
    

    如果 didReceiveNotificationRequest 方法在限定时间内没有调用 contentHandler 方法结束处理,则会在过期之前进行回调本方法。此时你可以对你的 APNs 消息进行紧急处理后展示,如果没有处理,则显示原始 APNs 推送。

    接下来就是测试我们的多媒体推送是否成功,我在网上找了个小狗的照片,直接在个推平台上面推。

    多媒体测试

    6 啊,终于搞定了!棒棒哒~~~

    但是,之前的一个老项目说也要集成推送,我透,老项目要用 XCode 集成,这对于我这种懒人来说,简直是一种折磨啊,哎,折磨归折磨,该搞还要搞。但是之前已经用 CocoaPods 搞过一遍,这次用 XCode 集成还不是手到擒来。但是为了防止出错,本人还是先做了个 demo,这样后面在自己项目上面集成的话把握性会更大,踩的坑也就会更少。

    ###XCode 集成

    1.导入个推 SDK:

    2.库引用检查:

    3.添加系统依赖库:

    libc++.tbd
    libz.tbd
    libsqlite3.tbd
    libresolv.tbd
    Security.framework
    MobileCoreServices.framework
    SystemConfiguration.framework
    CoreTelephony.framework
    AVFoundation.framework
    CoreLocation.framework 
    UserNotifications.framework (iOS 10 及以上需添加,使用 Optional 方式接入)
    AdSupport.framework   (如果使用无 IDFA 版本 SDK,则需删除该 AdSupport 库)
    

    幸亏后面的步骤基本上都是一样的,唯一的欣慰呀!

    4.开启推送功能、后台运行权限设置、开启 WiFi 信息授权

    这里跟上面步骤一样,就不啰嗦了。

    5.copy 代码,这是我们程序猿最喜欢的啦,哈哈哈,之前搞过,这里就不累赘了。

    6.添加 Notification Service Extension

    (1).打开 XCode,菜单中选择 File->New->Target->Notification Service Extension。如下图所示:

    **注意:**1.Extension 的 Bundle Identifier 不能和 Main Target(也就是自己的 App Target)的 Bundle Identifier 相同,否则会报 BundleID 重复的错误。2.Extension 的 Bundle Identifier 需要在 Main Target 的命名空间下,比如说 Main Target 的 BundleID 为 ent.getui.xxx ,那么 Extension 的 BundleID 应该类似与 ent.getui.xxx.yyy 这样的格式。如果不这么做,会引起命名错误。

    这个是在个推官网上面看到的,之前自己也踩了这个坑,这里就记录下来。

    添加 Notification Service Extension 后会生成相应的 Target。点 Finish 按钮后会弹出是否激活该 Target 对应 scheme 的选项框,选择 Activate,如果没有弹出该选项框,需要自行添加相应的 scheme。如下图所示:

    (2).Notification Service Extension 添加成功后会在项目中自动生成 NotificationService.h 和 NotificationService.m 两个类

    这里跟上面一样,就不累赘了。

    (3).添加 GtExtensionSdk 依赖库

    选择 Notification Service Extension 所对应的 Target,添加如下依赖库:

    libz.tbd
    libsqlite3.tbd
    GTExtensionSDK.framework
    UserNotifications.framework
    

    (4).XCode10 建议开启 WiFi 信息授权:在 Xcode 10.x 以上,找到应用 Target 设置中的 Capabilities -> Access WiFi Information,确认开关已经设为 ON 状态。如下图所示:

    (5).开启多媒体地址 Http 访问支持:

    ##集成过程中遇到的问题

    无效的 deviceToken

    最让我印象深刻的就是无效的 deviceToken,在测试 APNS 推送的时候,询问过个推那边的技术支持,他们说可以先在应用配置里面测试一下,然后我就拿着我的 deviceToken 去测试一下,结果提示我是无效的 deviceToken,我晕,然后继续咨询个推的技术支持,他们说这个原因有可能是我证书环境的问题。经过一番仔细的检查之后,发现,我在个推平台上面上传的是通用证书,然后我 XCode 上面的授权证书是开发环境下,这样一来,拿到的是开发环境下的 deviceToken,用测试一下,当然会出错。 解决的方案有两种:第一,在个推开发平台上传开发环境下的推送证书。第二:将自己的授权证书更换为生产环境。

    通知扩展里面修改标题的代码不生效

    self.bestAttemptContent.title = [NSString stringWithFormat:@"%@ [Success]", self.bestAttemptContent.title];
    

    发现 demo 里面有这么一行代码,我把这行代码打开后,推送一条消息,发现标题没有变化,我惊呆了!询问个推技术支持,个推技术支持说,让我先运行主 target,然后再运行通知扩展,运行通知扩展的时候会让我们去找主 targetAPP,选择主 target,然后再推送就会有了,嗯,想了下,这个应该是 XCode 的 bug。

    ##结语

    最后,我要说,消息推送功能的集成对 APP 而言真的真的很重要。以上是个推 iOS 推送 SDK 集成的全步骤,给大家做个参考。特别需要注意的几点是:

    1.在个推平台上上传的推送证书一定要正确并且要和自己的环境相对应,推荐上传 P8 证书;

    2.主 target 和通知扩展 target 是两个 target,命名和 bundleID 上要注意,本人是按照个推官网给的建议命名的。

    原文链接: 作者:Ezreallp 链接: https://www.jianshu.com/p/cce2200c0ed7

    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   960 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 21:19 · PVG 05:19 · LAX 14:19 · JFK 17:19
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.