腾讯云即时通讯离线消息集成总结

前言

最近公司的聊天消息增加一个离线消息推送的功能,之前因为排期的问题,只是简单的本地通知,在账号离线的状态下或者是没有开启程序的时候都不会收到,所以新加了一下这个功能。在做这个功能的时候遇到一些小问题,特别在这里分享一下,下面的内容大部分都是对腾讯云通讯文档的整理和分析。

一,集成步骤:

1,推送原理:

如想要接收APNs离线消息通知,需要在腾讯云管理平台提交Push证书,在客户端每次登录时,获取并通过API接口上报Token。详细推送原理可参阅:Apple Push Notification Service。(值得注意的是,推送功能只用于通知用户,如果APP在前台,以app内消息提示小红点为主,不会跳消息提示,didReceiveRemoteNotification 获取到的消息由于不可控,可以忽略。)

2,证书申请流程

APNs 证书申请流程可参考文档:Apple推送证书申请。(这里注意iOS10的推送的区别)。这里有一篇关于iOS10推送的介绍博客,可以看一下

3,上传证书到控制台

完成APNs 证书申请以后,需要把生成的p12证书上传到控制台:


上传时有几个注意点:
1,上传证书名最好使用全英文(尤其不能使用括号等特殊字符)
2,上传证书生效时间为10分钟左右
3,上传证书需要设置密码,无密码收不到推送(这个很重要,一定要设置证书密码,虽然我也不知道为什么要这么做...)
4,注意生产环境的选择,发布AppStore的证书需要设置为生产环境,否则无法收到推送
5,上传的p12证书必须是自己申请的真实有效的证书

4,客户端实现APNs推送 (重点代码演示)
4.1 步骤:

客户端要实现接收APNs推送,需要实现4个部分:

向苹果后台请求DeviceToken、
登录SDK后上传Token到腾讯云、
APP进入后台时上报切后台事件、
APP进入前台时上报切前台事件。

- (void)replyPushNotificationAuthorization:(UIApplication *)application{
    
    if (IOS10_OR_LATER) {
        //iOS 10 later
        UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
        //必须写代理,不然无法监听通知的接收与点击事件
        center.delegate = self;
        [center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge  | UNAuthorizationOptionAlert | UNAuthorizationOptionSound) completionHandler:^(BOOL granted, NSError * _Nullable error) {
            if (!error && granted) {
                //用户点击允许
                NSLog(@"注册成功");
            }else{
                //用户点击不允许
                NSLog(@"注册失败");
            }
        }];
        // 可以通过 getNotificationSettingsWithCompletionHandler 获取权限设置
        //之前注册推送服务,用户点击了同意还是不同意,以及用户之后又做了怎样的更改我们都无从得知,现在 apple 开放了这个 API,我们可以直接获取到用户的设定信息了。注意UNNotificationSettings是只读对象哦,不能直接修改!
        [center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
            NSLog(@"========%@",settings);
        }];
        
    }else if (IOS8_OR_LATER)
    {
        //iOS 8 - iOS 10系统
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound  categories:nil];
        [application registerUserNotificationSettings:settings];
    }
    //注册远端消息通知获取device token
    [application registerForRemoteNotifications];
}

/**
 *  在AppDelegate的回调中会返回DeviceToken,需要在登录后上报给腾讯云后台
/**

-(void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    [[IMAPlatform sharedInstance] configOnAppRegistAPNSWithDeviceToken:deviceToken];
}

上传Token到腾讯云请参考如下代码,填写参数时busiId需要和控制台分配的证书ID保持一致:

- (void)configOnAppRegistAPNSWithDeviceToken:(NSData *)deviceToken
{
    DebugLog(@"didRegisterForRemoteNotificationsWithDeviceToken:%ld", (unsigned long)deviceToken.length);
    NSString *token = [NSString stringWithFormat:@"%@", deviceToken];
    [[TIMManager sharedInstance] log:TIM_LOG_INFO tag:@"SetToken" msg:[NSString stringWithFormat:@"My Token is :%@", token]];
    TIMTokenParam *param = [[TIMTokenParam alloc] init];

/* 用户自己到苹果注册开发者证书,在开发者账号中下载并生成证书(p12文件),将生成的p12文件传到腾讯证书管理控制台,控制台会自动生成一个证书id,将证书id传入一下busiId参数中。*/
#if kAppStoreVersion

// AppStore版本
#if DEBUG
    param.busiId = 2383;
