Android实现蓝牙聊天功能

蓝牙,时下最流行的智能设备传输数据的方式之一,通过手机app和智能设备进行连接,获取设备上的测量数据,我们生活中随处可见的比如蓝牙智能手环,蓝牙电子秤,蓝牙心电测量设备等等。

本篇我将紧接着上篇结尾所写,一起来看下手机之间如何通过蓝牙实现文字聊天。

先贴出上篇的一些demo;

当点击图上的两个列表中的任何一个列表,执行如下代码:

mBtAdapter.cancelDiscovery();

String info = ((TextView) v).getText().toString();

String address = info.substring(info.length() - 17);

Intent intent = new Intent();

intent.putExtra(EXTRA_DEVICE_ADDRESS, address);

setResult(Activity.RESULT_OK, intent);

finish();

此蓝牙聊天工具最后实现的效果是这样的:

将回到聊天主界面:

public void onActivityResult(int requestCode, int resultCode, Intent data) {

LogUtils.getInstance().e(getClass(), "onActivityResult " + resultCode);

switch (requestCode) {

case REQUEST_CONNECT_DEVICE:

// 当DeviceListActivity返回与设备连接的消息

if (resultCode == Activity.RESULT_OK) {

// 连接设备的MAC地址

String address = data.getExtras().getString(

DeviceListActivity.EXTRA_DEVICE_ADDRESS);

// 得到蓝牙对象

BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);

// 开始连接设备

mChatService.connect(device);

}

break;

case REQUEST_ENABLE_BT:

// 判断蓝牙是否启用

if (resultCode == Activity.RESULT_OK) {

// 建立连接

setupChat();

} else {

LogUtils.getInstance().e(getClass(), "蓝牙未启用");

Toast.makeText(this, R.string.bt_not_enabled_leaving,

Toast.LENGTH_SHORT).show();

finish();

}

}

}

在此,我将重点介绍下BluetoothChatService类中的连接流程;

因为蓝牙聊天是两个手机之间进行通讯,所以他们互为主机和从机,主要思路以及步骤如下:

1.开一个线程获取socket去连接蓝牙;

2.开一个线程获监听蓝牙传入的连接,如果连接被接受的话,再开启第三个线程去处理所有传入和传出的数据;

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);

}

开线程去连接

/**

* @description:蓝牙连接线程

* @author:zzq

* @time: 2016-8-6 下午1:18:41

*/

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) {

LogUtils.getInstance().e(getClass(), "socket获取失败:" + e);

}

mmSocket = tmp;

}

public void run() {

LogUtils.getInstance().e(getClass(), "开始mConnectThread");

setName("ConnectThread");

// mAdapter.cancelDiscovery();

try {

mmSocket.connect();

} catch (IOException e) {

// 连接失败,更新ui

connectionFailed();

try {

mmSocket.close();

} catch (IOException e2) {

LogUtils.getInstance().e(getClass(), "关闭连接失败" + e2);

}

// 开启聊天接收线程

startChat();

return;

}

synchronized (BluetoothChatService.this) {

mConnectThread = null;

}

connected(mmSocket, mmDevice);

}

public void cancel() {

try {

mmSocket.close();

} catch (IOException e) {

LogUtils.getInstance().e(getClass(), "关闭连接失败" + e);

}

}

}

/**

* 监听传入的连接

*/

private class AcceptThread extends Thread {

private final BluetoothServerSocket mmServerSocket;

public AcceptThread() {

BluetoothServerSocket tmp = null;

try {

tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);

} catch (IOException e) {

LogUtils.getInstance().e(getClass(), "--获取socket失败:" + e);

}

mmServerSocket = tmp;

}

public void run() {

setName("AcceptThread");

BluetoothSocket socket = null;

while (mState != STATE_CONNECTED) {

LogUtils.getInstance().e(getClass(), "----accept-循环执行中-");

try {

socket = mmServerSocket.accept();

} catch (IOException e) {

LogUtils.getInstance().e(getClass(), "accept() 失败" + e);

break;

}

// 如果连接被接受

if (socket != null) {

synchronized (BluetoothChatService.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) {

LogUtils.getInstance().e(getClass(),"不能关闭这些连接" + e);

}

break;

}

}

}

}

LogUtils.getInstance().e(getClass(), "结束mAcceptThread");

}

public void cancel() {

LogUtils.getInstance().e(getClass(), "取消 " + this);

try {

mmServerSocket.close();

} catch (IOException e) {

LogUtils.getInstance().e(getClass(), "关闭失败" + e);

}

}

}

