个推你应该这样用的
前言:
说到这个远程推送,大家知道的应该都挺多的,但用到的估计极光和个推要占一很大部分,这篇博客重点说的就是个推的使用,个推官网的链接在这里,它的集成是比较方便的,你可以直接使用Cocoapods集成,待会再下面命令行也会给大家分享出来,这我们还会提到的有它的一个推送流程,还有SDK的一些使用以及在使用的过程中我们需要注意的地方:
先看看个推的推送流程图:
集成中建议利用Cocoapods集成,建议还是集成这个无IDFA版本,下面是命令行,至于为什么建议集成这个版本的,个推的文档中也有这样一段话:“在 App 内无广告情况下还是建议开发者使用获取 IDFA 版本,并提交 AppStore 审核。 集成 IDFA 而未集成任何广告服务可能会遭到 Apple 拒绝。”。
1 2 | platform :ios pod 'GTSDK' , '1.5.3-noidfa' |
推送需要注意点:
一:在 Xcode 8.0 以上,必须开启Push Notification能力,操作看下图:
二:为了更好支持消息推送,SDK可定期抓取离线消息,提高消息到达率,需要配置后台运行权限,操作如下:
个推把你需要勾选的这两个选项也作出了解释:
Background fetch
: 后台定期获取权限
Remote notifications
:APNs静默推送权限
代码使用说明:
还是建议大家给个推创建一个APPDelegate的类别,如下图所示:
下一步就是注册远程通知 即用户是否同意接收通知,源代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | /** 注册远程通知 即用户是否同意接收通知 */ - ( void )registerRemoteNotification { /* Xcode8的需要手动开启“TARGETS -> Capabilities -> Push Notifications” */ /* 下面的方法区分10.0之后版本和之前版本 该项目的最低适配版本是8.0之后的,所以放弃8.0之前注册远程通知方法 */ if ([[UIDevice currentDevice].systemVersion floatValue] >= 10.0) { #if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 // Xcode 8编译会调用 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]; #else // Xcode 7编译会调用 UIUserNotificationType types = (UIUserNotificationTypeAlert | UIUserNotificationTypeSound | UIUserNotificationTypeBadge); UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:types categories: nil ]; [[UIApplication sharedApplication] registerUserNotificationSettings:settings]; [[UIApplication sharedApplication] registerForRemoteNotifications]; #endif // 大于等于8.0系统的就用这个方法注册远程通知 } 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]; } } #pragma mark - 远程通知(推送)回调 /** 远程通知注册成功委托 */ -( void )application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:( NSData *)deviceToken { NSString *token = [[deviceToken description] stringByTrimmingCharactersInSet:[ NSCharacterSet characterSetWithCharactersInString:@ "<>" ]]; token = [token stringByReplacingOccurrencesOfString:@ " " withString:@ "" ]; // 获取到的Token // NSLog(@"\n>>>[DeviceToken Success]:%@\n\n", token); // [ GTSdk ]:向个推服务器注册deviceToken,这个方法写在类别里面! [ self registerDeviceTokenToGeTuiSDK:token]; } /** 远程通知注册失败委托 */ -( void )application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:( NSError *)error { // NSLog(@"\n>>>[DeviceToken Error]:%@\n\n", error.description); } |
原本想着把SDK的方法一个一个写出来解读的,不过那样子感觉就像官方文档了,没什么意思了,在这里我直接把AppDelegate+getui.m这整个文件的代码写出来,每一个方法都是有说明的,里面很多点也是写在了注释当中,这样就觉得更完整,可读性更高一点:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | @implementation AppDelegate (getui) // 初始化个推SDK -( void )initGeTuiSDK{ // [ GTSdk ]:使用APPID/APPKEY/APPSECRENT创建个推实例 // 通过个推平台分配的appId、 appKey 、appSecret 启动SDK, // 注:该方法需要在主线程中调用 [GeTuiSdk startSdkWithAppId:GTAPPID appKey:GTAPPKEY appSecret:GTAPPSECRET delegate: self ]; } // Background Fetch 恢复SDK 运行 -( void )BackgroundFetchGeTuiSdk{ // Background Fetch 恢复SDK 运行 [GeTuiSdk resume]; } // 同步本地角标值到服务器 -( void )setBadgeGeTuiSdk:( NSInteger )badge{ [GeTuiSdk setBadge:badge]; } // 重置角标计数 -( void )resetBadgeGeTuiSdk{<br> [GeTuiSdk resetBadge]; } /** 向个推注册deviceToken @param deviceToken deviceToken */ -( void )registerDeviceTokenToGeTuiSDK:( NSString *)deviceToken{ // 向个推服务器注册deviceToken [GeTuiSdk registerDeviceToken:deviceToken]; } /* 将收到的APNs信息传给个推统计 @param userInfo 获取到的消息 */ -( void )handleRemoteNotificationToGrTuiSDK:( NSDictionary *)userInfo{ // 将收到的APNs信息传给个推统计 [GeTuiSdk handleRemoteNotification:userInfo]; } #pragma mark - GeTuiSdkDelegate /** SDK启动成功返回cid */ - ( void )GeTuiSdkDidRegisterClient:( NSString *)clientId { // [4-EXT-1]: 个推SDK已注册,返回clientId // NSLog(@"\n>>[GTSdk RegisterClient]:%@\n\n", clientId); WRITEUSERDEFAULTS(clientId, ClientId); } /** SDK遇到错误回调 */ - ( void )GeTuiSdkDidOccurError:( NSError *)error { // [EXT]:个推错误报告,集成步骤发生的任何错误都在这里通知,如果集成后,无法正常收到消息,查看这里的通知。 //NSLog(@"\n>>[GTSdk error]:%@\n\n", [error localizedDescription]); } /* SDK收到透传消息回调 SDK 在线状态时( App 在前台运行),个推服务器会直接给 App 发送透传消息,不发送苹果APNS消息,可以更快的把消息发送到手机端;SDK 离线状态时 (停止 SDK 或 App 后台运行 或 App 停止),个推服务器会给 App 发送苹果 APNs 消息,同时保存个推的离线消息,当 SDK 在线后,SDK 会获取所有的个推透传消息,offLine 字段就是表明该条消息是否为离线消息。 注意:这里是否能收到推送消息也是有在线时间限制的,最长是72小时之前的在线过的用户、 也就是说能收到消息的就是在72小时内在线过的,超过这个时间的是收不到推送消息的,这也就解决好长时间不在线,已在线会收到很多推送消息的困扰 **/ - ( void )GeTuiSdkDidReceivePayloadData:( NSData *)payloadData andTaskId:( NSString *)taskId andMsgId:( NSString *)msgId andOffLine:( BOOL )offLine fromGtAppId:( NSString *)appId { /** *汇报个推自定义事件 *actionId:用户自定义的actionid,int类型,取值90001-90999。 *taskId: 下发任务的任务ID。 *msgId: 下发任务的消息ID。 *返回值: BOOL,YES表示该命令已经提交,NO表示该命令未提交成功。注:该结果不代表服务器收到该条命令 **/ //[GeTuiSdk sendFeedbackMessage:90001 andTaskId:taskId andMsgId:msgId]; // 数据转换 NSString *payloadMsg = nil ; if (payloadData) { payloadMsg = [[ NSString alloc] initWithBytes:payloadData.bytes length:payloadData.length encoding: NSUTF8StringEncoding ]; } // 解析拿到的数据 if (payloadMsg != nil ) { NSData * data = [payloadMsg dataUsingEncoding: NSUTF8StringEncoding ]; NSDictionary * JSONresponseObject = [ NSJSONSerialization JSONObjectWithData:data options: NSJSONReadingMutableContainers error: nil ]; } UIAlertController * GeTuiAlertController=[[NotificationHandleObject sharedInstance]addBaseViewNotificationAlertViewWithMessage:JSONresponseObject[@ "title" ] andConfirmTitle:@ "确定" ]; [ self .window.rootViewController presentViewController:GeTuiAlertController animated: YES completion: nil ]; } } } /** 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); } /** SDK设置推送模式回调 */ - ( void )GeTuiSdkDidSetPushMode:( BOOL )isModeOff error:( NSError *)error { if (error) { // NSLog(@"\n>>[GTSdk SetModeOff Error]:%@\n\n", [error localizedDescription]); return ; } // NSLog(@"\n>>[GTSdk SetModeOff]:%@\n\n", isModeOff ? @"开启" : @"关闭"); } // 别名推送 // 绑定别名是否成功 // 处理 绑定/解绑 delegate返回结果: - ( void )GeTuiSdkDidAliasAction:( NSString *)action result:( BOOL )isSuccess sequenceNum:( NSString *)aSn error:( NSError *)aError { if ([kGtResponseBindType isEqualToString:action]) { //NSLog(@"绑定结果 :%@ !, sn : %@", isSuccess ? @"成功" : @"失败", aSn); if (!isSuccess) { //NSLog(@"失败原因: %@", aError); } } else if ([kGtResponseUnBindType isEqualToString:action]) { //NSLog(@"绑定结果 :%@ !, sn : %@", isSuccess ? @"成功" : @"失败", aSn); if (!isSuccess) { //NSLog(@"失败原因: %@", aError); } } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话