内容简介:(环境:iOS12.0、极光推送SDK3.1.0、极光IM3.7.0)写iOS 推送(苹果原生态)时,笔者就是为研究极光打下基础。结果三个月快过去了,笔者犹如咸鱼,一直未开始研究极光,真是堕落啊。
(环境:iOS12.0、极光推送SDK3.1.0、极光IM3.7.0)
写iOS 推送(苹果原生态)时,笔者就是为研究极光打下基础。
结果三个月快过去了,笔者犹如咸鱼,一直未开始研究极光,真是堕落啊。
极光推送的坑 大多都是 苹果原生态的推送的问题。如果你对苹果原生态推送不了解,建议先看上面笔者写的小白文章,了解原生态的苹果推送方法及调用时机。
本文主要记录一些笔者对极光IM的理解。极光推送略提,弄懂原生态,极光推送就没什么难的地方。
极光推送的初步了解
极光推送的一些小知识
- 设备标签(Tag)和设备别名(Alias)
一个设备只能有一个别名,但能有多个标签。所以别名可以用userId,针对一个用户;标签可以用用户所处分组,方便针对目标用户推送,针对一批用户。
笔者举一个不那么恰当的例子。假设想推送裙子消息给男性用户,那么前端就可以绑定性别到Tag。
- 开发环境和生产环境:
推送证书也分为开发环境和生产环境。虚拟机和真机调试属于开发环境。测试包、企业包和App Store属于生产环境。
SDK中,上线时,我们要改成生产环境。笔者建议大家弄个宏之类的,到时候别忘了切换。
经笔者验证,如果App不是API下载的话,即使参数改成“1”,也收不到生产环境推送。不过不用担心,开发环境和生产环境都是一样的,开发环境只是让我们调试用。
[JPUSHService setupWithOption:launchOptions appKey:@"***" channel:@"Publish channel" apsForProduction:isProduction advertisingIdentifier:nil]; 复制代码
- IDFA
iOS 6.0+,IDFA为设备广告标示符,用于广告投放。通常不会改变,不同App获取到都是一样的。但如果用户完全重置系统((设置程序 -> 通用 -> 还原 -> 还原位置与隐私) ,这个广告标示符会重新生成。
IDFA,同一设备下的不同app信息共享。
获取:[[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
但是要注意审核问题。笔者不用这个就不研究了。在RegistrationID中会再说。
- RegistrationID
原生是采用deviceToken来标识设备唯一性。在极光中采用RegistrationID。其生成原则优先采用IDFA(如果设备未还原IDFA,卸载App后重新下载,能被识别出老用户),次采用deviceToken。
集成了 JPush SDK 的应用程序在第一次 App 启动后,成功注册到 JPush 服务器时,JPush 服务器会给客户端返回唯一的该设备的标识 - RegistrationID。
极光推送的消息形式
- 通知(APNS):手机的通知栏(状态栏)上会显示的一条通知信息。
- 自定义消息(应用内消息):不会被 SDK 展示到通知栏上。自定义消息主要用于应用的内部业务逻辑。朋友圈红点就可以用这个。
- 本地通知:SDK集成苹果实现本地通知。
极光推送的实现原理
通过我们的App服务器或极光Web端调用极光的API能发起极光推送。
换言之,开发过程中,登录账号后,将userId(setAlias)绑定到RegistrationID。然后在iOS端发起一个网络请求到App服务器后(通过目标userId可知 推送目标registrationId),由后台调用极光API。另外我们还能通过极光Web端调试,如下图。
(笔者的亲身体验!!!)iOS开发调试时,尽量用Web调用调用API。因为我们不知道后台的代码(如果后台在推送上也是个新手,推送环境或者推送配置字段弄错了,我们这半天也收不到推送。。。 )。当然,最后还是要测试一遍发请求给后台推送正不正常。
- 关于自定义消息的原理。
极光采用的是长连接。所以自定义消息在网络正常、App处于前台的情况下会马上收到。
- 关于通知(APNs)的原理
举个例子,用户A(userIdA)发消息给用户B(userIdB)。这里只考虑两个都绑定好了deviceToken等,不存在离线消息。
在苹果原生态下的流程图。
在极光下的流程图。
后台服务器瘦身。
极光推送的使用
通知
- iOS7以后的机型实现这些方法
1. - (void)jpushNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(NSInteger options))completionHandler; 2. - (void)jpushNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)())completionHandler; 3. - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler NS_AVAILABLE_IOS(7_0); 4. - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification; 复制代码
方法一:iOS10+ 点击推送调用。
方法二:iOS10+ App前台 收到推送调用。
方法三:iOS10+ ,收到静默推送或者后台推送调用。
方法三:iOS7+,iOS10-,前后台收到任何远程类型推送调用。
方法四:iOS7+ ~ iOS10-,收到本地推送调用。
应用内消息
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [defaultCenter addObserver:self selector:@selector(receivePushMessage:) name:kJMSGNetworkDidReceiveMessageNotification // 收到自定义消息 object:nil]; return YES; } // 收到自定义消息 - (void)receivePushMessage:(NSNotification *)notification { NSLog(@"Event - 收到自定义消息"); NSDictionary *info = notification.userInfo; if (info) { NSLog(@"The message - %@", info); } else { NSLog(@"Unexpected - 没有用户信息no user info in jpush mesasge"); } // 弄个 工具 类处理 // [PushUtil handleNotification:info]; } 复制代码
极光IM
官方文档里,极光推送就是亲生的,IM充话费送的。
官方开发指南并不够友好,给到的信息少之又少,连基本的通讯都没说清楚,SDK Reference可读性又差。OC版示例项目也好久不更新了,笔者又需要用OC。。。网上相关的资料也难查。
笔者想要的效果是账号用App服务器账号,不额外新建一个。
下面就记录笔者的研究成果。
接口Code的定义查看官方文档,本文不处理。 IM SDK ErrorCode 定义
极光IM注册
(默认用userId当IM账号密码)。
NSString *userId = @"Hsusue1"; [JMSGUser registerWithUsername:userId password:userId completionHandler:^(id resultObject, NSError *error) { NSLog(@"%@-----%@", resultObject, error); }]; 复制代码
注册成功,resultObject值为success。
如果已经注册过这个账号,回调的error会显示以下内容。
极光IM登录
[JMSGUser loginWithUsername:userId password:userId completionHandler:^(id resultObject, NSError *error) { NSLog(@"%@-----%@", resultObject, error); // 查看自己IM的个人信息 //JMSGUser *user = [JMSGUser myInfo]; }]; 复制代码
因为App账号采用后台的(包括个人信息),不确定这个账号有没有注册过极光IM,所以每次登录IM前都要发起注册。所以笔者采用以下代码,调用一系列接口。
[JMSGUser registerWithUsername:userId password:userId completionHandler:^(id resultObject, NSError *error){ DLog(@"error code = %ld",(long)error.code); [JMSGUser loginWithUsername:userId password:userId completionHandler:^(id responceObject, NSError *error){ NSLog(@"%@-----%@", resultObject, error); // 查看自己IM的个人信息 //JMSGUser *user = [JMSGUser myInfo]; //把App的个人信息(昵称等等)更新到IM JMSGUserInfo *userInfo = [[JMSGUserInfo alloc] init]; userInfo.nickname = @"nickname"; userInfo.gender = kJMSGUserGenderFemale; [JMSGUser updateMyInfoWithUserInfo:userInfo completionHandler:^(id resultObject, NSError *error) { NSLog(@"%@-----%@", resultObject, error); }]; }]; }]; 复制代码
另外,后台账号修改密码时,记得顺便修改IM密码。
IM发送消息
注意此处会发送推送和应用内消息。
// 对方的Id NSString *targetId = @"hsusue"; JMSGTextContent *textContent = [[JMSGTextContent alloc] initWithText:@"textContent"]; JMSGMessage *message = [JMSGMessage createSingleMessageWithContent:textContent username:targetId]; [JMSGMessage sendMessage:message]; 复制代码
发送的推送如下
发送结果回调在代理方法中
注意这里,是add,不是set。意味着只要实现了代理方法的target,都会调用。
- (void)viewDidLoad { [super viewDidLoad]; // nil表示所有会话的回调都接收 [JMessage addDelegate:self withConversation:nil]; } - (void)onSendMessageResponse:(JMSGMessage *)message error:(NSError *)error { NSLog(@"%@-----%@", message, error); } 复制代码
IM接收消息
也是在代理方法中(推送调用的方法此处不再介绍)。
- (void)onReceiveMessage:(JMSGMessage *)message error:(NSError *)error { NSLog(@"%@-----%@", message, error); } 复制代码
在这里可以判断消息所属类型,笔者发送了文本消息测试。
下载媒体文件失败的回调。
- (void)onReceiveMessageDownloadFailed:(JMSGMessage *)message; 复制代码
最近联系人列表 和 聊天记录
极光IM,App本地保存了各个账号的最近联系人列表和聊天记录。
SDK中 JMSGConversation
包含了一堆有用的信息。
这里只列出部分。
获取会话及其他操作
/*! * @abstract 获取单聊会话 * * @param username 单聊对象 username * * @discussion 如果会话还不存在,则返回 nil */ + (JMSGConversation * JMSG_NULLABLE)singleConversationWithUsername:(NSString *)username; /*! * @abstract 删除单聊会话 * * @param username 单聊用户名 * * @discussion 除了删除会话本身,还会删除该会话下所有的聊天消息。 */ + (BOOL)deleteSingleConversationWithUsername:(NSString *)username; /*! * @abstract 返回 conversation 列表(异步,已排序) * * @param handler 结果回调。正常返回时 resultObject 的类型为 NSArray,数组里成员的类型为 JMSGConversation * * @discussion 当前是返回所有的 conversation 列表,不包括聊天室会话,默认是已经排序。 */ + (void)allConversations:(JMSGCompletionHandler)handler; /*! * @abstract 获取当前所有会话的未读消息的总数 * * @discussion 获取所有会话未读消息总数,开启免打扰的会话未读数不会加入计数 */ + (NSNumber *)getAllUnreadCount; /*! * @abstract 同步分页获取最新的消息 * * @param offset 开始的位置。nil 表示从最初开始。 * @param limit 获取的数量。nil 表示不限。 * * @return 返回消息列表(数组)。数组成员的类型是 JMSGMessage* * * @discussion 排序规则是:最新 * * 参数举例: * * - offset = nil, limit = nil,表示获取全部。相当于 allMessages。 * - offset = nil, limit = 100,表示从最新开始取 100 条记录。 * - offset = 100, limit = nil,表示从最新第 100 条开始,获取余下所有记录。 */ - (NSArray JMSG_GENERIC(__kindof JMSGMessage *) *)messageArrayFromNewestWithOffset:(NSNumber *JMSG_NULLABLE)offset limit:(NSNumber *JMSG_NULLABLE)limit; 复制代码
会话对象的属性。
/*! * @abstract 会话标题 */ @property(nonatomic, strong, readonly) NSString * JMSG_NULLABLE title; /*! * @abstract 最后一条消息 */ @property(nonatomic, strong, readonly) JMSGMessage * JMSG_NULLABLE latestMessage; /*! * @abstract 会话最近一条消息的创建时间 * * @discussion 可用于会话排序,单位为毫秒 */ @property(nonatomic, strong, readonly) NSNumber *latestMsgTime; /*! * @abstract 未读数 * @discussion 有新消息来时, SDK 会对未读数自动加 1 */ @property(nonatomic, strong, readonly) NSNumber * JMSG_NULLABLE unreadCount; ///-------------------------------------------------------- /// @name Conversation Extend Properties 会话扩展属性:用于聊天 ///-------------------------------------------------------- /*! * @abstract 会话类型 - 单聊,群聊,聊天室 * @discussion 详细定义见 JMSGConversationType */ @property(nonatomic, assign, readonly) JMSGConversationType conversationType; /*! * @abstract 聊天对象 * * @discussion 需要根据会话类型转型。单聊时转型为 JMSGUser,群聊时转型为 JMSGGroup,聊天时转型为 JMSGChatRoom * * 注意: 在会话列表上, 请不要使用此属性, 否则有性能问题. 只在进入聊天界面(单个会话) 时使用此属性. * * 进入会话(聊天界面)后, 访问会话对象的各种信息, 包括群聊的群组成员, 都应使用此属性, * 而没有必要再通过接口查询 UserInfo / GroupInfo / ChatRoomInfo. */ @property(nonatomic, strong, readonly) id target; /*! * @abstract 会话目标用户所在的 appKey * * @discussion 这是为了跨应用聊天而新增的一个字段. * 如果此字段为空, 则表示为默认的主应用. * * 单聊会话时, 如果单聊对象用户不属于主应用, 则此字段会有值. * */ @property(nonatomic, strong, readonly) NSString *targetAppKey; 复制代码
看完这些能基本掌握它们的原理,但在推送和UI层上仍存在不少难度。
比如,消息发送失败在聊天界面展示红色的感叹号这个功能。在*iOS 极光IM 集成之旅有探讨。
极光也推出了IMUI,github地址: Aurora IMUI
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Thinkphp之极光推送
- iOS极光推送原理
- 给APP接入极光推送:后端(PHP)
- Match开发笔记 肆 极光推送接入指南(Swift版)
- 极光推送之Android客户端使用指南--基础篇
- ApiCloud开发SuperWebView——极光推送不能监听通知内容以及不能跳转的问题
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。