默认
发表评论 7
想开发IM:买成品怕坑?租第3方怕贵?找开源自已撸?尽量别走弯路了... 找站长给点建议
[已解决] MobileIMSDK的Android客户端如何重新登录服务器???
在主界面里,当服务器和客户端断连后,客户端会提醒客户断连了,可能是服务器断网了,那我就尝试再次登录

file:///C:\Users\Administrator\AppData\Roaming\Tencent\Users\2353319759\QQ\WinTemp\RichOle\QOMX}A6WE{_$E3X4N}$~)WT.pngfile:///C:\Users\Administrator\AppData\Roaming\Tencent\Users\2353319759\QQ\WinTemp\RichOle\QOMX}A6WE{_$E3X4N}$~)WT.pngpublic void refreshMyid() {
    int myid = ClientCoreSDK.getInstance().getCurrentUserId();
    if (myid==-1){
        int i=6;
        needLogin=true;
        while (needLogin && i>0){
            doLoginImpl();
            Log.e(PCMAudioService.class.getSimpleName(),"又一次重新登录");
            i--;
            try {
                Thread.sleep(1000*10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
   // this.viewMyid.setText(myid == -1 ? "连接断开" : "" + myid);
}


private void initForLogin()
{
    // 准备好异步登陆结果回调观察者(将在登陆方法中使用)
    onLoginSucessObserver = new Observer(){
        @Override
        public void update(Observable observable, Object data)
        {
            // 服务端返回的登陆结果值
            int code = (Integer)data;
            // 登陆成功
            Log.d(TAG,"接收到登录的反馈信息");
            if(code == 0){
                Log.e(TAG, "-------------登录成功------------");
                needLogin=false;
            }else{
                Log.e(TAG, "xxxxxxxxx登录失败了xxxxxxxxxxxx");

            }
        }
那我们在断连之后再重新登录是否就可以了???
但是我发现我只有在最后一次重新登录会成功,例如我尝试登录3次,只有在第3次会成功,前两次绝对不成功,这是为什么???





file:///C:\Users\Administrator\AppData\Roaming\Tencent\Users\2353319759\QQ\WinTemp\RichOle\QOMX}A6WE{_$E3X4N}$~)WT.png




即时通讯网 - 即时通讯开发者社区! 来源: - 即时通讯开发者社区!

标签:MobileIMSDK
上一篇:关于MobileIMSDK如何保证数据有序性的问题。下一篇:[已解决] 请教MobileIMSDK的Android端登录问题
推荐方案
评论 7
首先纠正理解:MobileIMSDK在首次“登陆/连接”服务器成功后,后面无论是网络有问题还是何种情况导致的掉线,框架这一层都会自动尝试重连,根本不需要你手动去调什么重“登陆”。不理解你为何需要手动调用重新登陆。。。
引用:JackJiang 发表于 2017-03-06 18:23
首先纠正理解:MobileIMSDK在首次“登陆/连接”服务器成功后,后面无论是网络有问题还是何种情况导致的掉线 ...

@JackJiang 谢谢你的解答,我的服务器我主动把它关闭了(如服务器断电了等不正常因素),Android客户端会受到user_id= -1的值,这时在聊天界面刷新user_id,显示为连接断开,这个时候,服务器重新启动了,这个时候的Android客户端是不会主动连接的,显示user_id的地方,会一直显示-- 连接断开。我下的SDK是1月份的。
签名: 该会员没有填写今日想说内容.
引用:niebiao 发表于 2017-03-07 08:46
@JackJiang 谢谢你的解答,我的服务器我主动把它关闭了(如服务器断电了等不正常因素),Android客户端会 ...

你的代码没有下错。

1问题来了:


如果按照你描述的情况,只要你手机网络正常,只要服务器重新启动,手机端是肯定可以自动连上的。如果照你说的,一直是断开,那显然就有问题了。不过,你可以按照我提供的思路来排查问题原因。

2你可以按照如下方法来排查:


1)使用我的Demo代码(你没有修改任何代码的版本),看看服务端关闭后客户端会不会自动重连:
注意:客户端和服务端都用我的代码。目的是用来排查你客户端和服务端的网络是否有问题,我的demo代码是经过大量测试和使用后验证的结果,所以基本上可以保证能按照设计技术特征正常运行,所以它是个好的参照物。

2)如果1)能正常运行(能自动重连),那么就应该排查你的代码,看看你修改了什么地方,有必要可以贴到论坛;

3)如果1)不能正常运行,那么可能是你的网络有问题,建议排查客户端到服务端的网路、服务端到客户的网络,必须要保证双向都能正常ping通才可以实现im的通信。