#else
    param.busiId = 2382;
#endif

#else
    //企业证书id
    param.busiId = 2516;
#endif

    [param setToken:deviceToken];

//    [[TIMManager sharedInstance] setToken:param];
    [[TIMManager sharedInstance] setToken:param succ:^{

        NSLog(@"-----> 上传token成功 ");
    } fail:^(int code, NSString *msg) {
        NSLog(@"-----> 上传token失败 ");
    }];
}

注意这里有个问题:这个上传token的步骤必须要在sdk登陆成功之后,才能进行。所以我之前这个步骤都是写在sdk登陆成功之后的回调中...

上报切后台事件请参考如下代码:(下面的这个接口成功,才能收到推送)

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    __block UIBackgroundTaskIdentifier bgTaskID;
    bgTaskID = [application beginBackgroundTaskWithExpirationHandler:^ {

        //不管有没有完成,结束background_task任务
        [application endBackgroundTask: bgTaskID];
        bgTaskID = UIBackgroundTaskInvalid;
    }];

    [[IMAPlatform sharedInstance] configOnAppEnterBackground];
}

- (void)configOnAppEnterBackground
{
    NSUInteger unReadCount = [[IMAPlatform sharedInstance].conversationMgr unReadMessageCount];
    [UIApplication sharedApplication].applicationIconBadgeNumber = unReadCount;

    TIMBackgroundParam  *param = [[TIMBackgroundParam alloc] init];
    [param setC2cUnread:(int)unReadCount];

    [[TIMManager sharedInstance] doBackground:param succ:^() {
        DebugLog(@"doBackgroud Succ");
    } fail:^(int code, NSString * err) {
        DebugLog(@"Fail: %d->%@", code, err);
    }];
}

上报切前台事件请参考如下代码:

- (void)applicationDidBecomeActive:(UIApplication *)application
{
   [[TIMManager sharedInstance] doForeground:^() {
           DebugLog(@"doForegroud Succ");
     } fail:^(int code, NSString * err) {
           DebugLog(@"Fail: %d->%@", code, err);
     }];
}
5,推送格式
5.1 通用推送规则

对于单聊消息,APNs推送规则为:

昵称:内容

其中昵称是发送方用户昵称,如果未设置昵称,则只显示内容。
对于群聊消息,APNs 推送规则为:

名称(群名):内容

其中名称为群名片或者发送者昵称,优先级为 群名片 > 群名。

5.2 不同类型消息推送规则

PNs 推送内容部分为消息体中各个Elem内容组合:

文本Elem:直接显示内容
语音Elem:显示 [语音]
文件Elem:显示 [文件]
图片Elem:显示 [图片]
自定义Elem:显示desc字段内容
例如:
一条消息中包含 文本Elem和图片Elem,文本内容为Test,最终显示的内容为: Test[图片]
另外一条消息中内容为空,则不进行下发,例如如果消息中只有自定义Elem,并且desc为空,则不进行下发;

这里不用关心是否托管账号还是独立账号,只要设置了昵称或者群名推送消息就会带上。

5.3多APP支持

对于需要多APP互通的场景,可在多个APP中写同一个sdkappid,可实现消息互通,由于多个APP推送证书不同,所以需要在控制台上提交多个证书,每个证书在IM通讯云上生成一个编号,可参考 3.1 Token 上报 设置证书,并提供当前证书的编号。

6, 推送声音
6.1 设置自己的推送声音

不同用户可能想使用不通的推送声音,sdk提供了设置用户声音的接口,可实现单聊声音、群组声音、音视频(暂不支持)声音的设置,也可在用户级别设置是否接收推送。

 *  APNs 配置
 */
@interface TIMAPNSConfig : NSObject
/**
 *  是否开启推送:0-不进行设置 1-开启推送 2-关闭推送
 */
@property(nonatomic,assign) uint32_t openPush;
/**
 *  C2C消息声音,不设置传入nil
 */
@property(nonatomic,retain) NSString * c2cSound;

/**
 *  Group消息声音,不设置传入nil
 */
@property(nonatomic,retain) NSString * groupSound;

/**
 *  Video声音,不设置传入nil
 */
@property(nonatomic,retain) NSString * videoSound;

@end

@interface TIMManager : NSObject

/**
 *  设置APNS配置
 *
 *  @param config APNS配置
 *  @param succ   成功回调
 *  @param fail   失败回调
 *
 *  @return 0 成功
 */
-(int) setAPNS:(TIMAPNSConfig*)config succ:(TIMSucc)succ fail:(TIMFail)fail;

@end

参数说明:

参数 说明
config 设置配置
openPush : 是否开启推送 0-不进行设置 1-开启推送 2-关闭推送
c2cSound : 单聊声音,文件名
groupSound : 群组声音,文件名
videoSound : 音视频邀请声音,文件名
succ 成功回调
fail 失败回调

6.2 获取自己的推送声音

界面展示如果需要获取推送声音,可使用 getAPNSConfig 获取,此接口每次都从服务器同步数据,不会进行本地缓存。

@interface TIMManager : NSObject

/**
 *  获取APNS配置
 *
 *  @param succ 成功回调,返回配置信息
 *  @param fail 失败回调
 *
 *  @return 0 成功
 */
-(int) getAPNSConfig:(TIMAPNSConfigSucc)succ fail:(TIMFail)fail;

@end

参数说明:

参数 说明
succ 成功回调,返回 TIMAPNSConfig 结构体
fail 失败回调

6.3 每条离线推送属性

如果需要定制每条消息的展示文本、扩展字段、提示音、是否推送属性,可以在消息设置TIMOfflinePushInfo,此条消息在推送时,会替换用户原有的默认属性。可实现每条消息定制化推送。填入kIOSOfflinePushNoSound到sound属性时接收端强制为静音提示

/**
 填入sound字段表示接收时不会播放声音
 */
extern NSString * const kIOSOfflinePushNoSound;

@interface TIMAndroidOfflinePushConfig : NSObject
/**
 *  离线推送时展示标签
 */
@property(nonatomic,retain) NSString * title;
/**
 *  Android离线Push时声音字段信息
 */
@property(nonatomic,retain) NSString * sound;
/**
 *  离线推送时通知形式
 */
@property(nonatomic,assign) TIMAndroidOfflinePushNotifyMode notifyMode;

@end

@interface TIMIOSOfflinePushConfig : NSObject
/**
 *  离线Push时声音字段信息
 */
@property(nonatomic,retain) NSString * sound;
/**
 *  忽略badge计数
 */
@property(nonatomic,assign) BOOL ignoreBadge;
@end

@interface TIMOfflinePushInfo : NSObject
/**
 *  自定义消息描述信息,做离线Push时文本展示
 */
@property(nonatomic,retain) NSString * desc;
/**
 *  离线Push时扩展字段信息
 */
@property(nonatomic,retain) NSString * ext;
/**
 *  推送规则标志
 */
@property(nonatomic,assign) TIMOfflinePushFlag pushFlag;
/**
 *  iOS离线推送配置
 */
@property(nonatomic,retain) TIMIOSOfflinePushConfig * iosConfig;
/**
  Android离线推送配置
 */
@property(nonatomic,retain) TIMAndroidOfflinePushConfig * androidConfig;
@end

上面的配置一定要在每条发送的message中配置一下,要不然是不会接收到推送消息的。(就是因为功能是先做的,推送是后加的,之前版本的sdk相关的字段废弃了,所以没有配置,卡在了这里很多时间,确实需要检讨一下)

好了,差不多就是这么多了。本人的简书博客大部分都是项目中的遇到的自己遇到的一些问题,或者是自己无聊写的一些小东西,没有什么特别厉害的东西。把博客当做是日记一样写出来,主要是为了提高一下自己语言组织能力和问题记录的目的。。。。

大家加油!!!!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容

  • 点击查看原文 Web SDK 开发手册 SDK 概述 网易云信 SDK 为 Web 应用提供一个完善的 IM 系统...
    layjoy阅读 13,652评论 0 15
  • 不同版本极光推送SDK集成各有差异,集成时一定要注意版本号,楼主已将博文更新成最新的SDK JPush v3.0....
    i顺颂时宜阅读 7,841评论 37 170
  • 1)项目里面不需要环信SDK的太多功能,只是想要聊天和好友功能,其他都不用,那SDK一定要总是跟着更新么? a.环...
    DefaultYuan阅读 26,539评论 17 59
  • 极光推送: 1.JPush当前版本是1.8.2,其SDK的开发除了正常的功能完善和扩展外也紧随苹果官方的步伐,SD...
    Isspace阅读 6,694评论 10 16
  • ** Tips:** 不同版本极光推送SDK集成各有差异,各位童鞋在集成时一定要注意版本号,本人集成的是基于 极光...
    anyurchao阅读 2,401评论 3 26