ios 个推推送集成

个推推送总结:

个推第三方平台官网地址:http://www.getui.com/cn/index.html

首先去官网注册账号,创建应用,应用的配置信息,创建APNs推送证书上传 P12证书(开发对应开发证书,上线对应生产证书)包括导入 SDK 添加依赖库...这些繁琐的事请移步个推官网查看 xcode 集成教程.

一.推送的流程

个推 iOS 推送服务框架如下图所示:

  • 绿色部分是 APNs 推送,个推平台替开发者的应用通过苹果 APNs 服务器向指定的目标设备进行推送。由 APNs Server 将通知推送到相应的 iOS 设备上。
  • 红色部分是个推应用内推送部分,即 App 启动时,应用内集成的个推SDK会开启长连接到个推服务器,从而开发者可通过个推服务器推送消息到 App 里,这条链路性能和稳定性更强,是APNs的一个很重要的补充。

  app 在收到推送消息时分为三种情况

1.app 在前台接收到通知

APP接收到推送后推送后首先弹出一个Alert提示是否跳转页面

2.app 在后台接收到通知

点击通知栏使APP进入前台后,直接跳转页面

点击icon图标使APP进入前台后,不作操作

3.app 处于关闭状态接收到通知

点击通知栏启动APP,直接跳转页面

点击icon图标启动APP,不作操作

 

二.iOS 集成个推只支持透传消息(透传消息并且支持安卓)

 

三.集成个推官网 SDK 配置AppID,AppKey,AppSecret

首先为AppDelegate添加一个属性 分辨通知的三种情况

// 用来判断是否是通过点击通知栏开启(唤醒)APP
@property (nonatomic) BOOL isLaunchedByNotification;

 

[1]:使用APPID/APPKEY/APPSECRENT创建个推实例

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [self startSdkWith:kGtAppId appKey:kGtAppKey appSecret:kGtAppSecret];
}
- (void)startSdkWith:(NSString *)appID appKey:(NSString *)appKey appSecret:(NSString *)appSecret
{
    //[1-1]:通过 AppId、 appKey 、appSecret 启动SDK
    //该方法需要在主线程中调用
    [GeTuiSdk startSdkWithAppId:appID appKey:appKey appSecret:appSecret delegate:self];
    //[1-2]:设置是否后台运行开关
    [GeTuiSdk runBackgroundEnable:YES];
    //[1-3]:设置电子围栏功能,开启LBS定位服务 和 是否允许SDK 弹出用户定位请求
    [GeTuiSdk lbsLocationEnable:YES andUserVerify:YES];
}

[2]:注册APNS

#pragma mark - 用户通知(推送) _自定义方法
/** 注册远程通知 */
- (void)registerRemoteNotification {

    if ([[UIDevice currentDevice].systemVersion floatValue] >= 10.0) {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 // Xcode 8编译会调用
        UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
        [center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionCarPlay) completionHandler:^(BOOL granted, NSError *_Nullable error) {
            if (!error) {
                NSLog(@"request authorization succeeded!");
            }
        }];
        
        [[UIApplication sharedApplication] registerForRemoteNotifications];
#else // Xcode 7编译会调用
        UIUserNotificationType types = (UIUserNotificationTypeAlert | UIUserNotificationTypeSound | UIUserNotificationTypeBadge);
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
        [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
        [[UIApplication sharedApplication] registerForRemoteNotifications];
#endif
    } else if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) {
        UIUserNotificationType types = (UIUserNotificationTypeAlert | UIUserNotificationTypeSound | UIUserNotificationTypeBadge);
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
        [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
        [[UIApplication sharedApplication] registerForRemoteNotifications];
    } else {
        UIRemoteNotificationType apn_type = (UIRemoteNotificationType)(UIRemoteNotificationTypeAlert |
                                                                       UIRemoteNotificationTypeSound |
                                                                       UIRemoteNotificationTypeBadge);
        [[UIApplication sharedApplication] registerForRemoteNotificationTypes:apn_type];
    }
}

[3]远程通知注册成功委托

/** 远程通知注册成功委托 */
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    NSString *token = [[deviceToken description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];
    token = [token stringByReplacingOccurrencesOfString:@" " withString:@""];
    
    NSLog(@"\n>>>[DeviceToken Success]:%@\n\n", token);
    
    NSLog(@"--个推注册成功_-");
    // [ GTSdk ]:向个推服务器注册deviceToken
    [GeTuiSdk registerDeviceToken:token];
}

