传统蓝牙适用于较为耗电的操作,其中包括 Android 设备之间的流式传输和通信等。针对具有低功耗要求的蓝牙设备,Android 4.3(API 级别 18)中引入了面向低功耗蓝牙的 API 支持。因为项目需求,编写了关于传统蓝牙的demo,实现了蓝牙多连,蓝牙间信息发送与接收,有不对的地方,望指导,大家一起学习,谢谢!
大概效果如下:
安卓传统蓝牙多连接,消息接送#戏精上身的我#_腾讯视频
go!go!go!
首先权限问题
如要在应用中使用蓝牙功能,您必须声明两个权限。第一个是 BLUETOOTH。您需要此权限才能执行任何蓝牙通信,例如请求连接、接受连接和传输数据等。
第二个必须声明的权限是 ACCESS_FINE_LOCATION。您的应用需要此权限,因为蓝牙扫描可用于收集用户的位置信息。此类信息可能来自用户自己的设备,以及在商店和交通设施等位置使用的蓝牙信标。
如果您想让应用启动设备发现或操纵蓝牙设置,则除了 BLUETOOTH 权限以外,您还必须声明 BLUETOOTH_ADMIN 权限。大多数应用只是需利用此权限发现本地蓝牙设备。除非应用是根据用户请求修改蓝牙设置的“超级管理员”,否则不应使用此权限所授予的其他功能。
在您的应用清单文件中声明蓝牙权限。例如:
1.蓝牙帮助类 BlueToothUtils
public class BlueToothUtils implements BlueToothUtilsBroadcastReceiver.BlueToothUtilsBroadcastReceiverListener {
private static BlueToothUtilsblueToothUtils;
public synchronized static BlueToothUtilsgetInstance(Activity activity) {
if (null ==blueToothUtils) {
blueToothUtils =new BlueToothUtils(activity);
}
return blueToothUtils;
}
private BluetoothAdapterbluetoothAdapter;
private BluetoothServerSocketmmServerSocket;
private Threadthread;
private boolean isRunning =false;
private final Stringlock ="lock";
private final Stringlock2 ="lock2";
private BlueToothUtilsBroadcastReceiverblueToothUtilsBroadcastReceiver;
private MapstringBluetoothSocketMap;
private BlueToothUtilsListenerlistener;
private StringIMEI;
private Activitycontext;
public BlueToothUtils(Activity context) {
this.context = context;
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
stringBluetoothSocketMap =new HashMap<>();
IMEI =bluetoothAdapter.getName();
registerBlueStateReceiver();
if (null !=bluetoothAdapter) {
try {
mmServerSocket =bluetoothAdapter.listenUsingRfcommWithServiceRecord(IMEI, UUID.nameUUIDFromBytes(IMEI.getBytes()));
}catch (IOException e) {
e.printStackTrace();
}
}
}
private void registerBlueStateReceiver() {
blueToothUtilsBroadcastReceiver =new BlueToothUtilsBroadcastReceiver();
blueToothUtilsBroadcastReceiver.setOnBlueToothUtilsBroadcastReceiverListener(this);
IntentFilter intentFilter =new IntentFilter();
// 监视蓝牙关闭和打开的状态
intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
// 监视蓝牙设备与APP连接的状态
intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
intentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
// 注册广播
context.registerReceiver(blueToothUtilsBroadcastReceiver, intentFilter);
}
public void start() {
synchronized (lock) {
if (null ==mmServerSocket) {
return;
}
if (isRunning)return;
isRunning =true;
thread =new Thread(() -> {
while (isRunning) {
try {
BluetoothSocket socket =mmServerSocket.accept();
BluetoothDevice remoteDevice = socket.getRemoteDevice();
String name = remoteDevice.getName();
addSocket(name, socket);
receiveMessage(name);
}catch (IOException e) {
e.printStackTrace();
}
}
});
thread.start();
}
}
public void receiveMessage(String name) {
synchronized (lock2) {
if (null ==stringBluetoothSocketMap)return;
if (!stringBluetoothSocketMap.containsKey(name))return;
BlueToothEntity blueToothEntity =stringBluetoothSocketMap.get(name);
if (null == blueToothEntity)return;
if (!blueToothEntity.isRunning()) {
blueToothEntity.startListener();
}
}
}
public void addSocket(String key, BluetoothSocket socket) {
synchronized (lock2) {
if (TextUtils.isEmpty(key) ||null == socket)return;
if (null ==stringBluetoothSocketMap) {
stringBluetoothSocketMap =new HashMap<>();
}
stringBluetoothSocketMap.put(key, new BlueToothEntity(socket, listener));
}
}
public void sendMessage(String message) {
synchronized (lock2) {
if (null ==stringBluetoothSocketMap ||stringBluetoothSocketMap.size() ==0)return;
Log.e("阿斯达所asdas0", "sendMessage");
for (BlueToothEntity blueToothEntity :stringBluetoothSocketMap.values()) {
blueToothEntity.sendMessage(message);
}
}
}
public void connect(BluetoothDevice device) {
MyThreadPool.getInstance().newThread(() -> {
try {
String name =device.getName().trim();
BluetoothSocket tmp =device.createRfcommSocketToServiceRecord(UUID.nameUUIDFromBytes(name.getBytes()));
tmp.connect();
addSocket(name, tmp);
receiveMessage(name);
}catch (IOException e) {
e.printStackTrace();
}
});
}
public void setOnBlueTo