3补充提示:


你可以在IDE下查看logcat日志输出,客户端sdk是会打印出各种log的,你有必要把log给贴出来。同样服务端也有log,记得观察log的信息,有必要也贴到论坛。
引用:JackJiang 发表于 2017-03-07 09:46
你的代码没有下错。

@JackJiang 谢谢你的分析,确实,demo版本的Android 客户端确实是可以重连,但是我把代码导入到Eclipse里运行,还是没有重新连接上。
观看log,发现,确实有重连机制,但是编译源码得到的APK断线重连一次就没有再次重连了,而demo里的APK一直在重连。所以demo可以连接上,而源码编译的apk没有连接上,是因为没有重新连接。我也没有找到这个原因,没有改动源码,只是把/src_all/里的demo代码和source里的代码合并起来。public class AutoReLoginDaemon
{
        private static final String TAG = AutoReLoginDaemon.class.getSimpleName();

        public static int AUTO_RE$LOGIN_INTERVAL = 2000;

        private Handler handler = null;
        private Runnable runnable = null;
        private boolean autoReLoginRunning = false;
        private boolean _excuting = false;

        private static AutoReLoginDaemon instance = null;

        private Context context = null;

        public static AutoReLoginDaemon getInstance(Context context)
        {
                if (instance == null)
                        instance = new AutoReLoginDaemon(context);
                return instance;
        }

        private AutoReLoginDaemon(Context context)
        {
                this.context = context;
                init();
        }

        private void init()
        {
                this.handler = new Handler();
                this.runnable = new Runnable()
                {
                        public void run()
                        {
                                if (!AutoReLoginDaemon.this._excuting)
                                {
                                        new AsyncTask()
                                        {
                                                protected Integer doInBackground(Object[] params)
                                                {
                                                        AutoReLoginDaemon.this._excuting = true;
                                                        if (ClientCoreSDK.DEBUG)
                                                                Log.d(AutoReLoginDaemon.TAG
                                                                                , "【IMCORE】自动重新登陆线程执行中, autoReLogin?" + ClientCoreSDK.autoReLogin + "...");
                                                        int code = -1;

                                                        if (ClientCoreSDK.autoReLogin)
                                                        {
                                                                code = LocalUDPDataSender.getInstance(
                                                                                AutoReLoginDaemon.this.context).sendLogin(
                                                                                                ClientCoreSDK.getInstance().getCurrentLoginName()
                                                                                                , ClientCoreSDK.getInstance().getCurrentLoginPsw()
                                                                                                , ClientCoreSDK.getInstance().getCurrentLoginExtra());
                                                        }
                                                        return Integer.valueOf(code);
                                                }

                                                protected void onPostExecute(Integer result)
                                                {
                                                        if (result.intValue() == 0)
                                                        {
                                                                // *********************** 同样的代码也存在于LocalUDPDataSender.SendLoginDataAsync中的代码
                                                                // 登陆消息成功发出后就启动本地消息侦听线程:
                                                                // 第1)种情况:首次使用程序时,登陆信息发出时才启动本地监听线程是合理的;
                                                                // 第2)种情况:因网络原因(比如服务器关闭或重启)而导致本地监听线程中断的问题:
                                                                //      当首次登陆后,因服务端或其它网络原因导致本地监听出错,将导致中断本地监听线程,
                                                                //                  所以在此处在自动登陆重连或用户自已手机尝试再次登陆时重启监听线程就可以恢复本地
                                                                //                  监听线程的运行。
                                                                LocalUDPDataReciever.getInstance(AutoReLoginDaemon.this.context).startup();
                                                        }

                                                        //
                                                        _excuting = false;
                                                        // 开始下一个心跳循环
                                                        handler.postDelayed(runnable, AUTO_RE$LOGIN_INTERVAL);
                                                }
                                        }
                                        .execute(new Object[0]);
                                }
                        }
                };
        }

        public void stop()
        {
                this.handler.removeCallbacks(this.runnable);
                this.autoReLoginRunning = false;
        }

        public void start(boolean immediately)
        {
                stop();

                this.handler.postDelayed(this.runnable, immediately ? 0 : AUTO_RE$LOGIN_INTERVAL);
                this.autoReLoginRunning = true;
        }

        public boolean isautoReLoginRunning()
        {
                return this.autoReLoginRunning;
        }
}


