本文主要介绍,蓝牙开启、蓝牙扫描、配对,建立链接,进行通信。
1.声明权限:
2.获取蓝牙适配器:
// 获取蓝牙配置器 BluetoothAdapter 方式1.
BluetoothManager bluetoothManger =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
bluetoothAdapter = bluetoothManger.getAdapter();
//方式2
// bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
3.开启蓝牙:
if (!bluetoothAdapter.isEnabled()) {
// 没有开启蓝牙 开启蓝牙
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
4.动态申请权限:
//判断是否有访问位置的权限,没有权限,直接申请位置权限
if ((checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
|| (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)) {
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, 200);
}
5.创建蓝牙结果列表,并添加点击事件。
// 创建设备列表适配器
deviceListAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1);
deviceListView = (ListView) findViewById(R.id.device_list);
deviceListView.setAdapter(deviceListAdapter);
deviceListView.setOnItemClickListener((adapterView, view, i, l) -> {
if (bluetoothAdapter.isDiscovering()) {
bluetoothAdapter.cancelDiscovery();
}
String deviceName = deviceListAdapter.getItem(i);
Log.e("nyz", "deviceName " + deviceName);
selectedDevice = bluetoothAdapter.getRemoteDevice(deviceName.split("\\n")[1]);
Log.e("nyz", "name " + selectedDevice.getName());
Log.e("nyz", "address " + selectedDevice.getAddress());
ParcelUuid[] uuids = selectedDevice.getUuids();
for (int index = 0; index < uuids.length; index++) {
Log.e("nyz", "uuids " + uuids[index]);
}
connectToDevice(selectedDevice);
});
6.创建广播接受者,用于接收扫描到蓝牙后的结果。
@SuppressLint("MissingPermission")
private final BroadcastReceiver deviceReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.e("nyz", "action " + action);
// 当有新设备被发现时
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
deviceListAdapter.notifyDataSetChanged();
if (!TextUtils.isEmpty(device.getName())) {
deviceListAdapter.add(device.getName() + "\n" + device.getAddress());
}
}
// 做配对使用
else if (BluetoothDevice.ACTION_PAIRING_REQUEST.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
int pairingVariant = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, BluetoothDevice.ERROR);
// 如果需要 PIN 码,可以在这里自动输入
if (pairingVariant == BluetoothDevice.PAIRING_VARIANT_PIN) {
device.setPin("1234".getBytes()); // 替换为您的 PIN 码
}
// 如果需要用户确认配对请求,可以在这里显示对话框来请求用户确认
} else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR);
int previousBondState = intent.getIntExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, BluetoothDevice.ERROR);
// 配对状态改变的处理逻辑
if (bondState == BluetoothDevice.BOND_BONDED && previousBondState == BluetoothDevice.BOND_BONDING) {
// 配对成功
} else if (bondState == BluetoothDevice.BOND_NONE && previousBondState == BluetoothDevice.BOND_BONDED) {
// 配对解除
}
} else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
Log.e("nyz", "搜索开始..");
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
Log.e("nyz", "搜索结束..");
} else if (BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED.equals(action)) {
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, BluetoothAdapter.ERROR);
if (state == BluetoothAdapter.STATE_CONNECTING) {
Log.e("nyz", "正在链接...");
} else if (state == BluetoothAdapter.STATE_CONNECTED) {
// Log.e("nyz", "链接成功...");
// InputStream inputStream = null;
// try {
// inputStream = bluetoothSocket.getInputStream();
// OutputStream outputStream = bluetoothSocket.getOutputStream();
// Log.e("nyz", "inputStream " + (inputStream != null));
// Log.e("nyz", "outputStream " + (outputStream != null));
// Log.e("nyz", "获取流成功..");
// } catch (IOException e) {
// e.printStackTrace();
// }
} else if (state == BluetoothAdapter.STATE_DISCONNECTED) {
Log.e("nyz", "断开链接...");
}
}
}
};
7.注册和反注册:
// 注册广播
public void registerBroadcast() {
// 注册广播接收器
IntentFilter intent = new IntentFilter();
intent.addAction(BluetoothDevice.ACTION_FOUND);//搜索发现设备
intent.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);//状态改变
intent.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);//配对请求
intent.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);//行动扫描模式改变了
intent.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);//动作状态发生了变化
intent.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//搜索结束
intent.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);//开始搜索
intent.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);//链接状态变化
registerReceiver(deviceReceiver, intent);
}
@Override
protected void onDestroy() {
super.onDestroy();
// 取消注册广播接收器
unregisterReceiver(deviceReceiver);
}
8.开始搜索附近蓝牙设备:
bluetoothAdapter.startDiscovery,搜索结束后,会通过广播的形式来接收。
bluetoothAdapter.getBondedDevices() 返回的是已经配对过的蓝牙设备列表。
private void startDeviceDiscovery() {
deviceListAdapter.clear();
int state = bluetoothAdapter.getState();
Log.e("nyz", "state " + state);
boolean b = bluetoothAdapter.startDiscovery();
Log.e("nyz", "bluetooth state " + b);
//获取已经连接过的设备。
Set bondedDevices = bluetoothAdapter.getBondedDevices();
for (BluetoothDevice device : bondedDevices) {
Log.e("nyz", "device " + device.getName());
deviceListAdapter.add(device.getName() + "\n" + device.getAddress());
deviceListAdapter.notifyDataSetChanged();
}
}
9.附近蓝牙设备结果:添加到列表中。
// 当有新设备被发现时
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
deviceListAdapter.notifyDataSetChanged();
if (!TextUtils.isEmpty(device.getName())) {
deviceListAdapter.add(device.getName() + "\n" + device.getAddress());
}
}
10.点击列表中的蓝牙进行配对链接,没有配对过的需要配对,已经配对过的,可以直接链接。
1)点击事件
deviceListView.setOnItemClickListener((adapterView, view, i, l) -> {
//当点击某个蓝牙列表时,需要停止扫描,减少性能的消耗
if (bluetoothAdapter.isDiscovering()) {
bluetoothAdapter.cancelDiscovery();
}
String deviceName = deviceListAdapter.getItem(i);
Log.e("nyz", "deviceName " + deviceName);
selectedDevice = bluetoothAdapter.getRemoteDevice(deviceName.split("\\n")[1]);
Log.e("nyz", "name " + selectedDevice.getName());
Log.e("nyz", "address " + selectedDevice.getAddress());
ParcelUuid[] uuids = selectedDevice.getUuids();
for (int index = 0; index < uuids.length; index++) {
Log.e("nyz", "uuids " + uuids[index]);
}
//开始链接
connectToDevice(selectedDevice);
});
2)开始配对链接:
需要放在子线程中执行。
@SuppressLint("MissingPermission")
private void connectToDevice(BluetoothDevice device) {
new Thread() {
@Override
public void run() {
super.run();
UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); // SPP UUID for serial communication
try {
// 进行配对
if (!(device.getBondState() == BluetoothDevice.BOND_BONDED)) {
Log.e("nyz", "等待配对");
boolean success = device.createBond();
Log.e("nyz", "配对结果 " + success);
} else {
Log.e("nyz", "已经配对过");
}
// 等待配对完成
// Thread.sleep(500);
Log.e("nyz", "创建 socket");
bluetoothSocket = device.createRfcommSocketToServiceRecord(uuid);
Log.e("nyz", "connect...");
if (bluetoothSocket == null) {
Log.e("nyz", "connect...failed");
return;
} else {
Log.e("nyz", "socket 创建成功");
}
new Thread() {
@Override
public void run() {
super.run();
try {
bluetoothSocket.connect();
// 成功连接
Log.e("nyz", "链接成功...");
InputStream inputStream = bluetoothSocket.getInputStream();
OutputStream outputStream = bluetoothSocket.getOutputStream();
Log.e("nyz", "inputStream " + (inputStream != null));
Log.e("nyz", "outputStream " + (outputStream != null));
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
} catch (Exception e) {
Log.e("nyz", "conn failed");
e.printStackTrace();
}
}
}.start();
}
配对成功后, bluetoothSocket = device.createRfcommSocketToServiceRecord(uuid);
拿到一个一个Socket对象。
开始链接:
bluetoothSocket.connect();
// 成功连接
Log.e("nyz", "链接成功...");
InputStream inputStream = bluetoothSocket.getInputStream();
OutputStream outputStream = bluetoothSocket.getOutputStream();
Log.e("nyz", "inputStream " + (inputStream != null));
Log.e("nyz", "outputStream " + (outputStream != null));
链接成功后,可以从socket中拿到输入输出流,这样就可以和另外一台设计进行通信了。
和串口类似,串口通信,也是拿到一个输入输出流。
蓝牙通信官方文档:
蓝牙概览 | Connectivity | Android Developers