今天做了环信的推送,有一些无名的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"; #endifEMOptions *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.如果以上都没有问题,可以尝试重新制作上传一下推送证书。
最后,上张图
不足之处,请留言,谢谢!