[已解决] MobileIMSDK的Android客户端如何重新登录服务器???_源码编译的log,报错误后不再重连
源码编译的log到此处没有了,没有再重连

Android1.png (120.99 KB, 下载次数: 2487)

源码编译的log

源码编译的log

demo1.png (128.44 KB, 下载次数: 2516)

demo apk的log

demo apk的log

demo2.png (54.14 KB, 下载次数: 2570)

demo apk的log,报错后继续重连

demo apk的log,报错后继续重连

MobileIMSDK4aDemo.zip

1.01 MB, 下载次数: 1

签名: 该会员没有填写今日想说内容.
引用:niebiao 发表于 2017-03-07 15:03
@JackJiang 谢谢你的分析,确实,demo版本的Android 客户端确实是可以重连,但是我把代码导入到Eclipse里 ...

我等会下载你的代码来看看
引用:JackJiang 发表于 2017-03-07 17:00
我等会下载你的代码来看看

我调试过程中,在AsyncTask中,只是执行了doInBackground方法,而onPostExecute没有执行,没有进入循环
进一步调查,可能是android版本变更后,AsyncTask使用方法已经改变,可以改成这样,可以顺利的重连了


                                        new AsyncTask<Void, Void, Integer>() {
                        @Override
                        protected Integer doInBackground(Void... params) {
                                AutoReLoginDaemon.this._excuting = true;
                                                        if (ClientCoreSDK.DEBUG)
                                                                Log.d(AutoReLoginDaemon.TAG
                                                                                , "【IMCORE】自动重新登陆线程执行中, autoReLogin?" + ClientCoreSDK.autoReLogin + "...");
                                                        int code = -1;

                                                        if (ClientCoreSDK.autoReLogin)
                                                        {
                                                                code = LocalUDPDataSender.getInstance(
                                                                                AutoReLoginDaemon.this.context).sendLogin(
                                                                                                ClientCoreSDK.getInstance().getCurrentLoginName()
                                                                                                , ClientCoreSDK.getInstance().getCurrentLoginPsw()
                                                                                                , ClientCoreSDK.getInstance().getCurrentLoginExtra());
                                                        }
                                                        Log.d("niebiao", "xxxxxxxxxxxdoInBackgroundxxxxxxxxxxx"+_excuting);
                                                        return Integer.valueOf(code);
                        }

                        @Override
                        protected void onPostExecute(Integer result) {

                            if (result.intValue() == 0)
                                                        {
                                                                Log.d("niebiao", "-------onPostExecute-------"+_excuting);
                                                                // *********************** 同样的代码也存在于LocalUDPDataSender.SendLoginDataAsync中的代码
                                                                // 登陆消息成功发出后就启动本地消息侦听线程:
                                                                // 第1)种情况:首次使用程序时,登陆信息发出时才启动本地监听线程是合理的;
                                                                // 第2)种情况:因网络原因(比如服务器关闭或重启)而导致本地监听线程中断的问题:
                                                                //      当首次登陆后,因服务端或其它网络原因导致本地监听出错,将导致中断本地监听线程,
                                                                //                  所以在此处在自动登陆重连或用户自已手机尝试再次登陆时重启监听线程就可以恢复本地
                                                                //                  监听线程的运行。
                                                                LocalUDPDataReciever.getInstance(AutoReLoginDaemon.this.context).startup();
                                                        }

                                                        //
                                                        _excuting = false;
                                                        Log.d("niebiao", "-------onPostExecute-------"+_excuting);
                                                        // 开始下一个心跳循环
                                                        handler.postDelayed(runnable, AUTO_RE$LOGIN_INTERVAL);
                                                        Log.d("niebiao", "-------onPostExecute-------"+_excuting);
                        }
                    }.execute();

签名: 该会员没有填写今日想说内容.
引用:niebiao 发表于 2017-03-07 17:26
我调试过程中,在AsyncTask中,只是执行了doInBackground方法,而onPostExecute没有执行,没有进入循环
...

是的,这个贴子里好早以前讨论过,看看我7楼的回复:http://www.52im.net/thread-127-1-1.html

你修改的是对的。当时的代码我可能忘记同步到github了,我一会同步上去。
打赏楼主 ×
使用微信打赏! 使用支付宝打赏!

返回顶部