/** 远程通知注册失败委托 */

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
    NSLog(@"---个推注册失败---");
    //注册失败通知个推服务器
    [GeTuiSdk registerDeviceToken:@""];
}

[4]APP已经接收到远程通知(推送) - (App运行在后台/App运行在前台)

/** APP已经接收到“远程”通知(推送) - (App运行在后台/App运行在前台)  */
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler
{
    //此时 App 在后台点击通知栏进去前台 这里可做进入前台操作
    //app 进去前台 icon角标显示数为0 并且发送个推服务器
    [[UIApplication sharedApplication] cancelAllLocalNotifications];
    [UIApplication sharedApplication].applicationIconBadgeNumber = 0;
    [GeTuiSdk setBadge:0];

    // [ GTSdk ]:将收到的APNs信息传给个推统计
    [GeTuiSdk handleRemoteNotification:userInfo];
    // [4-EXT]:处理APN
    NSString *record = [NSString stringWithFormat:@"App运行在后台/App运行在前台[APN]%@, %@", [NSDate date], userInfo];
    NSLog(@"%@", record);
    
    completionHandler(UIBackgroundFetchResultNewData);
    self.isLaunchedByNotification = YES;

 

//iOS 10中收到推送消息

#pragma mark - iOS 10中收到推送消息

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
//  iOS 10: App在前台获取到通知
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
    
    NSLog(@"willPresentNotification:%@", notification.request.content.userInfo);
    
    // 根据APP需要,判断是否要提示用户Badge、Sound、Alert
    completionHandler(UNNotificationPresentationOptionBadge | UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert);
}

//  iOS 10: 点击通知进入App时触发
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler {
    
    //角标复位
    [GeTuiSdk resetBadge];
    
    [[UIApplication sharedApplication]setApplicationIconBadgeNumber:0];
    
    [[UIApplication sharedApplication] cancelAllLocalNotifications];
    
    NSLog(@"didReceiveNotification:%@", response.notification.request.content.userInfo);
    
    // [ GTSdk ]:将收到的APNs信息传给个推统计
    [GeTuiSdk handleRemoteNotification:response.notification.request.content.userInfo];
    
    completionHandler();
}
#endif

//设置GeTuiSdkDelegate

 

注意 APP 启动成功会返回 clientId ,我们项目中使用clientId进行消息透传,在登录的时候将clientId传给我们自己的服务器,我们服务器根据clientId给用户进行推送

/** SDK启动成功返回cid */
- (void)GeTuiSdkDidRegisterClient:(NSString *)clientId
{
    // [4-EXT-1]: 个推SDK已注册,返回clientId
    NSLog(@">>>[GeTuiSdk RegisterClient]:----%@", clientId);
    // 将clientId写入本地
    [USER_DEFAULT setObject:clientId forKey:kPushClientId];
}

/** SDK遇到错误回调 */
- (void)GeTuiSdkDidOccurError:(NSError *)error
{
    // [EXT]:个推错误报告,集成步骤发生的任何错误都在这里通知,如果集成后,无法正常收到消息,查看这里的通知。
    NSLog(@"\n>>[GTSdk error]:%@\n\n", [error localizedDescription]);
}

/** SDK收到透传消息回调 */

