蓝牙通信的简要设计与开发
Posted 林颖宝贝
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了蓝牙通信的简要设计与开发相关的知识,希望对你有一定的参考价值。
蓝牙通信的简要设计与开发
蓝牙通信步骤
具体步骤
1,首先开启蓝牙
2、搜索可用设备
3、创建蓝牙socket,获取输入输出流
4、读取和写入数据
5、断开连接关闭蓝牙
过程图及其文字描述
1.执行oncreate方法打开蓝牙,不需要经过用户的同意;
2.通过注册广播接收器获取搜索到的蓝牙设备,在列表上显示搜索到的设备;
3.点击所显示的设备调连接蓝牙的代码请求连接!
4.连接具体解释,连接时和socket聊天的方式近似;
5在此做出假设;假设蓝牙设备A向蓝牙设备B发送一串文字;首先调用相关的蓝牙连接代码建立连接;
6获取输出流通过socket发送数据到另外—个蓝牙设备;需要设置发送时的ID∶定义类似端口类型的;
7.接收端设备B需要获取输入流读取蓝牙设备A发送过来的消息;然后在界面上显示;
蓝牙通信原理
首先要知道几个类
BluetoothAdapter:代表本地蓝牙适配器(蓝牙无线电)。BluetoothAdapter是所有蓝牙交互的入口。使用这个你可以发现其他蓝牙设备,查询已配对的设备列表,使用一个已知的MAC地址来实例化一个BluetoothDevice,以及创建一个BluetoothServerSocket来为监听与其他设备的通信。
BluetoothGatt:BluetoothGatt作为中央来使用和处理数据,使用时有一个回调方法BluetoothGattCallback返回中央的状态和周边提供的数据
BluetoothDevice:代表一个远程蓝牙设备,使用这个来请求一个与远程设备的BluetoothSocket连接,或者查询关于设备名称、地址、类和连接状态等设备信息。
BluetoothCattService:BluetoothCattService作为周边来提供数据
BluetoothCattCharacteristic:BluetoothCattCharacteristic是蓝牙设备的特征
BluetoothGattServerCallback:BluetoothGattServerCallback返回周边的状态
蓝牙客户端socket工作步骤
1、创建客户端蓝牙Sokcet
2、创建连接
3、读写数据
4、关闭
蓝牙服务端socket工作步骤
1、创建服务端蓝牙Socket
2、绑定端口号(蓝牙忽略)
3、创建监听listen(蓝牙忽略, 蓝牙没有此监听,而是通过whlie(true)死循环来一直监听的)
4、通过accept(),如果有客户端连接,会创建一个新的Socket,体现出并发性,可以同时与多个socket通讯)
5、读写数据
6、关闭
android Studio实现
配置权限
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
状态描述文本及配色
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">MyBluetooth</string>
<string name="send">发送</string>
<string name="not_connected">你没有链接一个设备</string>
<string name="bt_not_enabled_leaving">蓝牙不可用,离开聊天室</string>
<string name="title_connecting">链接中...</string>
<string name="title_connected_to">连接到:</string>
<string name="title_not_connected">无链接</string>
<string name="scanning">蓝牙设备搜索中...</string>
<string name="select_device">选择一个好友链接</string>
<string name="none_paired">没有配对好友</string>
<string name="none_found">附近没有发现好友</string>
<string name="title_paired_devices">已配对好友</string>
<string name="title_other_devices">其它可连接好友</string>
<string name="button_scan">搜索好友</string>
<string name="connect">我的好友</string>
<string name="discoverable">设置在线</string>
<string name="back">退出</string>
<string name="startVideo">开始聊天</string>
<string name="stopVideo">结束聊天</string>
</resources>
蓝牙服务
public class ChatService
//本应用的主Activity组件名称
private static final String NAME = "BluetoothChat";
// UUID:通用唯一识别码,是一个128位长的数字,一般用十六进制表示
//算法的核心思想是结合机器的网卡、当地时间、一个随机数来生成
//在创建蓝牙连接
private static final UUID MY_UUID = UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
private final BluetoothAdapter mAdapter;
private final Handler mHandler;
private AcceptThread mAcceptThread;
private ConnectThread mConnectThread;
private ConnectedThread mConnectedThread;
private int mState;
public static final int STATE_NONE = 0;
public static final int STATE_LISTEN = 1;
public static final int STATE_CONNECTING = 2;
public static final int STATE_CONNECTED = 3;
//构造方法,接收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)
eAndroid蓝牙开发——实现蓝牙聊天