如何利用心跳包实现断线重连(语言-java)

我想实现利用心跳包实现服务器断线,安卓重连。
目前我有两个思路,但是都没能成功:
1、因为我设置了Button,只有点击button才能调用连接服务器的方法,如果将重连的方法放在连接服务器的方法里面,只有点击按钮之后才能实现断线重连,而且还得是点击之后呈现连接失败才能重连,我的要求是,只点击一次,且是连接成功,中断服务器连接之后还能重新连接
这是我思路1的代码:

 /***
     *
     * 连接A53服务器
     *
     * **/
    public void connA53Server(String ip, String port) {
        //隐藏软键盘
        hideSoftKeyboard(MainActivity.this);

        //服务器IP
        ip = TempFragment.editText1.getText().toString().trim();
        if (!checkIP(ip)) {
            ToastUtils.showToast(MainActivity.this, "请输入正确的服务器IP");
            return;
        }
        //端口号
        port = TempFragment.editText2.getText().toString().trim();
        if (TextUtils.isEmpty(port)) {
            ToastUtils.showToast(MainActivity.this, "请输入正确的端口号");
            return;
        }

        Log.i("MainActivity", "ip=" + ip);
        Log.i("MainActivity", "port=" + port);

        //先关闭socket
        closeSocket();
        //连接socket
        connectSocket(ip, port);
        //接收数据
        recvSocketData();
    }


    /**
     * 连接socket
     ***/
    public void connectSocket(final String ip, final String port) {
        // 利用线程池直接开启一个线程 & 执行该线程
        mThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        // 创建Socket对象 & 指定服务端的IP 及 端口号
                        socket = new Socket(ip, Integer.parseInt(port));
                        //如果连接
                        if (socket.isConnected()) {
                            // 连接成功
                            Message msg = new Message();
                            msg.what = CONN_SUCCESS;//成功
                         
                            handler.sendMessage(msg);
                            break; // 连接成功后,跳出循环
                        } else {
                            Message msg = new Message();
                            msg.what = CONN_FAIL;//失败
                            handler.sendMessage(msg);
                        }

                    } catch (SocketTimeoutException e) {
                        socket = null;
                        Message msg = new Message();
                        msg.what = CONN_TIME_OUT;
                        handler.sendMessage(msg);
                    } catch (IOException e) {
                        socket = null;
                        Message msg = new Message();
                        msg.what = CONN_FAIL;
                        handler.sendMessage(msg);
                    }
                    // 连接失败后,等待一段时间再进行重连
                    try {
                        Thread.sleep(RECONNECT_DELAY);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }

2、第二个思路是将断线重连的逻辑写在连接Socket的外部,在连接成功的地方发送心跳包 ,然后用是否停止发送心跳包来判断是否断线,但是有一个问题,我的IP和端口是通过弹窗editview输入的,如果直接引用editiew会报空指针错误
这是我的发送心跳包的代码:

// 开始发送心跳包
    public void startHeartbeatTimer() {
        isConnected = true;
        heartbeatTimer = new Timer();
        heartbeatTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                sendHeartbeatPacket();
            }
        }, 3000, HEARTBEAT_INTERVAL);
    }

    public boolean isHeartbeatStopped() {
        return heartbeatTimer == null;
    }

    public void checkHeartbeatTimer(final String ip, final int port){
        if(isHeartbeatStopped()){
            stopHeartbeatTimer();
            startReconnectTimer(ip,port);
        }
    }

    // 停止发送心跳包
    public void stopHeartbeatTimer() {
        if (heartbeatTimer != null) {
            heartbeatTimer.cancel();
            heartbeatTimer = null;
        }
    }

    // 发送心跳包
    public void sendHeartbeatPacket() {
        if (socket == null) {
            // socket对象为空,无法发送心跳包
            System.out.println("socket对象为空");
            return;
        }
        try {
            OutputStream outputStream = socket.getOutputStream();
            // 发送心跳包数据
            // ...
            System.out.println("发送心跳包");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 启动重连定时器
    public void startReconnectTimer(final String ip, final int port) {
        reconnectTimer = new Timer();
        reconnectTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                socket = reconnect(ip, port);
                if (socket != null) {
                    System.out.println("重新连接服务器成功");
                    stopReconnectTimer(); // 连接成功后停止重连定时器
                } else {
                    System.out.println("重新连接服务器失败,继续尝试...");
                }
            }
        }, RECONNECT_INTERVAL);
    }

    // 停止重连定时器
    public void stopReconnectTimer() {
        if (reconnectTimer != null) {
            reconnectTimer.cancel();
            reconnectTimer = null;
        }
    }

    //重新连接服务器
    public Socket reconnect(String ip, int port) {
        Socket reconnectedSocket = null;
        try {
            if (!isSocketConnected(socket)) {
                // 关闭旧的socket连接
                if (socket != null && !socket.isClosed()) {
                    socket.close();
                }
                // 创建新的socket连接
                reconnectedSocket = new Socket(ip, port);

                if (reconnectedSocket.isConnected()) {
                    Message msg = new Message();
                    msg.what = CONN_SUCCESS; // 连接成功
                    handler.sendMessage(msg);
                } else {
                    Message msg = new Message();
                    msg.what = CONN_FAIL; // 连接失败
                    handler.sendMessage(msg);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return reconnectedSocket;
    }

    // 检测 socket 连接状态
    public boolean isSocketConnected(Socket socket) {
        return socket != null && socket.isConnected() && !socket.isClosed();
    }

心跳那里,IP和端口做个缓存就好了,放在map里

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 这篇博客: 安卓8.0和7.0有什么区别 8.0系统新功能盘点[安卓中文网]中的   Android 8.0主打最近大热的人工智能,通过让机器自己学习进而提升效率,设备可以自动去识别和判断软件的使用频率来选择关闭或者保留,而不是通过长时间未使用而进行关闭,从而达到省电省资源的目的;而且通过人工智能,机器可以自动去管理推送和位置更新等服务,让用户可以省去管理定位等服务的时间;新的系统还重新设计了部分页面、UI和图标,对通知中心等界面还做了大规模的改动与设计;引入了画中画的强化版,除了可以随意拖动小屏幕位置外还能更加流畅的对主界面进行操作,大大提升效率。 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:

    这里写图片描述


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^