/**

* 连接成功后的线程 处理所有传入和传出的传输

*/

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;

// 得到BluetoothSocket输入和输出流

try {

tmpIn = socket.getInputStream();

tmpOut = socket.getOutputStream();

} catch (IOException e) {

LogUtils.getInstance().e(getClass(),"temp sockets not created" + e);

}

mmInStream = tmpIn;

mmOutStream = tmpOut;

}

public void run() {

int bytes;

String str1 = "";

// 循环监听消息

while (true) {

try {

byte[] buffer = new byte[256];

bytes = mmInStream.read(buffer);

String readStr = new String(buffer, 0, bytes);// 字节数组直接转换成字符串

String str = bytes2HexString(buffer).replaceAll("00", "").trim();

if (bytes > 0) {// 将读取到的消息发到主线程

mHandler.obtainMessage(BluetoothChatActivity.MESSAGE_READ, bytes, -1,buffer).sendToTarget();

} else {

LogUtils.getInstance().e(getClass(),"disconnected");

connectionLost();

if (mState != STATE_NONE) {

LogUtils.getInstance().e(getClass(), "disconnected");

startChat();

}

break;

}

} catch (IOException e) {

LogUtils.getInstance().e(getClass(), "disconnected" + e);

connectionLost();

if (mState != STATE_NONE) {

// 在重新启动监听模式启动该服务

startChat();

}

break;

}

}

}

/**

* 写入OutStream连接

*

* @param buffer

* 要写的字节

*/

public void write(byte[] buffer) {

try {

mmOutStream.write(buffer);

// 把消息传给UI

mHandler.obtainMessage(BluetoothChatActivity.MESSAGE_WRITE, -1,-1, buffer).sendToTarget();

} catch (IOException e) {

LogUtils.getInstance().e(getClass(),

"Exception during write:" + e);

}

}

public void cancel() {

try {

mmSocket.close();

} catch (IOException e) {

LogUtils.getInstance().e(getClass(),"close() of connect socket failed:" + e);

}

}

}

大概的流程就是上面三个线程里面所展现的,当然具体情况,根据项目来,比如蓝牙协议协议解析这块的根据协议定义的方式来进行解析;

代码中牵扯的到的蓝牙连接状态的改变,用到的handle,直接把状态发送至activity,通知activity更新;

/**

* 无法连接,通知Activity

*/

private void connectionFailed() {

setState(STATE_LISTEN);

Message msg = mHandler.obtainMessage(BluetoothChatActivity.MESSAGE_TOAST);

Bundle bundle = new Bundle();

bundle.putString(BluetoothChatActivity.TOAST, "无法连接设备");

msg.setData(bundle);

mHandler.sendMessage(msg);

}

/**

* 设备断开连接,通知Activity

*/

private void connectionLost() {

Message msg = mHandler.obtainMessage(BluetoothChatActivity.MESSAGE_TOAST);

Bundle bundle = new Bundle();

bundle.putString(BluetoothChatActivity.TOAST, "设备断开连接");

msg.setData(bundle);

mHandler.sendMessage(msg);

}

当点击发送按钮时,将文本输入框中的文字发送数据的方法:

private void sendMessage(String message) {

if (mChatService.getState() != BluetoothChatService.STATE_CONNECTED) {

Toast.makeText(this, R.string.not_connected,Toast.LENGTH_SHORT).show();

return;

}

if (message.length() > 0) {

byte[] send = message.getBytes();

mChatService.write(send);

}

}

//调用BluetoothChatService类中的write进行数据发送

public void write(byte[] out) {

ConnectedThread r;

synchronized (this) {

if (mState != STATE_CONNECTED)

return;

r = mConnectedThread;

}

r.write(out);

}

如此,蓝牙聊天的流程就是这样,如果退出聊天的时候,停止所有线程;

public synchronized void stop() {

LogUtils.getInstance().e(getClass(), "---stop()");

setState(STATE_NONE);

if (mConnectThread != null) {

mConnectThread.cancel();

mConnectThread = null;

}

if (mConnectedThread != null) {

mConnectedThread.cancel();

mConnectedThread = null;

}

if (mAcceptThread != null) {

mAcceptThread.cancel();

mAcceptThread = null;

}

}

相信看完本篇文章,在安卓蓝牙连接这块应该问题不大了(spp协议)。

源码地址:点我查看源码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

以上是 Android实现蓝牙聊天功能 的全部内容, 来源链接: utcz.com/p/240632.html

回到顶部