文档章节

iOS--环信的在线推送和离线推送

指尖流年
 指尖流年
发布于 2017/07/14 19:35
字数 1781
阅读 105
收藏 0
点赞 0
评论 0

今天做了环信的推送,有一些无名的bug着实让人头痛!快看看有没有和我掉进相同的坑里

-、推送前的准备工作

环信SDK的导入和配置上次说过了这次就直接跳过,证书也直接先过

1.进入环信管理后台,找到所创建的项目如图

选择 推送证书

结果:

二、回到工程代码中:

1初始化环信SDK

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    //AppKey:注册的AppKey,详细见下面注释。
    //apnsCertName:推送证书名(不需要加后缀),详细见下面注释。
    NSString *apnsCertName = nil;
    
#if DEBUG
    apnsCertName = @"kaifa";
#else
    apnsCertName = @"shengchan";
#endif
    EMOptions *options = [EMOptions optionsWithAppkey:@"douser#istore"];
    options.apnsCertName =apnsCertNam;
    [[EMClient sharedClient] initializeSDKWithOptions:options];
    
    //登录环信
    EMError *error1 = [[EMClient sharedClient] loginWithUsername:[[NSUserDefaults standardUserDefaults] objectForKey:@"uuid"]  password:[[NSUserDefaults standardUserDefaults] objectForKey:@"password"]];
    
     NSLog(@"ppppppperror1:%d",error1.code);
//自动登录
    [[EMClient sharedClient].options setIsAutoLogin:YES];

//**********环信推送
  //添加监听在线推送消息
    
    [[EMClient sharedClient].chatManager addDelegate:self delegateQueue:nil];
//iOS8以上 注册APNS
    if ([application respondsToSelector:@selector(registerForRemoteNotifications)]) {
        [application registerForRemoteNotifications];
        UIUserNotificationType notificationTypes = UIUserNotificationTypeBadge |
        UIUserNotificationTypeSound |
        UIUserNotificationTypeAlert;

        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:notificationTypes categories:nil];
        [application registerUserNotificationSettings:settings];
    }
    else{
        UIRemoteNotificationType notificationTypes = UIRemoteNotificationTypeBadge |
        UIRemoteNotificationTypeSound |
        UIRemoteNotificationTypeAlert;
        [[UIApplication sharedApplication] registerForRemoteNotificationTypes:notificationTypes];
    }
    return YES;
}
//将得到的deviceToken传给SDK
- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken{
    
    //极光推送
    [JPUSHService registerDeviceToken:deviceToken];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //环信推送
        [[EMClient sharedClient] bindDeviceToken:deviceToken];
        
        NSLog(@"环信推送deviceToken:%@",deviceToken);
        
       // 7a7c8847b366d8cb4cc4c13681b7e9ec99a9c10d31780f57cd7e43745e0cdc23
    });
    
}

//注册deviceToken失败

