• 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(@"
    >>>[DeviceToken Success]:%@
    
    ", 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(@"
    >>[GTSdk error]:%@
    
    ", [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(@"
    >>[GTSdk ReceivePayload]:%@
    
    ", msg);
    #pragma mark--- 接收到推送后,进行提示或怎样
    
    }
    /** SDK收到sendMessage消息回调 */
    - (void)GeTuiSdkDidSendMessage:(NSString *)messageId result:(int)result
    {
        // 发送上行消息结果反馈
        NSString *msg = [NSString stringWithFormat:@"sendmessage=%@,result=%d", messageId, result];
        NSLog(@"
    >>[GTSdk DidSendMessage]:%@
    
    ", msg);
    }
    
    
    /** SDK运行状态通知 */
    - (void)GeTuiSDkDidNotifySdkState:(SdkStatus)aStatus
    {
        // 通知SDK运行状态
        NSLog(@"
    >>[GTSdk SdkState]:%u
    
    ", 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(@"
    >>[GTSdk SetModeOff Error]:%@
    
    ", [error localizedDescription]);
            return;
        }
        NSLog(@"---ss-%d____",isModeOff);
        NSLog(@"
    >>[GTSdk SetModeOff]:%@
    
    ----", 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];

     

  • 相关阅读:
    Java多线程:线程与进程
    Java多线程:线程间通信之volatile与sychronized
    Java基础:内存模型
    Windows10 ubuntu子系统的启用即基础配置
    Java基础:Java虚拟机(JVM)
    前序,中序,后序问题
    Java枚举enum以及应用:枚举实现单例模式
    Java外部类可以访问内部类private变量
    Java单例模式(Singleton)以及实现
    Java构造器:级联调用,调用兄弟构造器
  • 原文地址:https://www.cnblogs.com/ningmengcao-ios/p/6599301.html
Copyright © 2020-2023  润新知