集成相关
更新时间: 2024/06/24 10:56:00
本文介绍集成 NIM SDK 和登录 IM 过程中,可能遇到的问题及其解决方案。
为什么 IM 登录失败并返回 302 错误码?
302 表示账号密码错误,即登录时传入的 AppKey、accid、Token 三者不匹配,可能的原因包括但不限于:
原因一:AppKey 与 accid 不匹配
-
判断 accid 是否正确:
调用 IM 服务端 API 注册云信 IM 账号时,网易服务器会将 accid 统一小写处理,请以响应体返回的
accid
为准。 -
判断 accid 是否存在:
您可以调用服务端 API 获取用户名片 测试 accid 是否存在。传入您需要查询的 accid,若 code 返回 200 则说明该 accid 存在;若 code 返回 414,desc 返回 "... not register" 则说明该 accid 不存在。
原因二:accid 与 Token 不匹配
-
调用 SDK 登录方法时,调试打印传入的
accid
和token
,检查是否与注册云信账号后服务器中的信息一致。 -
如果 Token 过期,则调用 IM 服务端 API 刷新Token 重置。
- 指定 Token:传入用户指定的 token,请求成功后,服务器更新 token。
- 不指定 Token:不传入指定 token,由网易云信服务器随机生成 token 并返回给开发者。
为什么自动登录失败并返回 417 错误码?
- 在设备上第一次登录时,必须手动登录,包括新装 app,以及卸载后重新安装 app,否则会返回 417。
- 主动登出或注销账号后,再次登录时必须手动登录,不能使用自动登录,否则返回 417。
- 非强制模式下的自动登录,服务器会检查当前登录设备是否为上一次登录的设备,如果不是,服务器将拒绝本次自动登录,并返回 417。
- 如果未配置「各端均可以同时登录在线」,假设某账号在设备A 上登录后,又在设备B 上登录,此时如果手机A 再自动登录会返回 417,因为当前登录设备并非上一次登录设备。 关于多端登录的配置和说明,请参见 多端登录与互踢。
SDK 返回 417 后,开发者必须手动登录。如果继续自动登录,将持续失败,且不再返回失败原因。
如何判断 IM 登录成功?
- 手动登录:
调用
login
方法登录时,判断是否触发onSuccess
回调。 - 自动登录:
调用
observeOnlineStatus
注册在线状态变化回调,监听当前账户登录状态的变化。
- 手动登录:
调用
login
方法登录时,判断error == nil
表示登录成功。 - 自动登录
注册NIMLoginManagerDelegate.–onLogin:
回调监听当前账户登录状态的变化。
- 手动登录:
调用
Login
方法登录时,在回调函数LoginCallback
中,判断LoginRes
:其中login_step_
值为kNIMLoginStepLogining
且res_code_
为kNIMResSuccess = 200
表示登录成功。 - 自动登录: 与手动登录一致。
- 手动登录:
调用
NIM.getInstance
方法初始化 SDK 时,SDK 会自动登录,判断是否出发onConnect
回调。 - 自动登录: 与手动登录一致。
如何判断 IM 账号处于非登录状态?
调用 observeOnlineStatus
注册在线状态变化观察者来监听用户在线状态:自动登录失败回调 UNLOGIN
、被其他端的登录踢掉回调 KICKOUT
等。
实现 NIMLoginManagerDelegate
的 –onLogin:
回调获取登录状态。
- 自动登录失败也会触发
-onAutoLoginFailed:
回调获取登录状态。 - 被踢会触发
-onKick:clientType:
回调。
注册客户端掉线回调 nim_client_reg_disconnect_cb
、自动重连回调 nim_client_reg_auto_relogin_cb
、客户端被踢回调 nim_client_reg_kickout_cb
。
调用 NIM.getInstance
方法初始化 SDK 时,配置 ondisconnect
回调函数,此回调会收到一个对象,包含 code
字段,若为 kicked
表示被踢,该字段可能为空。
如何获取用户在线状态(登录登出信息)?
在线状态事件订阅
详见在线状态订阅开发文档。
登录登出消息抄送
在云信控制台开通和配置消息抄送服务后,云信服务器会将登录登出事件抄送到开发者配置的接收地址上。关于登录登出消息抄送功能,请参考IM 其他抄送。
通过服务端 API 查询
在云信控制台开通 IM 即时通讯的全局功能 > 登录登出事件记录查询功能后,调用服务端 API 用户登录登出事件记录查询,请注意无法查询开通之前的历史记录。
注意事项
- 事件订阅是网易服务器通知客户端 SDK,消息抄送是网易服务器通知开发者应用服务器,查询 API 是开发者主动调用查询。
- 如果超时断开连接,但是推送可达,则不会触发该用户断开连接的在线状态事件,但是会触发该用户登出的消息抄送。
- 如果使用消息抄送功能来实现在线状态,需要注意登录登出消息抄送并不一定成对出现,可能出现乱序或丢失,因此,需要解析登录登出消息抄送的时间戳字段
timestamp
并将其维护为在线状态时间戳,如果新到达的登录登出消息抄送时间戳小于已保存的在线状态时间戳,则需要忽略新到达的登录登出抄送。
SDK 会实时更新用户资料吗?
SDK 会将用户资料缓存到本地,并实时更新当前用户资料,但不保证其他用户的资料实时更新。
其他用户资料更新时机为:
- 登录时同步好友信息(同步完成会发出通知)
- 收到其他用户发来的消息(如果消息发送者有资料变更,SDK 会更新并发出通知)
- 调用接口从服务器获取用户资料
SDK 更新用户资料完成的回调说明如下:
调用 observeOnlineStatus
注册在线状态变化观察者来监听用户在线状态:自动登录失败回调 UNLOGIN
、被其他端的登录踢掉回调 KICKOUT
等。
实现 NIMLoginManagerDelegate
的 –onLogin:
回调获取登录状态。
- 自动登录失败也会触发
-onAutoLoginFailed:
回调获取登录状态。 - 被踢会触发
-onKick:clientType:
回调。
注册客户端掉线回调 nim_client_reg_disconnect_cb
、自动重连回调 nim_client_reg_auto_relogin_cb
、客户端被踢回调 nim_client_reg_kickout_cb
。
调用 NIM.getInstance
方法初始化 SDK 时,配置 ondisconnect
回调函数,此回调会收到一个对象,包含 code
字段,若为 kicked
表示被踢,该字段可能为空。
- 登录时会同步好友信息(同步完成会发出通知)
通过 observeLoginSyncDataStatus
注册登录后数据同步状态通知。
通过 onLogin
接收登录状态回调,NIMLoginStepSyncing
表示同步数据开始,NIMLoginStepSyncOK
表示同步数据完成。
通过 nim_friend_reg_changed_cb
全局注册好友变更通知回调函数,回调函数 nim_friend_change_cb_func
中,参数 type
表示数据变化类型 NIMFriendChangeType
,参数 result_json
表示同步内容。
通过 var nim = NIM.getInstance({onsyncdone: onSyncDone})
设置同步完成回调函数。
- 收到其他用户发来消息(如果消息发送者有资料变更,SDK 会负责更新并发出通知)
通过 observeUserInfoUpdate
注册用户资料变更观察者通知。
实现 NIMUserManagerDelegate
的 onUserInfoChanged
回调,包含 NIMUser
对象。
通过nim_user_reg_user_name_card_changed_cb()
全局注册用户名片变更通知回调函数,回调函数nim_user_name_card_change_cb_func
中参数result_json
表示用户名片Json Keys Array。
通过 var nim = NIM.getInstance({..., onupdateuser: onUpdateUser})
设置用户名片更新回调函数。
- 调用接口从服务器获取用户资料
通过 fetchUserInfo
方法从服务器获取指定用户资料。
通过 fetchUserInfos
方法从服务器获取指定用户资料。
调用 nim_user_get_user_name_card_online
传入 accids
,设置回调函数 nim_user_get_user_name_card_cb_func
。
- 获取用户资料:
nim.getUser
,可以传入参数sync: true
来强制从服务器获取最新数据。 - 获取用户资料数组:
nim.getUsers
,可以传入参数sync: true
来强制从服务器获取最新数据。
如何通过 SDK 接口订阅用户在线状态?
允许用户订阅其他人发布的事件,当被订阅人发布事件后,订阅者可以收到相应的通知。目前支持在线状态事件订阅,对特定账号的登录登出事件进行通知。该功能需要在云信控制台进行开通。非好友也可以订阅在线状态。
- 每次调用接口最多只能订阅 100 个账号,数量较多时需多次调用。有效订阅账号不能超过 3000 个。
- 订阅有效期为 60 - 2592000(即 60 秒到 30 天),过期后需要重新订阅。如果未过期的情况下重复订阅,新设置的有效期会覆盖之前的有效期。
- 在线状态事件会受推送的影响:如果推送可达,默认标记该账号为在线状态(不会触发该用户断开连接的事件)。如需更改上述默认行为,请至云信控制台IM 即时通讯 - 全局功能 - 在线状态订阅进行配置。如果没有集成推送,或者推送不可达,则当用户断开连接时,会触发断开连接事件。
- 系统默认的在线状态事件值为:1-登录,2-登出,3-断开连接。
各端配置方法如下:
通过 subscribeEvent
进行订阅,其中 EventSubscribeRequest
为事件订阅请求对象,通过 setEventType
方法设置在线状态事件类型,通过 setExpiry
方法设置订阅有效期,通过 setPublishers
方法设置事件发布者。
- 查询订阅:
querySubscribeEvent
- 取消订阅:
unSubscribeEvent
,如果其中EventSubscribeRequest
的publishers
不填则取消全部订阅。 - 接收订阅:
getService
通过 -subscribeEvent:completion:
进行订阅,其中 NIMSubscribeRequest
为构造的订阅请求对象,其中 type
为 1
表示在线状态事件,expiry
为订阅有效期,syncEnabled
表示是否立即同步状态值,publishers
为事件发布者。
- 查询订阅:
-querySubscribeEvent:completion:
- 取消订阅:
-unSubscribeEvent:completion:
,如果其中NIMSubscribeRequest
的publishers
不填则取消全部订阅。 - 接收订阅:实现
NIMEventSubscribeManagerDelegate
协议的–onRecvSubscribeEvents:
方法。
通过 nim_subscribe_event
方法进行订阅,其中 event_type
表示事件类型,kNIMEventTypeOnlineState = 1
表示在线状态事件,ttl
表示有效期,accid_list_json
表示accid列表,sync_event
表示是否立即同步。
- 查询订阅:
nim_query_subscribe_event
- 取消订阅:
nim_unsubscribe_event
- 取消全部订阅:
nim_batch_unsubscribe_event
- 接收订阅:
- 全局注册接收订阅的事件的回调函数:
nim_subscribe_event_reg_push_event_cb
- 全局注册批量接收订阅的事件的回调函数:
nim_subscribe_event_reg_batch_push_event_cb
- 全局注册接收订阅的事件的回调函数:
通过 nim.subscribeEvent
订阅事件,传入参数 type: 1
,subscribeTime
设置订阅有效期,accounts
设置 accid 数组,sync
设置是否立即同步。
- 查询订阅:
nim.querySubscribeEventsByAccounts
- 取消订阅:
nim.unSubscribeEventsByAccounts
- 取消全部订阅:
nim.unSubscribeEventsByType
- 接收订阅:
NIM.getInstance
,其中onPushEvents
表示注册的回调函数,会收到参数param
,其msgEvents
属性表示推送事件对象数组。
通过在线状态订阅 接口进行订阅,参数 accid
为事件订阅人账号,eventType
为 1
,publisherAccids
为被订阅人的账号列表(JSONArray格式),最多订阅 100 个账号,ttl
为有效期。
该接口的 publisherAccids
参数(被订阅人的账号列表),如果其中包括无效账号,服务器会忽略无效账号,不会将其列在返回的 failedAccid
中。
- 查询订阅:
https://api.netease.im/nimserver/event/subscribe/query.action
- 取消订阅:
https://api.netease.im/nimserver/event/subscribe/delete.action
- 取消全部订阅:
https://api.netease.im/nimserver/event/subscribe/batchdel.action
已订阅在线状态的前提下,为什么登录的时候没有同步对方的在线状态?
订阅者登录时,如果被订阅者是在线的,那么会收到其在线事件回调;但是如果被订阅者是离线的,那么订阅者无法收到其离线事件回调;如果后续被订阅者重新登录,才能触发在线状态事件。
建议登录时在应用层将所有被订阅账号的初始在线状态设置为离线,登录后无论被订阅者是在线,还是从离线变为在线,都能正常触发在线状态回调,再相应更新在线状态即可。
对方是我的好友,但是为什么不显示对方的在线状态?
IM 好友关系和在线状态是两个不同的功能,只添加好友是不会显示对方的在线状态的。注意:
- 好友关系是双向的,一旦添加好友成功,彼此都是对方好友。
- 在线状态事件订阅是单向的,双方需要各自订阅。
为何集成 NIM SDK 失败?
排查方式
- 更换设备进行对比测试。
- 编译并运行官方的 Demo 进行对比测试。
- 如果是网络相关问题,更换网络类型(4G/WiFi/有线网络)进行对比测试。
联系技术支持
如果问题可复现,请提供以下相关信息:
-
你的设备信息
- Windows:操作系统版本
- Android:品牌、机型、安卓系统版本、厂商系统版本(设置 > 关于手机)
- iOS:机型、系统版本(设置 > 通用 > 关于手机)
- Web:浏览器版本
-
Demo 或 SDK 的类型和版本号
-
问题的触发条件、操作步骤、接口调用顺序等
-
问题相关的程序代码、报错信息、错误日志、时间节点。
为何返回 408 连接超时?
错误码 408 表示客户端 SDK 收到回包超时,即发出请求包后,在一定时间内判断为没有收到对应的回包。可能的原因包括但不限于:
- 网络异常:检查或更换网络进行对比,例如切换 WIFI/有线/4G/5G 网络。
- 操作错误:客户端未登录时调用 SDK 接口导致无法收到回包。
- 参数错误:调用接口时传入了错误的参数导致连接异常。
- 并发处理:客户端已经收到回包,但是还有大量前序包未处理完造成超时。
- 旧版适配问题:Android SDK 4.3.0 及之前的版本,没有对于 Android 8.0 以上系统版本的适配,请更新SDK。
- iOS 端 rsa key 配置不对导致登录出错。
- 实现动态登录,
getToken
方法请求超时,或没有配置请求的情况下,登录会超时。
为何返回 415 错误码?
415 表示客户端和服务器建立连接失败,一般是调用登录方法时出现。可能的原因包括但不限于:
- 用户开启了 VPN 或者修改了本地 HOST,导致无法解析或者获取到错误的连接地址。
- 由于 DNS 缓存等原因导致 SDK 获取到错误的服务器 IP(例如已下线或维护中的服务器)。
- 用户的防火墙拦截了连接请求,请更换 4G/5G 网络或热点进行对比。
- 旧版 SDK 不支持 IPv6 ,请升级到最新版本 SDK。
为何返回 414 错误码?
可能的原因包括但不限于:
- 如果在云信控制台应用配置 > 标识管理,选中了进行标识安全验证:当请求登录的客户端App标识不在以上列表中时,登录请求将被拒绝,当客户端标识(iOS Bundle Identifier / Android Package Name)不在配置的列表中,登录会返回 414。
- Android 端:没有在清单文件配置 Appkey,导致登录失败返回 414。 注意在控制台配置标识管理时,标识之间用英文逗号隔开,不要按换行键,否则将导致无法匹配。
- Windows 端:进入聊天室返回 414,如果设备 ID(device uuid) 出现乱码,请删除
C:\\ProgramData\\NeteaseWinDev
目录后重试。
为何返回 509 错误码?
可能的原因包括但不限于:
- 已登录的状态下,重复调用登录接口。
- 登录报错密码错误后,使用相同数据再次登录。
怎么删除 SDK 缓存文件?
- 调用
getSizeOfDirCache
方法获取缓存文件大小。 - 调用
clearDirCache
删除指定类型的缓存文件。
- 调用
–searchResourceFiles:completion:
方法搜索缓存的资源文件。 - 调用
–removeResourceFiles:completion:
方法删除缓存的资源文件。
执行搜索方法后,日志会记录:start search cache in path
;执行删除方法后,日志会记录:start clean cache path
。
- 调用
nim_global_get_sdk_cache_file_info_async
方法获取缓存文件信息。 - 调用
nim_global_del_sdk_cache_file_async
方法删除缓存文件。
调用 nim.destroy
方法删除实例缓存。
SDK 打印日志会影响设备性能吗?
SDK 对日志打印进行了针对性的优化,不会占用过多资源,对设备性能影响不大。已经打印的日志不被访问,没有IO读写,不会影响性能,SDK也会定期清理。
同类日志打印到同一份文件中,大小不超过 24MB;一旦大于 24MB 会裁剪并舍弃最早的日志,保留最新的8MB。
Android 打印日志分为普通 IO、高性能 MMAP 内存映射两种模式。
- 默认为普通模式,采用独立线程打印日志,写文件会做缓冲区,对性能影响不大;
- 开发者可以将
SDKOptions
的useXLog
参数设置为true
来启用高性能模式。
iOS 日志文件清理周期默认为 7 天。
可通过 [[NIMSDKConfig sharedConfig] setMaximumLogDays: days]
设置大于等于 2 的天数。
Windows 端的日志达到 8MB 仅保留最新的 4MB,无法指定保存大小。
如何解决报错:java.lang.UnsatisfiedLinkError: Can not load ... library?
SDK 没有针对模拟器的兼容性测试,如果使用模拟器出现类似报错,请更换真机调试运行。如果已经使用真机,请继续查看下文。
1. 确认是否已经正确地导入 SDK 文件
- 必须导入同一个 SDK 包中的 jar 和 so 文件,以确保版本一致。
- 每种架构目录下的 so 文件都是不一样的,需要分别导入。不能将同一份 so 文件用于不同的架构下。
2. 检查 jniLibs.srcDirs
在对应 Module 的 build.gradle
文件中,应配置 android > sourceSets > main > jniLibs.srcDirs 和 SDK 文件的路径一致,例如:
gradleandroid {
...
sourceSets {
main {
jniLibs.srcDirs = ['jniLibs']
}
}
}
3. 检查 abiFilters
如果在 build.gradle
文件中配置了 abiFilters
,应包含对应的架构,例如:
gradledefaultConfig {
ndk {
abiFilters "armeabi", "armeabi-v7a", "arm64-v8a", "x86"
}
}
4. 检查 packagingOptions
如果在 build.gradle
文件中配置了 packagingOptions
,请注意不能把 SDK 文件 exclude。例如下列是错误配置。
gradleandroid {
packagingOptions {
exclude 'lib/x86/....so'
exclude 'lib/x86_64/....so'
exclude 'lib/armeabi-v7a/....so'
exclude 'lib/arm64-v8a/....so'
}
}
5. 检查代码混淆
如果使用代码混淆,请保持 SDK 代码不被混淆,例如,应配置:-keep class com.netease.** { *; }
。
6. 检查动态加载
如果使用动态加载,需要等到动态加载完成才能调用相应接口。
例如,对于 Android 播放器,调用 init
方法初始化播放器以后,需要等待 onDynamicLoadingListener
动态加载完成回调,才能调用 create
方法创建播放器实例。
如何解决报错:More than one file was found with OS independent path 'assets/nim_keystore'?
问题原因是重复导入 SDK。例如:同时使用了 Gradle 集成和类库集成 SDK(使用其中一种即可),导入 UIKit 后重复导入 SDK(UIKit模块已包含SDK基础库)。
如何解决报错:core: load public key error / java.io.FileNotFoundException: nim_keystore?
可能的原因如下:
-
在
build.gradle
文件中错误地配置排除了 SDK 的 keystore,例如:groovy
android { packagingOptions { exclude 'assets/nim_keystore' } }
如果有此类配置,请删除。
如果没有排除 SDK 的 keystore,请手工添加缺失的
nim\_keystore
文件,方法如下:将 SDK 的
nim-basesdk-x.y.z.jar
解压,得到一个 assets 文件夹,其中包含nim\_keystore
和nim\_keystore2
两个文件:- 对于 Android Studio:将上述两个文件添加到主 Module 的 `src/main/assets` 里。 - 对于 Xamarin:将上述两个文件添加到 Assets 里面,另请参考:[Using Android Assets](https://docs.microsoft.com/en-us/xamarin/android/app-fundamentals/resources-in-android/android-assets?tabs=vswin)。
-
SDK 版本低于 v4.4.0:
- v4.4.0 以下的 SDK 版本,在 Android 8.0 以上的系统中,可能由于兼容性问题出现无法加载 keystore 的情况。如果开发者集成的 SDK 版本低于 v4.4.0,请更新到线上最新版本。
- Android Studio 2.X 版本的兼容性问题。解决方法:Android Studio > File > Settings 中搜索 Instant Run,取消选中 Enable Instant Run ... >,点击 OK 按钮保存。
如何解决报错:java.lang.NullPointerException: texImage2D cann't be used with a null Bitmap?
-
导入
lib/assets
文件夹。 -
确认主模块
build.gradle
文件中,sourceSets/main
配置的assets.srcDirs
路径是否和实际一致。
iOS SDK 如何对 app 角标赋值?
方式一 APNs 推送自动赋值
如果收到消息的时候 app 在后台,则 iOS 系统根据 APNs 推送的 badge
字段的数值自动对 app 角标进行赋值(该数值等于 IM 服务器记录的该账号的总未读数);如果收到消息时 app 在前台,则不会对角标赋值。
方式二 iOS 系统方法赋值
App 从前台切换到后台时,调用 iOS 系统方法 setApplicationIconBadgeNumber
赋值给角标,示例代码:
[application setApplicationIconBadgeNumber:unreadCount]
例如:app 在后台收到一条消息,此时 app 的角标会变成 1;app 回到前台,会话的总未读数是 1,此时又收到一条消息,会话的总未读数变成 2。当 app 再次切到后台时,开发者应调用 iOS 系统方法给角标赋值为2。
注意事项:
-
如果需要清除 SDK 所有会话的未读数,可以调用
-markAllMessagesRead
方法。 -
如需自定义配置 iOS 应用角标未读数上限,请至云信控制台 IM 即时通讯 > 基础功能 > iOS 应用角标未读数上限进行配置。
为什么 iOS 端无法显示头像?
IM iOS SDK 的 NIMUserInfo
对象包含 avatarUrl
和 thumbAvatarUrl
两个属性,前者表示用户头像,后者表示用户头像缩略图(仅适用于通过 IM 用户资料托管上传到网易云信服务器的头像,否则无效)。SDK 默认会将 url 转换为 HTTPs。
如果开发者用户资料的头像 url 不是云信服务器提供的,请按以下步骤调整:
-
如果开发者存放头像 url 的服务器不支持 HTTPs,请配置取消 HTTPs 转换。
-
如果开发者是通过 SDK 方法来获取头像缩略图的,请注意头像缩略图属性
thumbAvatarUrl
不支持非网易服务器的 url,所以请只使用avatarUrl
属性。 -
如果开发者是通过 UIKit 方法来获取头像 url,请参考 UIKit 文档。UIKit 提供一个
NIMKitDataProvider
协议实现类,在提供头像 url 时使用NIMUserInfo
对象的avatarUrl
属性,而不要使用thumbAvatarUrl
属性。
向 IM iOS SDK 传入 HTTP 地址,为何 SDK 收到的是 HTTPs 地址?
iOS SDK有相关配置项。具体如下:
NIMServerSetting | NIMSDKConfig | 上传/发送消息 | 下载/接收消息 |
---|---|---|---|
setting.enabledHttps = YES |
\[NIMSDKConfig sharedConfig\].enabledHttpsForInfo = YES ; \[NIMSDKConfig sharedConfig\].enabledHttpsForMessage = YES |
HTTPs | 返回 url HTTP url转换为 HTTPs url。 |
setting.enabledHttps = YES |
\[NIMSDKConfig sharedConfig\].enabledHttpsForInfo = NO ; \[NIMSDKConfig sharedConfig\].enabledHttpsForMessage = NO ; |
HTTPs | 返回原 url,不做转换。 |
setting.enabledHttps = NO |
enabledHttpsForInfo 和 enabledHttpsForMessage 无效 |
HTTP | 返回原 url,不做转换。 |
在 iOS11 上发送相机拍摄的图片,为什么消息接收方无法显示?
iOS11 采用了新的图片格式 HEIC (全称为 High Efficiency Image File Format,文件格式为 .heic),只有 iOS11 或 High Sierra 版本的 macOS 才支持打开。如果采用原图发送,其它设备会因兼容性问题导致接收方无法显示。解决办法如下:
-
选择iPhone > 设置 > 相机 > 格式 > 兼容性最佳,拍摄的照片会保存为 JPG 格式。
-
如果发送 .heic 格式的图片,不要发送原图,发送前通过 SDK 进行压缩(默认会压缩为 JPEG 格式,可选 JPEG 和 PNG)。示例代码如下:
NIMImageObject \*imageObject = \[\[NIMImageObject alloc\] initWithImage:image\]; NIMImageOption \*option = \[\[NIMImageOption alloc\] init\]; option.compressQuality = 0.7; imageObject.option = option;
关于
NIMImageObject
类的NIMImageOption
属性,请参见 API 参考文档。
如何解决报错:事件服务解包失败?
IM Web Demo 或微信小程序 Demo 中,如果开发者将 Demo 的 AppKey 修改为自己的 AppKey 后,可能出现报错:{message: "事件服务解包失败", code: "事件服务解包失败"}
。
问题原因
应用未开通在线状态事件订阅功能。
解决方案
控制台开通在线状态事件订阅
登录云信控制台,在IM 即时通讯 > 全局功能 > 在线状态订阅开启该功能。
关闭相关配置
关闭 Demo 配置项:
- Web Demo:将
webdemo/im/js/config.js
中window.CONFIG.openSubscription = true
修改为false
。 - 微信小程序 Demo:将
config/envConfig.js
中ENVIRONMENT_CONFIG.openSubscription = true
修改为false
。
为什么收不到 IM Android SDK 的回调?
调用登录接口 NIMClient.getService(AuthService.class).login(info).setCallback(callback)
时收不到 onSuccess
、onFailed
、onException
回调。
可能的原因包含但不限于:
-
权限错误
请参考权限与组件仔细检查核对权限配置部分。
-
进程错误
NIMClient.init
和NIMClient.config
方法必须在所有进程中调用,因此请参考初始化开发指南配置自定义的 Application,并在onCreate
中配置以下接口:- `NIMClient.init`:在 Application 中初始化 SDK - `NIMClient.config`:在 Application 中配置 SDK,在其他位置初始化
如果集成了 UIKit,必须进行主进程判断,例如:
NIMUtil.isMainProcess(this)
,具体请参考即时通讯 Demo 源码。 -
application 未能创建成功
请检查你的app是否出现此类报错:
Unable to create application ...: java.lang.RuntimeException: ...
。 -
applicationId(应用ID)或package(软件包名称)配置不正确
如果工程主模块的 build.gradle 文件中配置了
applicationId
,并且与AndroidManifest.xml
中配置的package
属性不同,构建工具会用applicationId
替换package
,具体请参考 Google官方文档。 -
未正确配置各种广播接收器
请参考即时通讯 Demo 中,demo、avchatkit(音视频)、rtskit(互动白板)模块的
AndroidManifest.xml
中配置的各种receiver
。
如何解决报错 ld: symbol(s) not found for architecture arm64/armv7/i386/x86\_64
?
-
检查有没有导入相应的库文件;
-
检查 Xcode 配置,在 Build settings > Architectures > Valid Architectures 中,是否配置对应的架构支持;
-
在 Build settings > Other Linkers Flags 中,增加
-all\_load
选项,查看是哪些库文件冲突。
如何解决报错 stop reason = signal
?
在 SIGPIPE main.m
文件中,添加以下代码:
objective-csignal(SIGPIPE, SIG_IGN);
int main(int argc, char * argv[]) {
@autoreleasepool {
signal(SIGPIPE, SIG_IGN);
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
由于网络中断等原因,Socket 断开,继续发送数据的话系统会抛出 SIGPIPE 信号,默认处理方法是显示提示信息,终止并退出程序。为了避免这种情况,可以设置 SIG_IGN 忽略信号处理函数 signal(SIGPIPE, SIG_IGN)
,这样产生 SISPIPE 信号时就不会终止程序,而是直接把这个信号忽略掉。
如何解决报错 Error Domain=NIMLocalErrorDomain Code=1 "错误的参数"
?
表示参数错误,包括参数类型错误。
例如,进入聊天室 –enterChatroom:completion:
需要传入的 roomId
类型为 NSString
,如果传入 long
类型会导致错误。
如何解决报错 Error Domain=NIMLocalErrorDomain Code=14
?
问题描述
AppKey 缺失,未注册 AppKey 就进行登录行为之类的接口。
解决方案
Swift 初始化需要使用 NIMSDK.shared()
来确保 SDK 全局单例。
let sdk = NIMSDK.shared()`
传入 appKey
等 NIMSDKOption
参数。
sdk.register(with: NIMSDKOption(appKey: "...", apnsCername: "..."))
关于 IM Web SDK 的浏览器数据库兼容性问题
问题描述
IM Web SDK 底层使用 indexedDb 作为数据库存储。但有些特定浏览器不支持数据库,或兼容性不好,可能会出现数据获取失败。
解决方案
- 通过
NIM.support.db
或SDK.support.db
(返回值true/false
) 来判断 SDK 在该浏览器上是否支持数据库。 - 初始化时配置
var nim = NIM.getInstance({..., db: false });
来禁用数据库。
场景问题
-
调用
nim.getTeam
方法获取群资料时,获取不到validToCurrentUser
字段。原因:只有在浏览器支持的情况下,SDK才能在
onteams
回调时把该字段存入数据库,调用nim.getTeam
方法时再读取出来。 -
某些 Web 浏览器和微信小程序,退出登录后,下次登录时无法显示历史会话。
建议禁用数据库,并打开漫游消息,下次登录时,通过漫游消息的方式重新读取最近的历史消息,以便重构会话列表。 收到漫游消息时,会触发onroamingmsgs
回调;生成会话后,会触发onsessions
回调。
如何解决报错 java.lang.RuntimeException: Unable to get provider ...: java.lang.ClassNotFoundException: Didn't find class"..." on path: DexPathList...
java.lang.RuntimeException: Unable to get provider ...: java.lang.ClassNotFoundException: Didn't find class"..." on path: DexPathList[[zip file "..."],nativeLibraryDirectories=[/data/app-lib/...-1, /vendor/lib, /system/lib]]`?
解决方案
首先,必须确保已经正确地导入和配置 jar 包及 so 库,以使其参与编译和运行。
如已确认,再查看下列步骤。
- 在对应 Module 的 build.gradle > android > defaultConfig 中添加
multiDexEnabled: true
。
groovyandroid {
...
defaultConfig {
...
multiDexEnabled: true
}
}
- 如果 app 使用继承 Application 的类,需重写
attachBaseContext()
方法并调用MultiDex.install(this)
。
javapublic class XXX extends Application {
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
}
微信小程序如何退出/切换聊天室?
- 如果直接退出聊天室,请调用
chatroom.disconnect
。 - 如果切换不同的聊天室,请调用
chatroom.destroy
清除之前的聊天室实例后再初始化新的聊天室。
如何解决微信小程序中报错 wx::ws: onclose {code: 1006, reason: "abnormal closure"}
?
问题描述
这是由于微信底层异常断开 WebSocket 连接导致,IM Web SDK 无法控制此类异常。
对于 WebSocket,code 1006表示连接非正常关闭,具体可参考:MDN。
问题原因
如果修改 AppKey 后,没有去除对 token 的 md5 加密,使用开发者自己的 accid 和 token 登录时,SDK 会返回 302,微信小程序会返回 1006 错误码。
解决方案
将 controller/im.js
中 token: MD5(headers.token)
修改为 token: headers.token
。
如果不是上述情况,开发者可以考虑在出现 1006 异常之后,在收到 IM Web SDK 的 onWillreconnect
(即将重连的回调)后调用 nim.disconnect
接口登出 SDK,并在该接口的 done
回调中调用 nim.connect
登录 SDK。
nim.disconnect({ done: () => { nim.connect() } })
为何体验版小程序无法收发图片、音频、视频等文件消息?
小程序分为开发版、体验版、正式版。体验版小程序没有配置域名白名单,会出现无法收发文件消息的情况。但是如果打开Console就能收发,是因为调试模式不会进行域名白名单校验。
如何解决报错 java.util.ServiceConfigurationError: An SPI class of type org.apache.lucene.codecs.PostingsFormat with classname org.apache.lucene.codecs.lucene50.Lucene50PostingsFormat does not exist
?
如果开发者的 apk 最终会经过代码混淆,请在 proguard 配置文件中加入以下代码:
-dontwarn org.apache.lucene.\*\* -keep class org.apache.lucene.\*\* {\*;}
如何解决报错 Fatal Exception: android.app.RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground()
?
Android 8.0 对特定函数做出了以下变更:
新的 Context.startForegroundService()
函数将启动一个前台服务。现在,即使应用在后台运行,系统也允许其调用 Context.startForegroundService()
。不过,应用必须在创建服务后的五秒内调用该服务的startForeground()
函数。
报错原因
对于 IM SDK 和开发者 app 而言,UI 进程负责展示包括通知栏消息提醒在内的用户界面,而 SDK 的后台进程(假设开发者按照 SDK 集成文档配置为 core 进程或 push 进程,以下简称 core 进程)会进行网络连接、消息收发等工作,并且会和 UI 进程通信。
当 app 切换到后台时,如果 core 进程还存活,但是 UI 进程先被系统回收(此时还能收发消息,但是无法实时展示通知栏提醒);或者当 core 进程无法感知到 UI 进程是否存活时,会尝试调用 Context.startForegroundService
来启动服务 com.netease.nimlib.service.ResponseService
以便唤醒 UI 进程展示通知栏,当 ResponseService
启动后会调用 startForeground
,相关原理请参考 Android文档。
当 UI 进程重新冷启动时,会经过初始化过程,也就是会触发 Application 的 onCreate
,如果开发者的代码逻辑导致 app 总体启动耗时较长,影响 SDK 从 core 进程调用 Context.startForegroundService
开始,到 ResponseService
调用 startForeground
之间的时间,超过 5 秒则会收到此报错。
如果没有第三方的影响,SDK 在上述过程中的平均耗时为 0.5 秒,因此不会由于 SDK 自身原因导致上述报错。
解决方案
自 v6.3.0,支持在初始化 SDK 时配置 SDKOptions.disableAwake
为 true
来禁止后台进程唤醒 UI进程。
如果配置了禁止 core 进程唤醒 UI 进程,那么当 core 进程还存活但是 UI 进程已被系统回收的情况下,SDK 在后台接收到的消息无法通过通知栏展示给用户,只有当 app 恢复前台时,用户才能看到已接收的消息,会影响实时性。因此,上述配置项只是退避措施,如果开发者希望 app 在后台时用户可以收到通知栏消息的话,建议检查优化 app 启动逻辑,例如异步初始化等,确保可以 5 秒内唤醒 UI。
另外,也建议开发者集成消息推送(离线推送),当 core 进程也被系统回收的情况下,可以经由系统通道实时推送消息。
相关答疑
为什么我使用其他服务商的推送没有出现此报错?
推送是使用系统厂商通道,通过系统级Service来触发通知栏,不依赖于app进程。上述报错是 SDK 通过监听新消息到达时为了弹出通知栏提醒出现的,和系统推送原理是不一样的。
如何解决报错 java.lang.NoClassDefFoundError: Failed resolution of: Lcom/coloros/mcssdk/PushManager
?
没有导入 OPPO 推送 SDK,请参考实现离线推送导入指定版本的 OPPO 推送 SDK。
上述报错还可能导致登录接口没有回调。
如何获取网易云信服务器当前时间?
网易云信 IM SDK 提供从客户端向服务器获取时间的接口,接口频控限制为 1秒/次。由于网络上下行的原因,返回的时间会存在一定误差。当接口调用失败或超过频控时返回本地计算结果。
通过调用 queryServerTimeCompletion:
方法。
通过调用 nim.getServerTime({done:(error,time)=>{...}})
方法。
报错:java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
可能原因包括但不限于:
开发者在 StatusBarNotificationConfig.notificationEntrance
中配置的 activity
不存在。
如何解决报错 java.lang.IllegalStateException: SDK not initialized or invoked in wrong process
?
可能原因包括但不限于:
- SDK 尚未初始化就调用其他接口。请先完成初始化。
- 未在主进程调用 SDK 初始化接口。
- 同时使用七鱼 SDK 与云信 SDK 时配置不当。请在初始化七鱼 SDK 时,
YSFOptions
中配置isMixSDK = true
。 - 重复调用初始化接口。
如何主动上传日志?
Android、iOS 有压缩日志的接口,但上传接口不必配合压缩接口使用,调用上传接口的时候会自动压缩打包。如果开启上传任务抄送,服务器会收到相应的日志上传抄送信息。
如何解决报错 NOS\_e: http post exception, status code=799 javax.net.ssl.SSLHandshakeException: Domain specific configurations require that hostname aware checkServerTrusted(X509Certificate\[\], String, String) is used
?
问题原因一
可能是配置了networkSecurityConfig导致的,如果没有特别需求的可以去掉networkSecurityConfig的配置。配置项如下:
// AndroidManifest.xml
<application
android:networkSecurityConfig="@xml/network_security_config">
</application>
// network_security_config.xml
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">c=xx.xxx.com</domain>
</domain-config>
</network-security-config>
问题原因二
在 Android9.0 以上可能部分第三方 SDK 的 HTTP 域名需要配置 networkSecurityConfig
才能访问,这个时候可以删掉 networkSecurityConfig
配置的域名:
为何 iOS 弹窗查找并连接到本地网络上的设备?
iOS 14 新增本地网络设备的隐私权限,需要获取 Local Network Usage Description
权限,才允许访问本地网络设备。而网易云信 IM iOS SDK 自 v8.0.1版本起引入了 traceroute 功能,用于网络连通连接。
建议您在 info.plist
中添加 Privacy - Local Network Usage Description
。
如何解决报错 android.content.pm.PackageManager android.content.Context.getPackageManager()' on a null object reference
?
报错详情:
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.pm.PackageManager android.content.Context.getPackageManager()' on a null object reference on packet: PacketHeader \[SID 2 , CID 2 , SER 2 , RES 200 , TAG 2 , LEN 118\]java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.pm.PackageManager android.content.Context.getPackageManager()' on a null object reference
at com.heytap.mcssdk.of.bt(Unknown Source)
at com.heytap.mcssdk.of.of(Unknown Source)
at com.heytap.mcssdk.of.to(Unknown Source)
at out.to.bt.bt.bt.bt(Unknown Source)
at com.netease.nimlib.mixpush.oppo.a.isFrameWorkSupport(OppoLocalChecker.java:1)
at com.netease.nimlib.mixpush.c.a.isLocalSupport(APlatformLocalChecker.java:1)
at com.netease.nimlib.mixpush.c.e.a(MixPushSuggest.java:3)
at com.netease.nimlib.mixpush.d.a(MixPushCore.java:17)
at com.netease.nimlib.mixpush.d.a(MixPushCore.java:13)
at com.netease.nimlib.mixpush.plugin.MixPushInteract.a(MixPushInteract.java:1)
at com.netease.nimlib.push.a.a.b.d(LoginResponseHandler.java:6)
at com.netease.nimlib.push.a.a.b.c(LoginResponseHandler.java:3)
at com.netease.nimlib.push.a.a.b.a(LoginResponseHandler.java:4)
at com.netease.nimlib.c.b.b$2.run(ResponseDispatcher.java:6)
at com.netease.nimlib.c.b.b.b(ResponseDispatcher.java:5)
at com.netease.nimlib.c.b.b.c(ResponseDispatcher.java:12)
at com.netease.nimlib.c.b.b.a(ResponseDispatcher.java:2)
at com.netease.nimlib.c.b.b$1.run(ResponseDispatcher.java:1)
at com.netease.nimlib.d.b.b$b.run(TaskExecutor.java:2)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:761)
问题原因
com.heytap.mcssdk
类是 OPPO 推送 SDK 中的类。原因是没有在 Application 初始化中调用 com.heytap.msp.push.HeytapPushManager.init(this, true)
接口导致。
解决方案
在 Application 中调用初始化接口即可,详情请参考集成 OPPO 推送。
如何去除 Demo 文件传输 15MB 大小限制?
PC 客户端 Demo 针对文件传输设置了 15MB 的限制,超过 15MB 无法发送,如果开发者通过基于 Demo 进行集成,可通过以下方式对文件大小限制进行调整:
- 在源码目录下用工具搜索指定的关键字内容:
STRID_SESSION_SUPPORT_15MB(表示暂时只支持小于15MB的非空文件)
,正常情况下该字段是在gdstrings.ini
文件中,得到对应的翻译字串。 - 根据
STRID_SESSION_SUPPORT_15MB
字符串找到对应代码进行修改即可,Demo 中有引用该代码的文件为session_box_dragdrop.cpp
和session_box_ui.cpp
,开发者可根据需要进行调整。
如何解决 SDK 日志中打印 database disk image is malformed
?
问题原因
这通常是代表了数据库损坏,可能的原因包括但不限于:
- 之前正在写入数据的时候,app 崩溃导致了 IO 错误。DB 数据出现中间错误的状态。
- 数据中有写入特殊数据,所以导致写入异常,数据库损坏。
解决方案
- SDK 版本低于 v8.6.2,可以选择重装 app。
- SDK 版本高于或等于 v8.6.2,可以通过启用数据库备份,即将
NIMSDKConfig—sessionDatabaseBackupEnabled
设置为YES
。
为何运行 Electron demo 时,执行 yarn install
报错 command failed exit code:1,command:just install
?
可能是网络原因,建议您执行如下步骤:
- 指定 npm 国内镜像。
npm config set registry=https://registry.npm.taobao.org/
- 指定 Electron 的国内镜像地址。
npm config set ELECTRON_MIRROR=https://npm.taobao.org/mirrors/electron/ npm install
如何实现用 Demo 重复登录一个账号?
-
搜索语言文件对应的中文提示对应的翻译常亮字串:
STRID_CHECK_SINGLETON_RUN
(同一PC不允许重复登录同一账号)。 -
代码中搜索指定常亮字串并可以找到关键代码设置为
true
。ShowMsgBox(this->GetHWND(), MsgboxCallback(), L"STRID_CHECK_SINGLETON_RUN", true);
为何 Web 端使用动态 Token 登录时报错 403(非法操作或没有权限)?
原因是 Web 端初始化 getInstance
方法中参数 authType
没有设置为 1 导致报错。
为何集成 SDK 报 Unicode 格式相关错误?
当使用 C++ sdk(8.5.1) #include "nim_cpp_wrapper/nim_cpp_api.h" 集成 SDK,但是返回报错如下:
已启动生成… 1>------ 已启动生成: 项目: MFCApplication1, 配置: Debug Win32 ------ 1>MFCApplication1Dlg.cpp 1>E:\\demo\\nim\_my\\nim\_sdk\\include\\nim\_cpp\_wrapper\\nim\_cpp\_api.h(1,1): warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失 1>E:\\demo\\nim\_my\\nim\_sdk\\include\\nim\_cpp\_wrapper\\nim\_sdk\_cpp\_wrapper.h(1,1): warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
解决方法:
需要进命令行修改其他选项至/utf-8。
Weblink 地址如何使用 HTTPs?
正常公有云的用户,如果在初始化的时候配置了 secure
字段为 false
,那么 lbs 返回的 link 地址就会使用 HTTP 的请求方式,反之配置为 true
就是使用 HTTPs 的请求方式。
针对私有化的用户,用户会配置 privateConf
字段,如果用户在 privateConf
字段里面配置了 link\_ssl\_web
字段为 false
,那么私有化 lbs 返回的 link 地址会使用 HTTP 的请求方式,反之配置为 true
就是使用 HTTPs 的请求方式。
同时配置了 link\_ssl\_web
和 secure
字段的情况下,link\_ssl\_web
会覆盖 secure
的字段的配置。
如何解决报错 Cannot fit requested classes in a single dex file
?
您可以在 build.gradle
中添加以下代码:
defaultConfig {
...
multiDexEnabled true
...
}
dependencies {
...
implementation "androidx.multidex:multidex:2.0.1"
...
}
NIM SDK 初始化失败
问题原因
- 指定的 install directory 不正确导致没有正确的搜索到
nim.dll
文件加载失败。 - 没有安装 VS2017 运行时库导致
nim.dll
加载失败。 nim.dll
依赖的其他组件不存在或不在 PATH 环境变量搜索路径下,如h\_available.dll
,(Loadlibrary 后返回 nullptr,GetLastError() 返回 126)。- 32 位进程加载了 64 位的动态库。
解决方法
- Dependencies:https://github.com/lucasg/Dependencies 可以查看 nim.dll 依赖。
- Procexp: https://docs.microsoft.com/en-us/sysinternals/downloads/process-explorer 可以查看试图加载
nim.dll
进程的 PATH 环境变量。
如何在 Demo 中修改消息提醒的通知栏样式?
通知栏样式的字段 notificationFoldStyle
可以设置为如下:
- 全部折叠:NotificationFoldStyle.ALL
- 全部不折叠:NotificationFoldStyle.EXPAND
- 按会话折叠:NotificationFoldStyle.CONTACT
Demo 中折叠示例如下:
修改路径:demo>res>values>strings.xml
如何解决成报错 java.lang.IllegalStateException: PreferenceContentProvider config of authority in AndroidManifest.xml is invalid, please check it
?
将 AndroidManifest.xml
中“云信内部使用的进程间通信 provider”包名“com.netease.nim.demo”替换成自己项目的包名。
xml<provider
android:name="com.netease.nimlib.ipc.cp.provider.PreferenceContentProvider"
android:authorities="com.netease.nim.demo.ipc.provider.preference"
android:exported="false" />
如何解决报错 java.lang.NoSuchMethodError: No static method metafactory(Ljava/lang/invoke/MethodHandles$Lookup...
?
集成 SDK 项目启动时报错:
java.lang.NoSuchMethodError: No static method metafactory(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; in class Ljava/lang/invoke/LambdaMetafactory; or its super classes (declaration of 'java.lang.invoke.LambdaMetafactory' appears in /apex/com.android.runtime/javalib/core-oj.jar)
需要修改 build.gradle
配置来支持 java 8 语法。
android {
...
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
}
如何解决报错 need android.permission.bluetooth connect Android 12
?
引入了 BLUETOOTH\_SCAN、BLUETOOTH\_ADVERTISE
和 BLUETOOTH\_CONNECT
权限,可让您的应用扫描附近的设备,而无需请求位置权限。您的应用必须以 Android 12 为目标平台,才能声明这些权限。
参考链接:Android 12 中的新蓝牙权限
如何解决微信小程序编译报错 Function(...) is not a function uniapp
?
编译成微信小程序时,会直接在微信小程序上报错 Function(...) is not a function。这是微信基础库版本过低的问题,请切换 2.21.0 以上的版本。
为何调用 setCurrSession
方法后再次登陆无效?
在不开启数据库或者浏览器数据库不可用的前提下,如果没有设置 syncSessionUnread :true
(未读数同步),那么每次重新登录时对应会话的未读数都会累加(漫游消息变成未读)。
解决方法:需要您设置开启未读数同步,漫游消息就不会计入未读数。
如何解决报错 load public key error
?
可能原因如下:
由于第三方加固抛出异常被 SDK 捕获,从而导致 SDK 连接崩溃。
以下示例堆栈分析:
Armadillo.abb71e2781126155f728f5fb06b8677afdf3b612
即第三方加固导致的异常。
堆栈详情举例:
java.lang.NullPointerException: Attempt to invoke a virtual method on a null object reference at Armadillo.abb71e2781126155f728f5fb06b8677afdf3b612.of(Unknown Source:66) at com.netease.nimlib.push.packet.asymmetric.c.b(KeyStore.java:6) at com.netease.nimlib.push.packet.asymmetric.c.a(KeyStore.java:2) at com.netease.nimlib.push.packet.asymmetric.b.c(AsymmetricFactory.java:1) at com.netease.nimlib.push.net.e.a(PackagePacker.java:15) at com.netease.nimlib.push.net.d.b(LinkClient.java:6) at com.netease.nimlib.push.net.d.a(LinkClient.java:6) at com.netease.nimlib.push.a.h(AuthManager.java:13) at com.netease.nimlib.push.a.d(AuthManager.java:2) at com.netease.nimlib.push.b.c.g(NetworkKeeper.java:5) at com.netease.nimlib.push.b.c.d(NetworkKeeper.java:1) at com.netease.nimlib.push.b.c$2.run(NetworkKeeper.java:2) at java.util.TimerThread.mainLoop(Timer.java:555) at java.util.TimerThread.run(Timer.java:505)
Android 端如何去除 com.netease.nimlib.service.NimReceiver
?
随着市场监管越来越严格,部分市场会对自启动或者开机启动的行为进行检测,并通知上架方进行整改。
问题原因
该问题主要是 NimReceive
引起的,这是一个广播接收者,如果使用 AAR 文件或者远程仓库的方式集成 IM SDK,我们会以静态注册的方式注册该广播接受者,并添加 "android.intent.action.BOOT_COMPLETED"
和 "android.net.conn.CONNECTIVITY_CHANGE"
这两个 action,用于监听开机事件和网络状态变化的事件。当收到这两个事件的时候,我们会尝试唤醒 IM 的核心服务,以此达到保活的目的。
解决方案
可以在主工程的 AndroidManifest.xml
文件中,通过 tools:node="remove"
标签去掉 NimReceiver
的注册。
<receiver
android:name="com.netease.nimlib.service.NimReceiver"
android:exported="false"
tools:node="remove"
android:process=":core">
</receiver>
详情请参考合并多个清单文件。
如何解决报错 More than one file was found with OS independent path...
?
问题原因
很多三方库都会包含 lbc+shared.so
,从而会导致编译的时候出现两个通用的 so 文件,出现编译报错。
解决办法
可以通过 packagingOptions
语法选择其中一个,复制下面的代码,放在主工程的 application
>build.gradle
> android{}
。
packagingOptions {
pickFirst 'lib/armeabi-v7a/libc++_shared.so'
pickFirst 'lib/arm64-v8a/libc++_shared.so'
pickFirst 'lib/x86/libc++_shared.so'
pickFirst 'lib/x86_64/libc++_shared.so'
}
如何解决 Web 项目运行报错 Refused to create a worker from xxx web
?
本地运行没问题,但是部署到线上环境时 SDK 报错。
"Refused to create a worker from 'blob:http://xxx.xxx' because it violates the following Content Security Policy directive: "script-src 'self' 'unsafe-inline' 'unsafe-eval'". Note that 'worker-src' was not explicitly set, so 'script-src' is used as a fallback."
原因是部署到服务器后加上了 content-security-policy
,我们的 IM SDK 使用到了 worker,所以用户需要在 content-security-policy
中配置一下 worker-src
。
配置方法请参考:https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/worker-src
Web 端使用 IndexDB 报错:Error: Failed to execute 'transaction' on 'IDBDatabase': The database connection is closing
原因是 IndexDB 所在的磁盘存储空间已满。
解决方法:建议清理浏览器对应 IndexDB 所在磁盘的垃圾文件。
IM 服务端接口报错 "forbidden in current region,error code:403"
问题原因
请求访问的服务器域名区域不匹配。
解决方案
需根据项目请求服务器所在区域,使用不同的域名:
- 国内项目请求域名:api.netease.im
- 海外项目请求域名:api-sg.netease.im
为何客户端获取不到第三方回调的扩展字段?
问题描述
用户服务端针对 IM 消息,进行拦截并设置扩展字段,客户端发送方获取不到该扩展字段。
问题原因
只有服务端 responseCode
返回 200 的时候,客户端才会读取 callbackExt
的内容。
解决方案
- 服务端
responseCode
设置为200,其他信息以 JSON 的形式放在callbackExt
中。 - 客户端不能在消息发送回调中获取,需要在消息状态变化回调中才能获取到
callbackExt
字段的内容。
如何解决报错 Uncaught Error:Adapter uniapp:socket 'xxx' when readyState=0
?
具体报错不一定是某一个接口,可能是不同接口,示例为 sendMsg
接口。
问题原因
uniapp 项目在真机上运行(app 运行,而非 H5),websocket 多个连接会失效。
解决方案
查询到项目中所有 websocket 连接,只保留一个 IM websocket 连接。
日志打印 "no db"
当您在初始化 IM Web SDK 时,设置 db
为 true,如果日志打印 link::afterLogin: no db callFunc: "db::addTask"event: {isTrusted: true}
,则表示无法打开数据库,原因如下:
- 用户使用新版本的 SDK 打开数据库之后,然后换成旧版本 SDK 登录打不开浏览器数据库,原因是浏览器自带的 indexDB 版本只能向上兼容,用过新版本 SDK 的 indexDB 数据库之后,不能再使用老版本 SDK 的 indexDB,建议用户清理浏览器数据之后重新登录。
- 未知异常导致无法开启数据库,该情况如果能复现可以进一步调查确认。
如果用户手动没开启数据库或因为 SDK 限制(历史原因限制 safari、edge、IE 等浏览器上的数据库)导致没开启数据库,日志只会打印 link::afterLogin: no db
。
safari 浏览器打开服务监控平台报错或者跳转到登录页:
Mac 端打包 release 环境后登录 IM 报错 415
问题描述
当您集成 Flutter SDK 后,打包 Debug 环境, 登录 IM 正常,但是打包 Release 环境后,登录 IM 报错 415。
问题原因
沙盒的 network 权限可能没开,检查 Release.entitlements
文件中以下参数是否配置:
xml<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.network.server</key>
<true/>
参考链接:https://developer.apple.com/documentation/security/app_sandbox
Android 端登录 IM 没有回调,并且报错 "No static method isSupportPush"
问题描述
调用登录接口没有回调,可以在日志中看到如下异常(不限于该异常):
java.lang.NoSuchMethodError: No static method isSupportPush(Landroid/content/Context;)Z in class Lcom/heytap/msp/push/HeytapPushManager; or its super classes (declaration of 'com.heytap.msp.push.HeytapPushManager' appears in /data/app/com.netease.nim.demo-1/base.apk:classes2.dex) at com.netease.nimlib.mixpush.oppo.a.isFrameWorkSupport(OppoLocalChecker.java:26) at com.netease.nimlib.mixpush.c.a.isLocalSupport(APlatformLocalChecker.java:39) at com.netease.nimlib.mixpush.c.e.a(MixPushSuggest.java:31) at com.netease.nimlib.mixpush.c.e.a(MixPushSuggest.java:55) at com.netease.nimlib.mixpush.d.b(MixPushCore.java:204) at com.netease.nimlib.mixpush.d.a(MixPushCore.java:176) at com.netease.nimlib.mixpush.plugin.MixPushInteract.a(MixPushInteract.java:17) at com.netease.nimlib.push.a.a.b.d(LoginResponseHandler.java:140) at com.netease.nimlib.push.a.a.b.c(LoginResponseHandler.java:105) at com.netease.nimlib.push.a.a.b.a(LoginResponseHandler.java:52) at com.netease.nimlib.d.b.b.c(ResponseDispatcher.java:164) at com.netease.nimlib.d.b.b.lambda$-qBnJYoCZozckRGOSmE9OQC73Ek(ResponseDispatcher.java) at com.netease.nimlib.d.b.-$$Lambda$b$-qBnJYoCZozckRGOSmE9OQC73Ek.run(lambda) at com.netease.nimlib.r.a.a.run(PriorityRunnable.java:21) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) at java.lang.Thread.run(Thread.java:761)
问题原因
初始化时在 SDKOptions
的 MixPushConfig
中配置了 OPPO 厂商相关参数,登录时 SDK 会判断当前设备是否支持 OPPO 推送,具体为 SDK 内部调用 OPPO SDK 进行判断,当 IM SDK 与 OPPO SDK 版本不对应时,调用不到相关类或方法,就会抛出类似异常,也阻塞了登录。
解决方案
- 使用 IM SDK 对应的厂商推送 SDK 版本,具体见推送接入文档和 SDK 更新日志。
- 如果未接入厂商推送 SDK,可以去掉
SDKOptions
的MixPushConfig
中的相关配置参数。
在 Android 端集成 IM Uikit 报错
问题描述
IM Uikit 在 Android 8.0 手机上集成出现以下报错:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.shjztsc.surgicalcomm/com.netease.yunxin .kit.corekit.im.utils.TransferHelperActivity): java.lang.IllegalStateException: Only fullscreen opaque activities can request orientation
问题原因
Android 8.0 不允许设置一个非全屏 activity 锁定方向。
解决方法
在集成时候,把 AndroidManifest.xml
中 Activity 的配置 android:screenOrientation="portrait"
去掉。
xml<item name="android:windowIsTranslucent">false</item> or <item name="android:windowIsFloating">false</item>
如何解决报错 org.apache.http.NoHttpResponseException: XXX failed to respond
?
问题原因
服务端断开连接,但并没有通知客户端,导致下次请求该服务时 httpclient
继续使用该连接导致报错。
解决方案
每隔3秒回收空闲连接,清理过期连接。
模拟器运行报错
问题描述
Building for iOS Simulator, but the linked and embedded framework 'xxx.framework' was built for iOS + iOS Simulator
问题原因
自 Xcode 11.0 起,Apple 允许但不推荐把用于多平台的二进制框架或库捆绑到一个 .framework
文件中。自 Xcode 12.3 起,Apple 不允许在一个 .framework
文件中绑定多平台的库,必须使用 .xcframework
文件替代。为支持在 iOS 模拟器上运行项目,SDK 会在 .framework
文件中捆绑了多平台的库,所以 .framework
文件会在使用模拟器运行时被 Xcode 识别为错误配置。
解决方法
在 Xcode 中,进入 TARGETS > Project Name > Build Settings > Build Options 菜单,将 Validate Workspace 设置为 Yes。
Unity 打包 Android 环境下登录报错 414
日志如下:
问题原因
Log.cs 的 sdcard 读写不了导致。
解决方案
在 AndroidManifest.xml
加如下权限: