前段时间公司让帮忙做一个控制蓝牙设备的Android程序,主要就是给设备发一些命令。以前没接触过蓝牙相关的开发,所以查阅了大量的资料,最终鼓捣出来了,在此记录下
在这里蓝牙设备是服务端,因此程序只需要实现客户端连接蓝牙设备就行了
1.首先申请相关权限
前面两个是蓝牙相关的权限,后面两个是定位相关的权限,定位权限必须要给,否则会扫描不到蓝牙设备
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-feature android:name="android.hardware.location.gps" />
2 检测蓝牙是否开启,若未开启则去开启
BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
if (!mBluetoothAdapter.isEnabled()) {
//去开启蓝牙
Intent enabler = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enabler, 205);
} else {
//开始扫描蓝牙设备
}
3 开始扫描设备
mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(BluetoothDevice bluetoothDevice, int i, byte[] bytes) {//bluetoothDevice 就是扫描到的蓝牙设备,这里将扫描到的设备实时展示出来
if (bluetoothDevices==null){
bluetoothDevices=new ArrayList<>();
}
if (bluetoothDevice != null) {
boolean isSame=false;
for (BluetoothDevice device : bluetoothDevices) {
if (bluetoothDevice.getAddress().equals(device.getAddress())){
isSame=true;
}
}
if (!isSame){
bluetoothDevices.add(bluetoothDevice);
Message message=new Message();
handler.sendMessage(message);
}
}
Log.e(TAG, "onReceive: ACTION_FOUND" + bluetoothDevice.getName() + bluetoothDevice.getAddress());
}
};
mBluetoothAdapter.startLeScan(mLeScanCallback);
textView.setText("扫描中...");
4.连接蓝牙设备并初始化好各种回调 回调中是在子线程里这里需要注意 蓝牙设备每次发送和接收的字符也是有限制的的
BluetoothGattCallback callback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
if (newState == BluetoothGatt.STATE_CONNECTED) { // 连接成功
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(BlueToothActivity.this, "连接成功", Toast.LENGTH_SHORT).show();
}
});
gatt.discoverServices(); // 则去搜索设备的服务(Service)和服务对应Characteristic
} else { // 连接失败
runOnUiThread(new Runnable() {
@Override
public void run() {
try {
bleGatt.close();
} catch (Exception e) {
e.printStackTrace();
}
Toast.makeText(BlueToothActivity.this, "连接失败", Toast.LENGTH_SHORT).show();
finish();
}
});
}
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
if (status == BluetoothGatt.GATT_SUCCESS) { // 成功订阅
runOnUiThread(new Runnable() {
@Override
public void run() {
setView(true);
if (progressDialog.isShowing()) {
progressDialog.dismiss();
}
}
});
services = gatt.getServices(); // 获得设备所有的服务
characteristics = new ArrayList<>();
descriptors = new ArrayList<>();
BluetoothGattService lastGattService = services.get(services.size() - 1);
BluetoothGattCharacteristic lastCharacteristic = lastGattService.getCharacteristics().get(lastGattService.getCharacteristics().size() - 1);
characteristic = lastCharacteristic;
Log.e(TAG, "onServicesDiscovered: " + characteristic.getUuid().toString());
bleGatt.setCharacteristicNotification(characteristic, true);
} else {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(BlueToothActivity.this, "订阅失败", Toast.LENGTH_SHORT).show();
}
});
}
}
@Override
public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
super.onMtuChanged(gatt, mtu, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
Toast.makeText(BlueToothActivity.this, "修改成功" + mtu, Toast.LENGTH_SHORT).show();
}
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
setTimer(false);
Log.e(TAG, "onCharacteristicChanged: " + characteristic.getStringValue(0));
String tem = characteristic.getStringValue(0);
tem = tem.trim();
if (tem.startsWith("{")) {
// Log.e(TAG, "onCharacteristicChanged: {");
resultInfo = null;
resultInfo = tem;
} else if (tem.subSequence(tem.length() - 1, tem.length()).equals("}")) {
// Log.e(TAG, "onCharacteristicChanged: }");
if (resultInfo == null) {
return;
}
resultInfo = resultInfo + tem;
runOnUiThread(new Runnable() {
@Override
public void run() {
setView(true);
Log.e(TAG, "run: showdialog" + resultInfo);
try {
// Log.e(TAG, "run: " );
showDialog(resultInfo);
resultInfo = null;
} catch (JSONException e) {
// Toast.makeText(BlueToothActivity.this, ""+resultInfo, Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
});
} else {
// Log.e(TAG, "onCharacteristicChanged: null");
if (tem.subSequence(tem.length() - 1, tem.length()).equals("}")) {
return;
}
resultInfo = resultInfo + tem;
}
}
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicWrite(gatt, characteristic, status);
Log.e(TAG, "onCharacteristicWrite: " + characteristic.getStringValue(0));
if (BluetoothGatt.GATT_SUCCESS == status) { // 发送成功
if (isLoop) {
if (b == null) {
return;
}
if (index + 20 < b.length - 1) {
byte tem[] = Arrays.copyOfRange(b, index, index + 20);
writeCharacteristic(new String(tem));
} else {
byte tem[] = Arrays.copyOfRange(b, index, b.length);
writeCharacteristic(new String(tem));
b = null;
setTimer(true);
isLoop = false;
}
index = index + 20;
} else {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(BlueToothActivity.this, "发送成功", Toast.LENGTH_SHORT).show();
Log.e(TAG, "run:发送成功2" );
}
});
setTimer(true);
}
} else { // 发送失败
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(BlueToothActivity.this, "发送失败", Toast.LENGTH_SHORT).show();
}
});
}
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
Log.e(TAG, "onCharacteristicRead: " + "蓝牙回复数据为" + characteristic.getValue().toString());
}
@Override
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
super.onReadRemoteRssi(gatt, rssi, status);
}
};
Log.e(TAG, "init: 藍牙連接" );
bleGatt = bluetoothDevice.connectGatt(this, false, callback);
5 发送数据
characteristic.setValue(tem);
发送成功后会回调上面的
onCharacteristicWrite 方法
蓝牙设备返回数据会回调
onCharacteristicChanged 方法