在Android上面如何使用带有心跳检测的Socket

由于移动设备的网络的复杂性,经常会出现网络断开,如果没有心跳包的检测,客户端只会在需要发送数据的时候才知道自己已经断线,会延误,甚至丢失服务器发送过来的数据。一下简单建立一个带有心跳检测的SocketDemo。

Android 后台Servevice

package org.feng.sockettest.server;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.ref.WeakReference;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Arrays;

import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;

public class BackService extends Service {
private static final String TAG = “BackService”;
private static final long HEART_BEAT_RATE = 3 * 1000;

public static final String HOST = "192.168.1.101";// "192.168.1.21";//
public static final int PORT = 9800;

public static final String MESSAGE_ACTION="org.feng.message_ACTION";
public static final String HEART_BEAT_ACTION="org.feng.heart_beat_ACTION";

private ReadThread mReadThread;

private LocalBroadcastManager mLocalBroadcastManager;

private WeakReference<Socket> mSocket;

// For heart Beat
private Handler mHandler = new Handler();
private Runnable heartBeatRunnable = new Runnable() {

    @Override
    public void run() {
        if (System.currentTimeMillis() - sendTime >= HEART_BEAT_RATE) {
            boolean isSuccess = sendMsg("");//就发送一个\r\n过去 如果发送失败,就重新初始化一个socket
            if (!isSuccess) {
                mHandler.removeCallbacks(heartBeatRunnable);
                mReadThread.release();
                releaseLastSocket(mSocket);
                new InitSocketThread().start();
            }
        }
        mHandler.postDelayed(this, HEART_BEAT_RATE);
    }
};

private long sendTime = 0L;
private IBackService.Stub iBackService = new IBackService.Stub() {

    @Override
    public boolean sendMessage(String message) throws RemoteException {
        return sendMsg(message);
    }
};

@Override
public IBinder onBind(Intent arg0) {
    return iBackService;
}

@Override
public void onCreate() {
    super.onCreate();
    new InitSocketThread().start();
    mLocalBroadcastManager=LocalBroadcastManager.getInstance(this);

}
public boolean sendMsg(String msg) {
    if (null == mSocket || null == mSocket.get()) {
        return false;
    }
    Socket soc = mSocket.get();
    try {
        if (!soc.isClosed() && !soc.isOutputShutdown()) {
            OutputStream os = soc.getOutputStream();
            String message = msg + "\r\n";
            os.write(message.getBytes());
            os.flush();
            sendTime = System.currentTimeMillis();//每次发送成数据,就改一下最后成功发送的时间,节省心跳间隔时间
        } else {
            return false;
        }
    } catch (IOException e) {
        e.printStackTrace();
        return false;
    }
    return true;
}

private void initSocket() {//初始化Socket
    try {
        Socket so = new Socket(HOST, PORT);
        mSocket = new WeakReference<Socket>(so);
        mReadThread = new ReadThread(so);
        mReadThread.start();
        mHandler.postDelayed(heartBeatRunnable, HEART_BEAT_RATE);//初始化成功后,就准备发送心跳包
    } catch (UnknownHostException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

private void releaseLastSocket(WeakReference<Socket> mSocket) {
    try {
        if (null != mSocket) {
            Socket sk = mSocket.get();
            if (!sk.isClosed()) {
                sk.close();
            }
            sk = null;
            mSocket = null;
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

class InitSocketThread extends Thread {
    @Override
    public void run() {
        super.run();
        initSocket();
    }
}

// Thread to read content from Socket
class ReadThread extends Thread {
    private WeakReference<Socket> mWeakSocket;
    private boolean isStart = true;

    public ReadThread(Socket socket) {
        mWeakSocket = new WeakReference<Socket>(socket);
    }

    public void release() {
        isStart = false;
        releaseLastSocket(mWeakSocket);
    }

    @Override
    public void run() {
        super.run();
        Socket socket = mWeakSocket.get();
        if (null != socket) {
            try {
                InputStream is = socket.getInputStream();
                byte[] buffer = new byte[1024 * 4];
                int length = 0;
                while (!socket.isClosed() && !socket.isInputShutdown()
                        && isStart && ((length = is.read(buffer)) != -1)) {
                    if (length > 0) {
                        String message = new String(Arrays.copyOf(buffer,
                                length)).trim();
                        Log.e(TAG, message);
                        //收到服务器过来的消息,就通过Broadcast发送出去
                        if(message.equals("ok")){//处理心跳回复
                            Intent intent=new Intent(HEART_BEAT_ACTION);
                            mLocalBroadcastManager.sendBroadcast(intent);
                        }else{
                            //其他消息回复
                            Intent intent=new Intent(MESSAGE_ACTION);
                            intent.putExtra("message", message);
                            mLocalBroadcastManager.sendBroadcast(intent);
                        }
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

}

在Activity中发送以及接收数据:

package org.feng.sockettest;

import java.lang.ref.WeakReference;

import org.feng.sockettest.server.BackService;
import org.feng.sockettest.server.IBackService;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v4.content.LocalBroadcastManager;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {
private static final String TAG = “MainActivity”;

private IBackService iBackService;
private ServiceConnection conn = new ServiceConnection() {

    @Override
    public void onServiceDisconnected(ComponentName name) {
        iBackService = null;

    }

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        iBackService = IBackService.Stub.asInterface(service);
    }
};

private TextView mResultText;
private EditText mEditText;
private Intent mServiceIntent;

class MessageBackReciver extends BroadcastReceiver {
    private WeakReference<TextView> textView;

    public MessageBackReciver(TextView tv) {
        textView = new WeakReference<TextView>(tv);
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        TextView tv = textView.get();
        if (action.equals(BackService.HEART_BEAT_ACTION)) {
            if (null != tv) {
                tv.setText("Get a heart heat");
            }
        } else {
            String message = intent.getStringExtra("message");
            tv.setText(message);
        }
    };
}

private MessageBackReciver mReciver;

private IntentFilter mIntentFilter;

private LocalBroadcastManager mLocalBroadcastManager;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);

    mResultText = (TextView) findViewById(R.id.resule_text);
    mEditText = (EditText) findViewById(R.id.content_edit);

    mReciver = new MessageBackReciver(mResultText);

    mServiceIntent = new Intent(this, BackService.class);

    mIntentFilter = new IntentFilter();
    mIntentFilter.addAction(BackService.HEART_BEAT_ACTION);
    mIntentFilter.addAction(BackService.MESSAGE_ACTION);

}

@Override
protected void onStart() {
    super.onStart();
    mLocalBroadcastManager.registerReceiver(mReciver, mIntentFilter);
    bindService(mServiceIntent, conn, BIND_AUTO_CREATE);
}

@Override
protected void onStop() {
    super.onStop();
    unbindService(conn);
    mLocalBroadcastManager.unregisterReceiver(mReciver);
}

public void onClick(View view) {
    switch (view.getId()) {
    case R.id.send:
        String content = mEditText.getText().toString();
        try {
            boolean isSend = iBackService.sendMessage(content);//Send Content by socket
            Toast.makeText(this, isSend ? "success" : "fail",
                    Toast.LENGTH_SHORT).show();
            mEditText.setText("");
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        break;

    default:
        break;
    }
}

}

完整项目带服务器段代码的见: http://git.oschina.net/fengcunhan/SocketTest.git

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值