蓝牙能在移动电话、PDA、无线耳机、笔记本电脑、相关外设等众多设备之间进行无线信息交换。利用“蓝牙”技术,能够有效地简化移动通信终端设备之间的通信,也能够成功地简化设备与Internet之间的通信,从而数据传输变得更加迅速高效,为无线通信拓宽道路。
在最近项目中,用到了android机器蓝牙同硬件通信,所以在此举个小例子总结一下。结构同上次介绍ch34串口差不多,大家有兴趣可以去看看https://blog.csdn.net/weixin_35959554/article/details/85262658
在下拙见通信细分为几个步骤:
第一当然是开启权限了:
第二获取到设备搜索到已配对的蓝牙列表:
// 得到蓝牙适配器对象
_bluetooth = BluetoothAdapter.getDefaultAdapter();
// 得到所有设备
devices = _bluetooth.getBondedDevices();
if (devices != null && devices.size() > 0) {
//默认获取第一个配对成功的蓝牙设备
for (BluetoothDevice dev : devices) {
_device = dev;
break;
}
}
第三设置连接协议:
设置协议时,必须使用android的SSP(协议栈默认)的UUID:00001101-0000-1000-8000-00805F9B34FB才能正常和外部的,也是SSP串口的蓝牙设备去连接。
String MY_UUID = "00001101-0000-1000-8000-00805F9B34FB";
//选择连接的协议
_socket = _device.createRfcommSocketToServiceRecord(UUID.fromString(MY_UUID));
第四开启连接获取输入流:
try {
if (!_socket.isConnected()) {
//发起连接请求
_socket.connect();
}
} catch (IOException e) {
sentConMsg("蓝牙连接异常");
return;
}
try {
//获取输入流
if (_socket.getInputStream() != null) {
inStream = _socket.getInputStream();
} else {
sentConMsg("蓝牙输入流为空");
return;
}
//获取输出流
if (_socket.getOutputStream() != null) {
outStream = _socket.getOutputStream();
} else {
sentConMsg("蓝牙输出流为空");
return;
}
} catch (IOException e) {
sentConMsg("蓝牙输入输出数据异常");
return;
}
第五开启线程读取数据:
//读取线程
private class ReadThread extends Thread {
public void run() {
try {
while (IsStart) {
int size = inStream.available();
if (size > 0) {
sentConMsg("蓝牙连接成功");
byte[] buf = new byte[size];
inStream.read(buf, 0, buf.length);
sentData(buf);
_Datatime = 0;
} else {
//数据为空时 开始断开计时
if (_Timer == null) {
_Timer = new Timer();
_Timer.schedule(new DataTimer(), 0, 1000);
}
continue;
}
}
} catch (Exception ex) {
}
}
}
只要完成上面几个步骤,那么数据应该就是可以读到了。
发送数据时一个方法就行了:
//发送数据
public void send(byte[] data) {
try {
if (outStream != null) {
outStream.write(data);
}
} catch (IOException e) {
e.printStackTrace();
}
}
当然要做就要做的运用起来方便一些,所以在读取类里面我写了两个接口,一个是发送现在蓝牙的连接状态,一个是读到的数据,在activity里面只需要实现这两个接口,那么就可以很方便的显示数据在界面上了。
//发送数据
private void sentData(byte[] bytes) {
Message message = Message.obtain();
message.obj = bytes;
DataHandler.sendMessage(message);
}
/**
* 数据传输事件
*/
private List lsDatas;
public void addGetData(GetDataListener dataListener) {
if (lsDatas == null) {
lsDatas = new ArrayList<>();
}
lsDatas.add(dataListener);
}
public void removeGetData(GetDataListener dataListener) {
if (lsDatas == null) {
lsDatas = new ArrayList<>();
}
lsDatas.remove(dataListener);
}
private Handler DataHandler = new Handler() {
public void handleMessage(Message msg) {
if (lsDatas == null)
return;
for (GetDataListener item : lsDatas) {
item.getData((byte[]) msg.obj);
}
}
};
//发送状态
private void sentConMsg(String msg) {
Message message = Message.obtain();
message.obj = msg;
ConnetHandler.sendMessage(message);
}
/**
* 连接状态事件
*/
private List lstConnect;
public void addConnectState(ConnectStateListener connectStateListener) {
if (lstConnect == null) {
lstConnect = new ArrayList<>();
}
lstConnect.add(connectStateListener);
}
public void removeConnectState(ConnectStateListener connectStateListener) {
if (lstConnect == null) {
lstConnect = new ArrayList<>();
}
lstConnect.remove(connectStateListener);
}
private Handler ConnetHandler = new Handler() {
public void handleMessage(Message msg) {
if (lstConnect == null)
return;
for (ConnectStateListener item : lstConnect) {
item.ConnectState((String) msg.obj);
}
}
};
当然在最后不使用蓝牙时也得关闭蓝牙回收资源:
try {
if (_socket != null) {
// 关闭BluetoothSocket请求端。
_socket.close();
_socket = null;
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (inStream != null) {
inStream.close();
}
if (outStream != null) {
outStream.close();
}
if (_device != null) {
_device = null;
}
多的不说,大部分重要的就是上面那些,我就直接上我封装的一个操作类,注释也很详细的,大家可以看看
public class BluetoothHelper {
//连接的协议
private String MY_UUID = "00001101-0000-1000-8000-00805F9B34FB";
private static BluetoothHelper bluetoothHelper;
private static Context context;
private BluetoothAdapter _bluetooth ;
private static BluetoothDevice _device = null;
private static BluetoothSocket _socket = null;
private InputStream inStream = null;
private OutputStream outStream = null;
private boolean IsStart = false;
private ReadThread bluThread;
private Timer _Timer = null;
private int _Datatime = 0;
Set devices;
public static BluetoothHelper getInstance(Context con) {
if (null == bluetoothHelper) {
bluetoothHelper = new BluetoothHelper();
context = con;
}
return bluetoothHelper;
}
//在3秒内持续没有数据 那么判定蓝牙断开
private class DataTimer extends TimerTask {
@Override
public void run() {
_Datatime++;
if (_Datatime > 3) {
sentConMsg("蓝牙已断开");
}
}
}
//得到当前连接蓝牙名称
public String getDeviceName() {
if (_device != null) {
return _device.getName();
}
return "";
}
//得到已配对蓝牙列表
public Set getDevices() {
if (devices != null) {
return devices;
}
return new HashSet<>();
}
//打开蓝牙连接
public void open() {
sentConMsg("正在搜索蓝牙设备");
// 得到蓝牙适配器对象
_bluetooth = BluetoothAdapter.getDefaultAdapter();
// 得到所有设备
devices = _bluetooth.getBondedDevices();
if (devices != null && devices.size() > 0) {
//默认获取第一个配对成功的蓝牙设备
for (BluetoothDevice dev : devices) {
_device = dev;
break;
}
}
if (_device == null) {
sentConMsg("没有搜索到已配对成功的蓝牙");
return;
}
try {
sentConMsg("正在连接蓝牙设备");
//选择连接的协议
_socket = _device.createRfcommSocketToServiceRecord(UUID.fromString(MY_UUID));
} catch (IOException e) {
sentConMsg("蓝牙初始化端口异常");
return;
}
try {
if (!_socket.isConnected()) {
//发起连接请求
_socket.connect();
}
} catch (IOException e) {
sentConMsg("蓝牙连接异常");
return;
}
try {
//获取输入流
if (_socket.getInputStream() != null) {
inStream = _socket.getInputStream();
} else {
sentConMsg("蓝牙输入流为空");
return;
}
//获取输出流
if (_socket.getOutputStream() != null) {
outStream = _socket.getOutputStream();
} else {
sentConMsg("蓝牙输出流为空");
return;
}
} catch (IOException e) {
sentConMsg("蓝牙输入输出数据异常");
return;
}
IsStart = true;
//开启线程读数据
if (bluThread == null) {
bluThread = new ReadThread();
bluThread.start();
}
}
//关闭蓝牙连接
public void close() {
if (_Timer != null) {
_Timer.cancel();
_Timer = null;
_Datatime = 0;
}
try {
if (_socket != null) {
// 关闭BluetoothSocket请求端。
_socket.close();
_socket = null;
}
} catch (IOException e) {
e.printStackTrace();
}
if (bluThread != null) {
bluThread.interrupt();
bluThread = null;
}
IsStart = false;
try {
if (inStream != null) {
inStream.close();
}
if (outStream != null) {
outStream.close();
}
if (_device != null) {
_device = null;
}
} catch (IOException e) {
e.printStackTrace();
}
}
//发送数据
public void send(byte[] data) {
try {
if (outStream != null) {
outStream.write(data);
}
} catch (IOException e) {
e.printStackTrace();
}
}
//读取线程
private class ReadThread extends Thread {
public void run() {
try {
while (IsStart) {
int size = inStream.available();
if (size > 0) {
sentConMsg("蓝牙连接成功");
byte[] buf = new byte[size];
inStream.read(buf, 0, buf.length);
sentData(buf);
_Datatime = 0;
} else {
//数据为空时 开始断开计时
if (_Timer == null) {
_Timer = new Timer();
_Timer.schedule(new DataTimer(), 0, 1000);
}
continue;
}
}
} catch (Exception ex) {
}
}
}
//发送数据
private void sentData(byte[] bytes) {
Message message = Message.obtain();
message.obj = bytes;
DataHandler.sendMessage(message);
}
/**
* 数据传输事件
*/
private List lsDatas;
public void addGetData(GetDataListener dataListener) {
if (lsDatas == null) {
lsDatas = new ArrayList<>();
}
lsDatas.add(dataListener);
}
public void removeGetData(GetDataListener dataListener) {
if (lsDatas == null) {
lsDatas = new ArrayList<>();
}
lsDatas.remove(dataListener);
}
private Handler DataHandler = new Handler() {
public void handleMessage(Message msg) {
if (lsDatas == null)
return;
for (GetDataListener item : lsDatas) {
item.getData((byte[]) msg.obj);
}
}
};
//发送状态
private void sentConMsg(String msg) {
Message message = Message.obtain();
message.obj = msg;
ConnetHandler.sendMessage(message);
}
/**
* 连接状态事件
*/
private List lstConnect;
public void addConnectState(ConnectStateListener connectStateListener) {
if (lstConnect == null) {
lstConnect = new ArrayList<>();
}
lstConnect.add(connectStateListener);
}
public void removeConnectState(ConnectStateListener connectStateListener) {
if (lstConnect == null) {
lstConnect = new ArrayList<>();
}
lstConnect.remove(connectStateListener);
}
private Handler ConnetHandler = new Handler() {
public void handleMessage(Message msg) {
if (lstConnect == null)
return;
for (ConnectStateListener item : lstConnect) {
item.ConnectState((String) msg.obj);
}
}
};
}
activity代码如下,可以看看是怎么调用的:
ublic class MainActivity extends AppCompatActivity implements View.OnClickListener, ConnectStateListener, GetDataListener {
private EditText readText, writeText;
private TextView connectText;
private Button writeButton, openButton, CloseButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initData();
}
//初始化连接以及数据传输事件
private void initData() {
BluetoothHelper.getInstance(this).addConnectState(this);
BluetoothHelper.getInstance(this).addGetData(this);
}
//设置连接状态显示
@Override
public void ConnectState(String s) {
if (s != null && s.length() > 0)
connectText.setText(s);
}
//设置接收数据显示
@Override
public void getData(byte[] bytes) {
if (bytes != null && bytes.length > 0) {
readText.setText(bytes2HexString(bytes));
}
}
private void initView() {
connectText = (TextView) findViewById(R.id.ConectValues);
readText = (EditText) findViewById(R.id.ReadValues);
writeText = (EditText) findViewById(R.id.WriteValues);
writeButton = (Button) findViewById(R.id.WriteButton);
openButton = (Button) findViewById(R.id.OpenButton);
CloseButton = (Button) findViewById(R.id.CloseButton);
CloseButton.setOnClickListener(this);
writeButton.setOnClickListener(this);
openButton.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.OpenButton:
BluetoothHelper.getInstance(this).open();
break;
case R.id.WriteButton:
byte[] to_send = toByteArray(writeText.getText().toString());
BluetoothHelper.getInstance(this).send(to_send);
break;
case R.id.CloseButton:
BluetoothHelper.getInstance(this).close();
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
BluetoothHelper.getInstance(this).removeConnectState(this);
BluetoothHelper.getInstance(this).removeGetData(this);
BluetoothHelper.getInstance(this).close();
}
/**
* 将String转化为byte[]数组
*
* @param arg 需要转换的String对象
* @return 转换后的byte[]数组
*/
private byte[] toByteArray(String arg) {
if (arg != null) {
/* 1.先去除String中的' ',然后将String转换为char数组 */
char[] NewArray = new char[1000];
char[] array = arg.toCharArray();
int length = 0;
for (int i = 0; i < array.length; i++) {
if (array[i] != ' ') {
NewArray[length] = array[i];
length++;
}
}
/* 将char数组中的值转成一个实际的十进制数组 */
int EvenLength = (length % 2 == 0) ? length : length + 1;
if (EvenLength != 0) {
int[] data = new int[EvenLength];
data[EvenLength - 1] = 0;
for (int i = 0; i < length; i++) {
if (NewArray[i] >= '0' && NewArray[i] <= '9') {
data[i] = NewArray[i] - '0';
} else if (NewArray[i] >= 'a' && NewArray[i] <= 'f') {
data[i] = NewArray[i] - 'a' + 10;
} else if (NewArray[i] >= 'A' && NewArray[i] <= 'F') {
data[i] = NewArray[i] - 'A' + 10;
}
}
/* 将 每个char的值每两个组成一个16进制数据 */
byte[] byteArray = new byte[EvenLength / 2];
for (int i = 0; i < EvenLength / 2; i++) {
byteArray[i] = (byte) (data[i * 2] * 16 + data[i * 2 + 1]);
}
return byteArray;
}
}
return new byte[]{};
}
/* *
* @param bytes 字节数组
* @return 16进制大写字符串
*/
public static String bytes2HexString(byte[] bytes) {
if (bytes == null) return null;
int len = bytes.length;
if (len <= 0) return null;
char[] ret = new char[len << 1];
for (int i = 0, j = 0; i < len; i++) {
ret[j++] = hexDigits[bytes[i] >>> 4 & 0x0f];
ret[j++] = hexDigits[bytes[i] & 0x0f];
}
return new String(ret);
}
private static final char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
}
布局文件就不贴了(感觉贴了太多代码了。。。。。),以上就是我分享的一些蓝牙通信技术,可能理解不太深刻有可能又讲错的,莫怪莫怪