个推你应该这样用的

前言:

    说到这个远程推送,大家知道的应该都挺多的,但用到的估计极光和个推要占一很大部分,这篇博客重点说的就是个推的使用,个推官网的链接在这里,它的集成是比较方便的,你可以直接使用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);
        }
    }
}
posted @   MrRisingSun  阅读(3685)  评论(1编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示