Android APP实现与串口蓝牙模块通讯,单次接收20bytes,发送10bytes
Android开发平台示例:BluetoothLeGatt
https://github.com/android/connectivity-samples/tree/main/BluetoothLeGatt/
1、设备是否支持蓝牙
//获取蓝牙适配器
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
// 说明此设备不支持蓝牙操作
Log.d(TAG, "onCreate: 设备不支持蓝牙操作");
Toast.makeText(this, "设备不支持蓝牙", Toast.LENGTH_SHORT).show();
//如果应用必须有蓝牙,则退出应用
finish();
}
2、设备是否开启蓝牙,未开启则开启蓝牙
// 检测蓝牙是否开启,开启蓝牙
if (!mBluetoothAdapter.isEnabled()) {
//未开启
//开启蓝牙
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENBLE_BT);
//系统会弹出是否同意打开窗口,用户点击后会回调onActivityResult
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_ENBLE_BT) {
if (resultCode == RESULT_OK) {
Toast.makeText(this, "点击了OK,蓝牙已经开启", Toast.LENGTH_SHORT).show();
} else if (resultCode == RESULT_CANCELED) {
Toast.makeText(this, "点击了取消,蓝牙没开启", Toast.LENGTH_SHORT).show();
//如果应用必须开启蓝牙,则退出应用
finish();
}
}
}
3、权限申请
AndroidManifest.xml 里面声明权限:
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-feature android:name="android.hardware.location.gps" />
<!-- 打开位置权限。如果应用没有位置权限,蓝牙扫描功能不能使用,需要动态申请(Build.VERSION.SDK_INT < 23 不需要) -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
4、查询手机已配对的设备
//通过 getBondedDevices() 来实现,这将返回表示已配对设备的一组 BluetoothDevice 。
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
Log.d(TAG, device.getName() + " " + device.getAddress());
}
}
5、创建扫描器
if (mBluetoothAdapter != null) {
BluetoothLeScanner mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner(); //获取扫描器
BluetoothLeScanner mSampleScanCallback = new SampleScanCallback(); //创建扫描回调
//注意:扫描回调只能创建一次,关闭扫描的时候也要使用同一回调,不然不能停止
}
private class SampleScanCallback extends ScanCallback {
@Override
public void onScanResult(int callbackType, ScanResult result) {} //得到扫描的设备
@Override
public void onBatchScanResults(List<ScanResult> results) {}
@Override
public void onScanFailed(int errorCode) {}
}
6、开始扫描
//蓝牙设备开始扫描 注意:扫描只能开启一次,不然不能停止。(可能是开几次就要关几次,没有验证)
private void bluetoothStartScanDevices() {
if (mBluetoothLeScanner != null) {
mBluetoothLeScanner.startScan(mSampleScanCallback);
}
}
7、停止扫描
private void bluetoothStopScanDevices() {
// 通过调用 BluetoothLeScanner.stopScan 可以停止正在进行的蓝牙扫描。
// 这里需要注意的是,传入的回调必须是开启蓝牙扫描时传入的回调,否则蓝牙扫描不会停止。
if (mBluetoothLeScanner != null) {
mBluetoothLeScanner.stopScan(mSampleScanCallback);
}
}
8、创建服务类BluetootheService
,用服务来管理蓝牙的连接与通讯
public class BluetoothLeService extends Service {
private final IBinder mBinder = new LocalBinder();
public class LocalBinder extends Binder {
public BluetoothLeService getService() {
return BluetoothLeService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
close();
return super.onUnbind(intent);
}
}
9、声明服务
AndroidManifest.xml 里面声明服务:
<application
<service android:name=".BluetoothManage.BluetoothLeService" android:enabled="true"/>
10、绑定服务,在Activity
里绑定,此Activity将收到服务的通知,并进行数据交互
Intent gattServiceIntent = new Intent(DevicesSearchActivity.this, BluetoothLeService.class);
boolean isOK = bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE); //绑定失败检查AndroidManifest是否有声明
private final ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) { //与服务连接完成
mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
mBluetoothLeService.connect(mDeviceAddress);
}
@Override
public void onServiceDisconnected(ComponentName name) { //与服务断开连接
mBluetoothLeService = null;
}
};
11、在Activity里注册广播接收器,接收服务发出的广播,后面有里面的详细处理
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {}
}
12、在服务类BluetootheService
里创建连接
public boolean connect(final String address) {
if (mBluetoothAdapter == null || address == null) { return false;}
if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress) && mBluetoothGatt != null) {
if (mBluetoothGatt.connect()) { mConnectionState = STATE_CONNECTING; return true; } else { return false;}
}
final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
if (device == null) { return false; }
mBluetoothGatt = device.connectGatt(this, true, mGattCallback);
return true;
}
13、连接回调
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { //连接状态改变调用
String intentAction;
if (newState == BluetoothProfile.STATE_CONNECTED) { //连接完成
broadcastUpdate(ACTION_GATT_CONNECTED); //连接完成广播
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) { //连接断开
broadcastUpdate(ACTION_GATT_DISCONNECTED); //连接断开广播
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) { //连接完成后发现服务
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED); //发现服务广播
}
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic); //收到数据广播
}
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic); //收到数据广播
}
};
14、在Activity里广播接收器的详细处理
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) { // 连接成功
mConnectionState = STATE_CONNECTED;
invalidateOptionsMenu();
} else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) { // 断开连接
mConnectionState = STATE_DISCONNECTED;
invalidateOptionsMenu();
} else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) { // 发现有可支持的服务//获取GATT服务 + UUID
mBluetoothGattService = mBluetoothLeService.getSupportedGattServices(UUID.fromString(SampleGattAttributes.UUID_SERVICE));
//根据GATT服务获取写数据端口 + UUID
mWriteBluetoothGattCharacteristic = mBluetoothGattService.getCharacteristic(UUID.fromString(SampleGattAttributes.UUID_WRITE));
//根据GATT服务获取读数据端口 + UUID
mReadBluetoothGattCharacteristic = mBluetoothGattService.getCharacteristic(UUID.fromString(SampleGattAttributes.UUID_NOTIFY));
//打开读取数据通道
mBluetoothLeService.setCharacteristicNotification(mReadBluetoothGattCharacteristic, true);
Log.d(TAG, "onReceive: 发现有可支持的服务");
} else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) { //收到数据
String dataStr = intent.getStringExtra(BluetoothLeService.EXTRA_DATA);
Log.d(TAG, "onReceive: Data" + dataStr);
writeDataToBluetooth(); //发送数据
}
}
};
15、发送数据,在Activity
里
public void writeDataToBluetooth() {
byte[] WriteBytes = new byte[10];
mWriteBluetoothGattCharacteristic.setValue(WriteBytes);
mWriteBluetoothGattCharacteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
mBluetoothLeService.writeCharacteristic(mWriteBluetoothGattCharacteristic);
}
16、读取RSSI,在BluetoothLeService
服务类里
mBluetoothGatt.readRemoteRssi();
//readRemoteRssi读取信号强度函数调用后,在BluetoothGattCallback里回调
@Override
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
super.onReadRemoteRssi(gatt, rssi, status);
Log.d(TAG, "onReadRemoteRssi: " + rssi);
broadcastUpdateRSSI(ACTION_RSSI_VALUE, String.valueOf(rssi)); //广播发送给activity
}