- (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error{
    
    NSLog(@"deviceToken-----error -- %@",error);
    
}

// APP进入后台

- (void)applicationDidEnterBackground:(UIApplication*)application

{
    
    [[EMClient sharedClient]applicationDidEnterBackground:application];
    
}

// APP将要从后台返回

- (void)applicationWillEnterForeground:(UIApplication*)application

{
    
    [[EMClient sharedClient]applicationWillEnterForeground:application];
    
}

 

本地推送,主要在- (void)messagesDidReceive:(NSArray*)aMessages这个方法中

//监听环信在线推送消息

- (void)messagesDidReceive:(NSArray*)aMessages{

     //aMessages是一个对象,包含了发过来的所有信息,怎么提取想要的信息我会在后面贴出来.
    
    for (EMMessage *message in aMessages) {
        
       // EMConversation *conversation = [[EMClient sharedClient].chatManager getConversation:message.conversationId type:EMConversationTypeChat createIfNotExist:YES];
        
        id<IMessageModel> model = nil;
        model = [[EaseMessageModel alloc] initWithMessage:message];
        
        NSString *nickname = model.nickname;
        
        EMMessageBody *msgBody = message.body;
        switch (msgBody.type) {
            case EMMessageBodyTypeText:
            {
                // 收到的文字消息
                EMTextMessageBody *textBody = (EMTextMessageBody *)msgBody;
               // NSString *txt = [NSString stringWithFormat:@"%@给您发了一条消息:%@",nickname,textBody.text];
               
              //  NSLog(@"--------------收到的文字是 txt -- %@",txt);
                
                    UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"提示"message:@"您收到了一条信息" delegate:nil cancelButtonTitle:@"取消"otherButtonTitles:@"确定",nil];
                
                
                    [alertView show];
                
                
            }
                break;
            case EMMessageBodyTypeImage:
            {
                // 得到一个图片消息body
               // EMImageMessageBody *body = ((EMImageMessageBody *)msgBody);
                
                
                
                
                //                NSLog(@"大图remote路径 -- %@"   ,body.remotePath);
                //                NSLog(@"大图local路径 -- %@"    ,body.localPath); // // 需要使用sdk提供的下载方法后才会存在
                //                NSLog(@"大图的secret -- %@"    ,body.secretKey);
                //                NSLog(@"大图的W -- %f ,大图的H -- %f",body.size.width,body.size.height);
                //                NSLog(@"大图的下载状态 -- %lu",body.downloadStatus);
                //
                //
                //                // 缩略图sdk会自动下载
                //                NSLog(@"小图remote路径 -- %@"   ,body.thumbnailRemotePath);
                //                NSLog(@"小图local路径 -- %@"    ,body.thumbnailLocalPath);
                //                NSLog(@"小图的secret -- %@"    ,body.thumbnailSecretKey);
                //                NSLog(@"小图的W -- %f ,大图的H -- %f",body.thumbnailSize.width,body.thumbnailSize.height);
                //                NSLog(@"小图的下载状态 -- %lu",body.thumbnailDownloadStatus);
            }
                break;
                //            case EMMessageBodyTypeLocation:
                //            {
                //                EMLocationMessageBody *body = (EMLocationMessageBody *)msgBody;
                //                NSLog(@"纬度-- %f",body.latitude);
                //                NSLog(@"经度-- %f",body.longitude);
                //                NSLog(@"地址-- %@",body.address);
                //            }
                //                break;
                //            case EMMessageBodyTypeVoice:
                //            {
                //                // 音频sdk会自动下载
                //                EMVoiceMessageBody *body = (EMVoiceMessageBody *)msgBody;
                //                NSLog(@"音频remote路径 -- %@"      ,body.remotePath);
                //                NSLog(@"音频local路径 -- %@"       ,body.localPath); // 需要使用sdk提供的下载方法后才会存在(音频会自动调用)
                //                NSLog(@"音频的secret -- %@"        ,body.secretKey);
                //                NSLog(@"音频文件大小 -- %lld"       ,body.fileLength);
                //                NSLog(@"音频文件的下载状态 -- %lu"   ,body.downloadStatus);
                //                NSLog(@"音频的时间长度 -- %lu"      ,body.duration);
                //            }
                //                break;
                //            case EMMessageBodyTypeVideo:
                //            {
                //                EMVideoMessageBody *body = (EMVideoMessageBody *)msgBody;
                //
                //                NSLog(@"视频remote路径 -- %@"      ,body.remotePath);
                //                NSLog(@"视频local路径 -- %@"       ,body.localPath); // 需要使用sdk提供的下载方法后才会存在
                //                NSLog(@"视频的secret -- %@"        ,body.secretKey);
                //                NSLog(@"视频文件大小 -- %lld"       ,body.fileLength);
                //                NSLog(@"视频文件的下载状态 -- %lu"   ,body.downloadStatus);
                //                NSLog(@"视频的时间长度 -- %lu"      ,body.duration);
                //                NSLog(@"视频的W -- %f ,视频的H -- %f", body.thumbnailSize.width, body.thumbnailSize.height);
                //
                //                // 缩略图sdk会自动下载
                //                NSLog(@"缩略图的remote路径 -- %@"     ,body.thumbnailRemotePath);
                //                NSLog(@"缩略图的local路径 -- %@"      ,body.thumbnailLocalPath);
                //                NSLog(@"缩略图的secret -- %@"        ,body.thumbnailSecretKey);
                //                NSLog(@"缩略图的下载状态 -- %lu"      ,body.thumbnailDownloadStatus);
                //            }
                //                break;
                //            case EMMessageBodyTypeFile:
                //            {
                //                EMFileMessageBody *body = (EMFileMessageBody *)msgBody;
                //                NSLog(@"文件remote路径 -- %@"      ,body.remotePath);
                //                NSLog(@"文件local路径 -- %@"       ,body.localPath); // 需要使用sdk提供的下载方法后才会存在
                //                NSLog(@"文件的secret -- %@"        ,body.secretKey);
                //                NSLog(@"文件文件大小 -- %lld"       ,body.fileLength);
                //                NSLog(@"文件文件的下载状态 -- %lu"   ,body.downloadStatus);
                //            }
                //                break;
                
            default:
                break;
        }
    }
    
    
}

