实现蓝牙通信

1.添加蓝牙会话的服务组件ChatService
//构造方法,接收UI主线程传递的对象
public ChatService(Context context, Handler handler) {
//构造方法完成蓝牙对象的创建
mAdapter = BluetoothAdapter.getDefaultAdapter();
mState = STATE_NONE;
mHandler = handler;
}

private synchronized void setState(int state) {
mState = state;
mHandler.obtainMessage(BluetoothChat.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
}

public synchronized int getState() {
return mState;
}

public synchronized void start() {
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
if (mAcceptThread == null) {
mAcceptThread = new AcceptThread();
mAcceptThread.start();
}
setState(STATE_LISTEN);
}

//取消 CONNECTING 和 CONNECTED 状态下的相关线程,然后运行新的 mConnectThread 线程
public synchronized void connect(BluetoothDevice device) {
if (mState == STATE_CONNECTING) {
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
}
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
mConnectThread = new ConnectThread(device);
mConnectThread.start();
setState(STATE_CONNECTING);
}

/*
开启一个 ConnectedThread 来管理对应的当前连接。之前先取消任意现存的 mConnectThread 、
mConnectedThread 、 mAcceptThread 线程,然后开启新 mConnectedThread ,传入当前刚刚接受的
socket 连接。最后通过 Handler来通知UI连接
*/
public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) {
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
if (mAcceptThread != null) {
mAcceptThread.cancel();
mAcceptThread = null;
}
mConnectedThread = new ConnectedThread(socket);
mConnectedThread.start();
Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_DEVICE_NAME);
Bundle bundle = new Bundle();
bundle.putString(BluetoothChat.DEVICE_NAME, device.getName());
msg.setData(bundle);
mHandler.sendMessage(msg);
setState(STATE_CONNECTED);
}

// 停止所有相关线程,设当前状态为 NONE
public synchronized void stop() {
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
if (mAcceptThread != null) {
mAcceptThread.cancel();
mAcceptThread = null;
}
setState(STATE_NONE);
}

// 在 STATE_CONNECTED 状态下,调用 mConnectedThread 里的 write 方法,写入 byte
public void write(byte[] out) {
ConnectedThread r;
synchronized (this) {
if (mState != STATE_CONNECTED)
return;
r = mConnectedThread;
}
r.write(out);
}

// 连接失败的时候处理,通知 ui ,并设为 STATE_LISTEN 状态
private void connectionFailed() {
setState(STATE_LISTEN);
Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(BluetoothChat.TOAST, “链接不到设备”);
msg.setData(bundle);
mHandler.sendMessage(msg);
}

// 当连接失去的时候,设为 STATE_LISTEN 状态并通知 ui
private void connectionLost() {
setState(STATE_LISTEN);
Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(BluetoothChat.TOAST, “设备链接中断”);
msg.setData(bundle);
mHandler.sendMessage(msg);
}

// 创建监听线程,准备接受新连接。使用阻塞方式,调用 BluetoothServerSocket.accept()
private class AcceptThread extends Thread {
private final BluetoothServerSocket mmServerSocket;

public AcceptThread() {
    BluetoothServerSocket tmp = null;
    try {
        //使用射频端口(RF comm)监听
        tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
    } catch (IOException e) {
    }
    mmServerSocket = tmp;
}

@Override
public void run() {
    setName("AcceptThread");
    BluetoothSocket socket = null;
    while (mState != STATE_CONNECTED) {
        try {
            socket = mmServerSocket.accept();
        } catch (IOException e) {
            break;
        }
        if (socket != null) {
            synchronized (ChatService.this) {
                switch (mState) {
                    case STATE_LISTEN:
                    case STATE_CONNECTING:
                        connected(socket, socket.getRemoteDevice());
                        break;
                    case STATE_NONE:
                    case STATE_CONNECTED:
                        try {
                            socket.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        break;
                }
            }
        }
    }
}

public void cancel() {
    try {
        mmServerSocket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

}

/*
连接线程,专门用来对外发出连接对方蓝牙的请求和处理流程。
构造函数里通过 BluetoothDevice.createRfcommSocketToServiceRecord() ,
从待连接的 device 产生 BluetoothSocket. 然后在 run 方法中 connect ,
成功后调用 BluetoothChatSevice 的 connected() 方法。定义 cancel() 在关闭线程时能够关闭相关socket 。
*/
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;

public ConnectThread(BluetoothDevice device) {
    mmDevice = device;
    BluetoothSocket tmp = null;
    try {
        tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
    } catch (IOException e) {
        e.printStackTrace();
    }
    mmSocket = tmp;
}

@Override
public void run() {
    setName("ConnectThread");
    mAdapter.cancelDiscovery();
    try {
        mmSocket.connect();
    } catch (IOException e) {
        connectionFailed();
        try {
            mmSocket.close();
        } catch (IOException e2) {
            e.printStackTrace();
        }
        ChatService.this.start();
        return;
    }
    synchronized (ChatService.this) {
        mConnectThread = null;
    }
    connected(mmSocket, mmDevice);
}

public void cancel() {
    try {
        mmSocket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

}

/*
双方蓝牙连接后一直运行的线程;构造函数中设置输入输出流。
run()方法中使用阻塞模式的 InputStream.read()循环读取输入流,然后发送到 UI 线程中更新聊天消息。
本线程也提供了 write() 将聊天消息写入输出流传输至对方,传输成功后回写入 UI 线程。最后使用cancel()关闭连接的 socket
*/
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;

public ConnectedThread(BluetoothSocket socket) {
    mmSocket = socket;
    InputStream tmpIn = null;
    OutputStream tmpOut = null;
    try {
        tmpIn = socket.getInputStream();
        tmpOut = socket.getOutputStream();
    } catch (IOException e) {
        e.printStackTrace();
    }
    mmInStream = tmpIn;
    mmOutStream = tmpOut;
}

@Override
public void run() {
    byte[] buffer = new byte[1024];
    int bytes;
    while (true) {
        try {
            bytes = mmInStream.read(buffer);
            mHandler.obtainMessage(BluetoothChat.MESSAGE_READ, bytes, -1, buffer).sendToTarget();
        } catch (IOException e) {
            connectionLost();
            break;
        }
    }
}

public void write(byte[] buffer) {
    try {
        mmOutStream.write(buffer);
        mHandler.obtainMessage(BluetoothChat.MESSAGE_WRITE, -1, -1, buffer).sendToTarget();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public void cancel() {
    try {
        mmSocket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

}
2.选择界面布局

<?xml version="1.0" encoding="utf-8"?>









3.源码博客地址:https://gitee.com/whqhhh/myBlueTooth

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值