友情围观,群主的耐心,我等菜鸟自愧不如 |
引用:暄落 发表于 2020-09-24 13:58 嗯,以官方的Demo为参照点,如果搞不定,你就开贴,需要什么协助会尽力帮你 |
引用:JackJiang 发表于 2020-09-24 13:40 新进展是我这边连接github 项目中的 MobileIMSDK-master\demo_binary\Server\MobileIMSDKServerDemo_deploy_v5.0b20200905\run.bat在我本地是不会断开的,应该是我们后端的同学那里代码有问题。现在那边正在排查 |
[已回复] 求助关于MobileIMSDK聊天消息指纹码的生成以及其它疑问 这段代码解决了我的这个问题。我在退出登录的时候没有解绑监听器。 |
引用:暄落 发表于 2020-09-24 13:29 好,我来把RainbowChat中的“退出登陆”这个功能的主要实现代码,发你参一下,具体如果你不太理解功能是怎么样UI交互的,你就自已下载APP体验一下。 具体的功能体验就是:RainbowChat的“退出登陆”功能在下图中,点退出登陆时,会关闭当前连接并释放im sdk这一层的资源并跳转到登陆界面。 我贴的是没有删减的代码,你不需要关注的业务内容,跳过不看就行。 下面是“退出登陆”按钮,点击时的事件处理: // 点击"退出登陆" exitBtn.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { new AlertDialog.Builder(MoreActivity.this) .setTitle($$(R.string.general_are_u_sure)) .setMessage($$(R.string.main_more_msg_tone_exit_to_login)) .setPositiveButton($$(R.string.general_ok), new DialogInterface.OnClickListener(){ @Override public void onClick(DialogInterface dialog,int which) { // 退出登陆(但不退出JVM——即不通出APP进程) LoginActivity.doLogoutNoConfirm(MyApplication.getInstance2(), false, new Observer(){ // 此通知将在注册与IM服务器的连接、释放IM资源、释放本APP中所有activity后被通知 @Override public void update(Observable arg0, Object arg1) { // 退出登陆时,取消"自动登陆"的开关量设置 PreferencesToolkits.setAutoLogin(MoreActivity.this, false); // 代码执行至此,表示APP中所有的activity都已被回收(包括本MoreAcvitity), // 而要再次显示登陆界面activity的话,只能借助APP全局唯一的Context——即 // Application实例,以下代码千万不可引用错了Context哦 Context ctx = MyApplication.getInstance2(); Intent iLogin = IntentFactory.createLoginIntent(ctx); // 因Application对象并不是Activity,所以必须要加此flag,否则无法启动Activity iLogin.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // 进入登陆activity ctx.startActivity(iLogin); } }); } }) .setNegativeButton($$(R.string.general_cancel), null) .show(); } }); LoginActivity.doLogoutNoConfirm()方法的主要代码如下: /** * 退出APP的登陆,并释放所有资源。 * <p> * 注:方法中不涉及任何GUI,用在多线程中调用也没事。 * * @param context * @param exitJVM true表示完成退出APP(可用于完关闭应用时),否则表 * 示仅退出所有Activity(可用于切换到登陆界面重新登陆等场景下) * @param obsAfterLogoutIMServer 本观察者将在logout im server完成后,被 * 调用,当前此参数已知的是在更多界面中的”退出登陆“时使用了。一般来说,本参数 * 的设置只在exitJVM参数=false时才有意义,请参见源码 */ public static void doLogoutNoConfirm(final Context context, final boolean exitJVM , final Observer obsAfterLogoutIMServer) { // TODO 退出登陆时如有其它事情要处理,可在此补充! // 【1】注销HTTP服务器的登陆 。。。。。。。。 // 【2】注销IM服务器连接并释放IM框架所占的所有资源 IMClientManager.doLogoutIMServer(context , new Observer(){// 为何要使用观察者?因退出登陆数据发送是在异步线程中实现的, // 使用观察者的目的是确保退出JVM等是在数据已发送完成后再行的哦!!!! @Override public void update(Observable observable, Object data) { // 释放APP应用占用的资源 systemExit(context, exitJVM); // if(obsAfterLogoutIMServer != null) obsAfterLogoutIMServer.update(null, null); } }); // 【3】重置大文件下载管理器 。。。。。。。 } IMClientManager.doLogoutIMServer()方法的实现代码: /** * 退出IM服务器连接并释放IM所占的所有资源(含退出IM框架连接、再释放IM框架所占的资源)。 * <p> * 在切换账号等功能场景下,使用本方法可以保证重新登陆时IM框架 * 已回到重初状态,从而完全正常的重新登陆。 * * @see LocalDataSender#sendLoginout() * @see IMClientManager#releaseMobileIMSDK() */ public static void doLogoutIMServer(final Context context, final Observer obsForSucess) { // 退出登陆 new AsyncTask<Object, Integer, Integer>(){ private Observer obsForSucess = null; @Override protected Integer doInBackground(Object... params) { int code = -1; try { if(params != null) obsForSucess = (Observer)params[0]; // local user info 为空即意味着用户极是打开了登陆界面而尚未有登陆过,那当然就不需要退出登陆罗 if(MyApplication.getInstance(context).getIMClientManager().getLocalUserInfo() != null) code = LocalDataSender.getInstance().sendLoginout(); } catch (Exception e) { Log.e(TAG, "错误发生于doLogout:sendLoginout时:"+e.getMessage(), e); } return code; } @Override protected void onPostExecute(Integer code) { // local user info 为空即意味着用户极是打开了登陆界面而尚未有登陆过,那当然就不需要退出登陆罗 if(MyApplication.getInstance(context).getIMClientManager().getLocalUserInfo() != null) { if(code == 0) Log.d(LoginActivity.class.getSimpleName(), "注销登陆请求已成功发出!"); else Log.w(LoginActivity.class.getSimpleName(), "注销登陆请求发送失败。错误码是:"+code+"!"); } try { // 释放IM所占资源 MyApplication.getInstance(context).getIMClientManager().releaseMobileIMSDK(); } catch (Exception e) { Log.e(TAG, "错误发生于logoutMobileIMSDK:onPostExecute:releaseMobileIMSDK()时:"+e.getMessage(), e); } // * 处理完成后通知观察者做其它事哦 if(obsForSucess != null) obsForSucess.update(null, null); } }.execute(obsForSucess); IMClientManager.releaseMobileIMSDK()方法的实现代码: /** * 释放IM框架所占用的资源,在退出登陆时请务必调用本方法,否则重 * 新登陆将不能正常实现(指APP进程不退出时切换账号这种情况)。 */ public void releaseMobileIMSDK() { // 释放IM核心库资源 ClientCoreSDK.getInstance().release(); // 重置本类的初始化标识 this.resetInitFlag(); // 清空设置的回调 ClientCoreSDK.getInstance().setChatBaseEvent(null); ClientCoreSDK.getInstance().setChatMessageEvent(null); ClientCoreSDK.getInstance().setMessageQoSEvent(null); // 清空本量中的关键全局变量 this.localUserInfo = null; this.currentFrontGroupChattingGroupID = null; this.currentFrontTempChattingUserUID = null; this.currentFrontChattingUserUID = null; // 重置关键数据模型变量 this.friendsListProvider = null; this.groupsProvider = null; this.messagesProvider = null; this.groupsMessagesProvider = null; this.alarmsProvider = null; this.currentVideoChattingActivity = null; ProhibitSpeechCheckerProvider.getInstance().clear(); // 释放实时音视频相关资源 VVP2PProvider.getInstance(context).release(); } 注意一点:RainbowChat中,在登陆界面跳转前,就进行是IM SDK的Init,所以即使是你看到的“退出登陆”这种情况,也可以确保再次登陆前已经完成im sdk的init: /** * 打开LoginActivity的Intent构造方法. 此方法通常用于无法普通地打开登陆界面的场景. * * @param thisActivity * @return */ public static Intent createLoginIntent(Context thisActivity) { // init MobileIMSDK first(必须保证此代码被调用,否则IM框架无法完成IM服务器的连接等工作) // 通常在打开登陆界面调用此方法,是合理的,因为它下一步就是登陆im框架啊 MyApplication.getInstance(thisActivity).getIMClientManager().initMobileIMSDK(); Intent intent = new Intent(thisActivity, LoginActivity.class); return intent; } IMClientManager.initMobileIMSDK()的代码实现: /** * IM框架初始化方法,本方法在连接IM服务器前必须被调用1次,否则IM底层框架将无法工作。 */ public void initMobileIMSDK() { if(!this._init) { baseEventListener = new ChatBaseEventListener(context); transDataListener = new ChatMessageEventListener(context); messageQoSListener = new MessageQoSListener(context); ClientCoreSDK.getInstance().init(context); ClientCoreSDK.getInstance().setChatBaseEvent(baseEventListener); ClientCoreSDK.getInstance().setChatMessageEvent(transDataListener); ClientCoreSDK.getInstance().setMessageQoSEvent(messageQoSListener); // ClientCoreSDK.DEBUG = true; friendsListProvider = new FriendsListProvider(); groupsProvider = new GroupsProvider(); messagesProvider = new MessagesProvider(); groupsMessagesProvider = new GroupsMessagesProvider(); alarmsProvider = new AlarmsProvider(this.context); this._init = true; } } |
引用:JackJiang 发表于 2020-09-24 13:26 嗯嗯,我怀疑是 退出账号→登录另一账号 这样的情况导致的。上边有我的退出登录与登录逻辑,我是仿写的 SDK Demo 里面的代码实现的 |
引用:暄落 发表于 2020-09-24 13:13 你想做的是,在不退出app的情况下,实现退出当前账号,前重新登陆这样的功能逻辑是吗? 如果是,我就把RainbowChat产品中的实现,贴给你参一下。 |
引用:JackJiang 发表于 2020-09-24 12:27 是的,我在出现的时候去后端那里看了一下,不存在同一账号重复登陆的情况。 |
引用:暄落 发表于 2020-09-24 10:50 这么规律,一定是其它问题。你排查过,不存在同一账号重复登陆是吧 |
引用:JackJiang 发表于 2020-09-24 10:45 我断开重连,早上怀疑是退出登录-登录,多次导致的问题,结果刚刚我连接sdk中的 run.bat ,发现连接自己的没有什么问题,可能是后端同学那里的问题。现在所有连接那个地址的都是 45s 断一次。 |
引用:JackJiang 发表于 2020-09-24 10:45 有一个回复提示进审核了,没有显示出来 |
引用:暄落 发表于 2020-09-24 09:16 你贴的这个内容,跟你发的帖子问题,是有关联的吗? |
引用:JackJiang 发表于 2020-09-23 12:47 退出登录代码: ----------------------------------------- 注销登录之后初始化的代码 ----------------------------------------------------- 再次登录的代码 |
引用:JackJiang 发表于 2020-09-23 12:47 我找到了触发条件:当我下线切换账号,重复几次就会出先这样的情况,应该是我退出登录或者登录写的有问题,麻烦站长帮我看下 |
按照你的Log显示,每隔45秒断一次,这一定是另有原因。 检查一下:这台手机的登陆ID,是否有别的手机有用同样的ID,也就是看看是否存在同一个ID重复登际的情况。 |