@property (strong, nonatomic) NSDate *lastPlaySoundDate;

//在后台运行时调用 推送
- (void)didReceiveMessages:(NSArray *)aMessages
{
    for(EMMessage *message in aMessages){
        UIApplicationState state = [[UIApplication sharedApplication] applicationState];
        switch (state) {
            case UIApplicationStateBackground:
                [self showNotificationWithMessage:message];
                break;
            default:
                break;
        }
    }
}
- (void)playSoundAndVibration{
    NSTimeInterval timeInterval = [[NSDate date]
                                   timeIntervalSinceDate:self.lastPlaySoundDate];
    if (timeInterval < 3.0) {
        //如果距离上次响铃和震动时间太短, 则跳过响铃
        NSLog(@"skip ringing & vibration %@, %@", [NSDate date], self.lastPlaySoundDate);
        return;
    }
    
    //保存最后一次响铃时间
    self.lastPlaySoundDate = [NSDate date];
    
    // 收到消息时,播放音频
    [[EMCDDeviceManager sharedInstance] playNewMessageSound];
    // 收到消息时,震动
    [[EMCDDeviceManager sharedInstance] playVibration];
}

- (void)showNotificationWithMessage:(EMMessage *)message
{
 
    
    EMPushOptions *options = [[EMClient sharedClient] pushOptions];

    
    
    NSString *alertBody = nil;
    if (options.displayStyle == EMPushDisplayStyleMessageSummary) {
        EMMessageBody *messageBody = message.body;
        NSString *messageStr = nil;
        switch (messageBody.type) {
            case EMMessageBodyTypeText:
            {
                messageStr = ((EMTextMessageBody *)messageBody).text;
            }
                break;
            case EMMessageBodyTypeImage:
            {
                messageStr = NSLocalizedString(@"message.image", @"Image");
            }
                break;
            case EMMessageBodyTypeLocation:
            {
                messageStr = NSLocalizedString(@"message.location", @"Location");
            }
                break;
            case EMMessageBodyTypeVoice:
            {
                messageStr = NSLocalizedString(@"message.voice", @"Voice");
            }
                break;
            case EMMessageBodyTypeVideo:{
                messageStr = NSLocalizedString(@"message.video", @"Video");
            }
                break;
            default:
                break;
        }
        
        do {
            // NSString *title = [[UserProfileManager sharedInstance] getNickNameWithUsername:message.from];
            if (message.chatType == EMChatTypeGroupChat) {
                NSDictionary *ext = message.ext;
                if (ext && ext[kGroupMessageAtList]) {
                    id target = ext[kGroupMessageAtList];
                    if ([target isKindOfClass:[NSString class]]) {
                        if ([kGroupMessageAtAll compare:target options:NSCaseInsensitiveSearch] == NSOrderedSame) {
                            //alertBody = [NSString stringWithFormat:@"%@%@", title, NSLocalizedString(@"group.atPushTitle", @" @ me in the group")];
                            break;
                        }
                    }
                    else if ([target isKindOfClass:[NSArray class]]) {
                        NSArray *atTargets = (NSArray*)target;
                        if ([atTargets containsObject:[EMClient sharedClient].currentUsername]) {
                            // alertBody = [NSString stringWithFormat:@"%@%@", title, NSLocalizedString(@"group.atPushTitle", @" @ me in the group")];
                            break;
                        }
                    }
                }
                NSArray *groupArray = [[EMClient sharedClient].groupManager getJoinedGroups];
                for (EMGroup *group in groupArray) {
                    if ([group.groupId isEqualToString:message.conversationId]) {
                        // title = [NSString stringWithFormat:@"%@(%@)", message.from, group.subject];
                        break;
                    }
                }
            }
            else if (message.chatType == EMChatTypeChatRoom)
            {
                NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
                NSString *key = [NSString stringWithFormat:@"OnceJoinedChatrooms_%@", [[EMClient sharedClient] currentUsername]];
                NSMutableDictionary *chatrooms = [NSMutableDictionary dictionaryWithDictionary:[ud objectForKey:key]];
                NSString *chatroomName = [chatrooms objectForKey:message.conversationId];
                if (chatroomName)
                {
                    // title = [NSString stringWithFormat:@"%@(%@)", message.from, chatroomName];
                }
            }
            
            //alertBody = [NSString stringWithFormat:@"%@:%@", title, messageStr];
        } while (0);
    }
    else{
        alertBody = NSLocalizedString(@"您收到了一条消息", @"you have a new message");
    }
    
    NSTimeInterval timeInterval = [[NSDate date] timeIntervalSinceDate:self.lastPlaySoundDate];
    BOOL playSound = NO;
    if (!self.lastPlaySoundDate || timeInterval >= 3.0) {
        self.lastPlaySoundDate = [NSDate date];
        playSound = YES;
    }
    
    NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
    [userInfo setObject:[NSNumber numberWithInt:message.chatType] forKey:@"MessageType"];
    [userInfo setObject:message.conversationId forKey:@"ConversationChatter"];
    
    //发送本地推送
    if (NSClassFromString(@"UNUserNotificationCenter")) {
        UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:0.01 repeats:NO];
        UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
        if (playSound) {
            content.sound = [UNNotificationSound defaultSound];
        }
        content.body =alertBody;
        content.userInfo = userInfo;
        UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:message.messageId content:content trigger:trigger];
        [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:nil];
    }
    else {
        UILocalNotification *notification = [[UILocalNotification alloc] init];
        notification.fireDate = [NSDate date]; //触发通知的时间
        notification.alertBody = alertBody;
        notification.alertAction = NSLocalizedString(@"open", @"Open");
        notification.timeZone = [NSTimeZone defaultTimeZone];
        if (playSound) {
            notification.soundName = UILocalNotificationDefaultSoundName;
        }
        notification.userInfo = userInfo;
        
        //发送通知
        [[UIApplication sharedApplication] scheduleLocalNotification:notification];
        
        
    }
}

 