/** SDK收到透传消息回调 */
- (void)GeTuiSdkDidReceivePayloadData:(NSData *)payloadData andTaskId:(NSString *)taskId andMsgId:(NSString *)msgId andOffLine:(BOOL)offLine fromGtAppId:(NSString *)appId
{
    // 汇报个推自定义事件
    [GeTuiSdk sendFeedbackMessage:90001 andTaskId:taskId andMsgId:msgId];
    
    // [4]: 收到个推消息
//这里收到透传消息,根据自己服务器返回的格式处理
    NSDictionary * jsonDict = [NSJSONSerialization JSONObjectWithData:payloadData options:NSJSONReadingMutableLeaves error:nil];
// 当app不在前台时,接收到的推送消息offLine值均为YES
    // 判断app是否是点击通知栏消息进行唤醒或开启
    // 如果是点击icon图标使得app进入前台,则不做操作,并且同一条推送通知,此方法只执行一次
    
    if (offLine) {
        // 离线消息,说明app接收推送时不在前台
        if (self.isLaunchedByNotification) {
            // app是通过点击通知栏进入前台
            
        } else {
            
            // app是通过点击icon进入前台,在这里不做操作
            
        }
    } else  {
        // app已经处于前台,提示框提示
 //调用系统震动系统声音
        AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
        AudioServicesPlaySystemSound(1007);

    }
    // 控制台打印日志
    NSString *msg = [NSString stringWithFormat:@"SDK收到透传消息回调taskId=%@,messageId:%@,payloadMsg:%@%@", taskId, msgId, jsonDict, offLine ? @"<离线消息>" : @""];
    NSLog(@"\n>>[GTSdk ReceivePayload]:%@\n\n", msg);
#pragma mark--- 接收到推送后,进行提示或怎样

}
/** SDK收到sendMessage消息回调 */
- (void)GeTuiSdkDidSendMessage:(NSString *)messageId result:(int)result
{
    // 发送上行消息结果反馈
    NSString *msg = [NSString stringWithFormat:@"sendmessage=%@,result=%d", messageId, result];
    NSLog(@"\n>>[GTSdk DidSendMessage]:%@\n\n", msg);
}


/** SDK运行状态通知 */
- (void)GeTuiSDkDidNotifySdkState:(SdkStatus)aStatus
{
    // 通知SDK运行状态
    NSLog(@"\n>>[GTSdk SdkState]:%u\n\n", aStatus);
}

#pragma mark ---application
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
    NSLog(@"推送的内容:%@",notificationSettings);
    
    [application registerForRemoteNotifications];
}

注意: app 运行在后台时并不会走 APNS 推送,由个推服务器推送,我们要让 app在后台第一时间让个推 SDK 断线,先用 APNS 推送, app 进入前台重新激活 SDK, 如果由个推服务器推送 app 可以收到透传的消息,但不会在通知栏提示.

- (void)applicationDidEnterBackground:(UIApplication *)application {
    ///切后台关闭SDK,让SDK第一时间断线,让个推先用APN推送
    [GeTuiSdk destroy];
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
    
    //设置角标为0 相当于复位
    [GeTuiSdk setBadge:0];
    [[UIApplication sharedApplication]setApplicationIconBadgeNumber:0];//进入前台取消应用消息图标搜索
    [[UIApplication sharedApplication] cancelAllLocalNotifications];
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
    [DeviceDelegateHelper sharedInstance].preDate = [NSDate date];
/// 重新上线
    [self startSdkWith:kGtAppId appKey:kGtAppKey appSecret:kGtAppSecret];
}

四.推送开关

关于推送开关的设置,我这里使用单例类属性接收,

//SDK设置推送模式回调
- (void)GeTuiSdkDidSetPushMode:(BOOL)isModeOff error:(NSError *)error
{
    if (error) {
        NSLog(@"\n>>[GTSdk SetModeOff Error]:%@\n\n", [error localizedDescription]);
        return;
    }
    NSLog(@"---ss-%d____",isModeOff);
    NSLog(@"\n>>[GTSdk SetModeOff]:%@\n\n----", isModeOff ? @"开启" : @"关闭");
    
    [GlobalData shareIntance].isMessagePush = isModeOff;
}

在需要设置 UISwitch 开关的地方来设置

[pushBtn setOn:[DemoGlobalClass sharedInstance].isMessageShake];
- (void)getValue:(UISwitch*)sender
{
        [GlobalData shareIntance].isMessagePush = sender.isOn;
        NSLog(@"-----%d__--",!sender.isOn);
     //发送开关结果告诉个推服务器
        [GeTuiSdk setPushModeForOff:!sender.isOn];
 
}

五.关于iOS icon 角标显示

角标的处理,其实个推 SDK 已经封装好了,iOS 前端只需要把收到推送的消息个数,已读全部通知,设置角标为0并且发送个推服务器,如有未读推送通知,把剩余的通知发送给个推服务器,我们服务器从个推服务器上获取角标,来设置推送的消息个数,并有我们服务器发送透传消息过来.

 //设置角标为0 相当于复位
    [GeTuiSdk setBadge:0];
    [[UIApplication sharedApplication]setApplicationIconBadgeNumber:0];//进入前台取消应用消息图标搜索
    [[UIApplication sharedApplication] cancelAllLocalNotifications];

 

 

 

posted @ 2017-03-22 13:03  _水畔竹汐  阅读(5635)  评论(1编辑  收藏  举报