代码就这么多。这样既有本地推送又有离线推送,如果做完了这些,还是收不到离线推送(app被关闭或者进入后台三分钟之后),就要看以下方面了:

1.看看你环信后台上传的证书名称与工程中初始化SDK的证书名是否一致

2.配置证书时候填的Bundle Identifier与你工程中的Bundle Identifier是否相同

3. deviceToken有没有传给环信SDK。即查看管理后台中,对应 IM 账户下是否有您刚刚写的证书名。(这两个方法有没有实现)

//将得到的deviceToken传给SDK

- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken{

      //极光推送

    [JPUSHService registerDeviceToken:deviceToken];

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        //环信推送

        [[EMClient sharedClient] bindDeviceToken:deviceToken];

             NSLog(@"环信推送deviceToken:%@",deviceToken);

    });}

 

//注册deviceToken失败

- (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error{    

    NSLog(@"deviceToken-----error -- %@",error);

}

4.确认Xcode环境是否配置正确 ,Build Settings---signing,看Debug对应的是不是开发的,Release对应的是不是生产的

5.在确认xcode运行环境是否正确 (Product-->Scheme-->Edit Scheme, 开发证书选Debug,生产证书选Release)

6.证书制作上传过程是否有问题,开发环境和生产环境是否一一对应。另外可以用推送工具进行验证(Easy APNs Provider - 推送测试工具)。

7.如果以上都没有问题,可以尝试重新制作上传一下推送证书。

最后,上张图

 

 

不足之处,请留言,谢谢!

 

 

© 著作权归作者所有

共有 人打赏支持
指尖流年
粉丝 6
博文 56
码字总数 25456
作品 0
海淀
iOS工程师
NMT 引入移动设备,Google Translate 离线翻译更逼真

谷歌 12 日在官网宣布已将神经机器翻译(Neural Machine Translation,NMT)技术应用到移动设备 Android 和 iOS 上,使得 Google Translate 的离线翻译能力上了一个台阶。 谷歌于约两年前推出...

h4cd ⋅ 06/14 ⋅ 0

【五元感谢】关于app推送 新人新问题

问下,小弟刚做app。 有ios和安卓,不懂推送。 第三方好多推送,现在有2个问题: 1:是否用一个第三方的产品,如极光推送,就可以在ios和安卓用这一套就可以了 2:目前哪个推送产品,比较简单...

kkk111112 ⋅ 04/25 ⋅ 0

Appuploader的安装介绍

注意:下载AU后需安装java8运行环境才能启动;安装好了最新Java8运行环境,解压AU软件包,无需安装,Windows 64位系统点击appuploader.exe启动;如果是Linux/Windows 32位系统或Mac系统双击appuplo...

webmirror ⋅ 05/11 ⋅ 0

iOS神级浏览器Alook端午节限免

前言 今天在 v2ex.com 论坛上看到有用户推荐iOS 端 Alook 浏览器,而且评价很不错,目前正在端午节限时免费中,分享给使用 iOS 的小伙伴们。 Alook Alook 浏览器最具特色的功能是 在线音/视频...

己立 ⋅ 前天 ⋅ 0

iOS天气动画、高仿QQ菜单、放京东APP、高仿微信、推送消息等源码

iOS精选源码 TYCyclePagerView iOS上的一个无限循环轮播图组件(http://www.code4app.com/thread-14507-1-1.html) iOS高仿微信完整项目源码(http://www.code4app.com/thread-14695-1-1.html)......

sunnyaigd ⋅ 06/12 ⋅ 0

iOS一些代码的取巧写法总结(二)

一、在xib/storyboard里面设置view圆角半径 在xib/storyboard里面设置view圆角半径 神奇的IB_DESIGNABLE和IBInspectable(xib中设置圆角) 二、push pop 动画突然消失的解决方案 产生的原因是动...

朝雨晚风 ⋅ 2016/12/05 ⋅ 0

安卓巴士联手Mob产品分享会精彩回顾

上周六(6月9日),由Mob和安卓巴士联合举办的Mob产品分享会在上海游族大厦完美落幕。 (大合影) 活动由Mob的五位PM担任主讲嘉宾,定向邀请了12位VIP用户,共同探讨了解MobSDK产品。 活动开...

逆鳞龙 ⋅ 06/14 ⋅ 0

友盟iOS推送配置(从真机调试到推送)

下面我来讲解一下友盟iOS的推送配置,其实友盟只是一个示例,换做其余的第三方推送服务也会适用,只是第三方的后面服务变了而已。 iOS推送(包括真机调试)所需要的步骤和文件如下: 备注:这...

easonjim ⋅ 2016/04/07 ⋅ 0

Mozilla 为 iOS 版 Firefox 12 浏览器引入全新生产力特性

Mozilla 宣布了面向苹果 iOS 移动平台的 Firefox 12 网络浏览器,为 iPad 和 iPhone 用户带来了一大票全新的生产力特性。 本次更新主打多任务和提升使用效率,比如下载文件以便后续离线阅读。...

达尔文 ⋅ 06/15 ⋅ 0

面试官自述:面向高级开发人员的iOS面试问题

当您准备进行技术性iOS面试时,了解您可能会询问哪些主题以及经验丰富的iOS开发人员期望什么是非常重要的。 这是许多硅谷公司用来衡量iOS候选人资历水平的一系列问题。 这些问题涉及iOS开发的...

菇哒微课 ⋅ 04/26 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Spring MVC基本概念

只写Controller

颖伙虫 ⋅ 15分钟前 ⋅ 0

微软重金收购GitHub的背后逻辑原来是这样的

全球最大的开发者社区GitHub网站花落谁家的问题已经敲定,微软最终以75亿美元迎娶了这位在外界看来无比“神秘”的小家碧玉。尽管此事已过去一些时日,但整个开发者世界,包括全球各地的开源社...

linux-tao ⋅ 15分钟前 ⋅ 0

磁盘管理—逻辑卷lvm

4.10-4.12 lvm 操作流程: 磁盘分区-->创建物理卷-->划分为卷组-->划分成逻辑卷-->格式化、挂载-->扩容。 磁盘分区 注: 创建分区时需要更改其文件类型为lvm(代码8e) 分区 3 已设置为 Linu...

弓正 ⋅ 35分钟前 ⋅ 0

Spring源码解析(六)——实例创建(上)

前言 经过前期所有的准备工作,Spring已经获取到需要创建实例的 beanName 和对应创建所需要信息 BeanDefinition,接下来就是实例创建的过程,由于该过程涉及到大量源码,所以将分为多个章节进...

MarvelCode ⋅ 55分钟前 ⋅ 0

js模拟栈和队列

栈和队列 栈:LIFO(先进后出)一种数据结构 队列:LILO(先进先出)一种数据结构 使用的js方法 1.push();可以接收任意数量的参数,把它们逐个推进队尾(数组末尾),并返回修改后的数组长度。 2....

LIAOJIN1 ⋅ 今天 ⋅ 0

180619-Yaml文件语法及读写小结

Yaml文件小结 Yaml文件有自己独立的语法,常用作配置文件使用,相比较于xml和json而言,减少很多不必要的标签或者括号,阅读也更加清晰简单;本篇主要介绍下YAML文件的基本语法,以及如何在J...

小灰灰Blog ⋅ 今天 ⋅ 0

IEC60870-5-104规约传送原因

1:周期循环2:背景扫描3:自发4:初始化5:请求6:激活7:激活确认8:停止激活9:停止激活确认10:激活结束11:远程命令引起的返送信息12:当地命令引起的返送信息13:文件传送20:响应总召...

始终初心 ⋅ 今天 ⋅ 0

【图文经典版】冒泡排序

1、可视化排序过程 对{ 6, 5, 3, 1, 8, 7, 2, 4 }进行冒泡排序的可视化动态过程如下 2、代码实现    public void contextLoads() {// 冒泡排序int[] a = { 6, 5, 3, 1, 8, 7, 2, ...

pocher ⋅ 今天 ⋅ 0

ORA-12537 TNS-12560 TNS-00530 ora-609解决

oracle 11g不能连接,卡住,ORA-12537 TNS-12560 TNS-00530 TNS-12502 tns-12505 ora-609 Windows Error: 54: Unknown error 解决方案。 今天折腾了一下午,为了查这个问题。。找了N多方案,...

lanybass ⋅ 今天 ⋅ 0

IDEA反向映射Mybatis

1.首先在pom文件的plugins中添加maven对mybatis-generator插件的支持 ` <!-- mybatis逆向工程 --><plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-ma......

lichengyou20 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部