我的实现使用两台android手机做ble相关的通信,一台机器作为服务端接收发过来的消息,另一台作为客户端发送消息。
客户端基本流程如下:
1.添加蓝牙相关权限
<uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
2.BLE设备扫描
使用BluetoothAdapter.startLeScan来扫描发现设备,这个方法需要参数BluetoothAdapter.LeScanCallback,所以还需要实现此回调方法,来获取扫描结果。
注意:BLE扫描耗电量比较大,尽可能缩短扫描时间。发现用户所需连接的设备后立即停止扫描
public class DeviceScanActivity extends ListActivity { private BluetoothAdapter mBluetoothAdapter; private boolean mScanning; private Handler mHandler; // 10秒后停止寻找. private static final long SCAN_PERIOD = 10000; private void scanLeDevice(final boolean enable) { if (enable) { // 经过预定扫描期后停止扫描 mHandler.postDelayed(new Runnable() { @Override public void run() { mScanning = false; mBluetoothAdapter.stopLeScan(mLeScanCallback); } }, SCAN_PERIOD); mScanning = true; mBluetoothAdapter.startLeScan(mLeScanCallback); } else { mScanning = false; mBluetoothAdapter.stopLeScan(mLeScanCallback); } } }
BLE扫描结果的接口,下面是BluetoothAdapter.LeScanCallback的实现。可以获取到扫描到设备的蓝牙名称和蓝牙地址等。
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) { runOnUiThread(new Runnable() { @Override public void run() { device.getName();//获得扫描到设备名称 device.getAddress();//获取设备蓝牙地址 } }); } };
3.连接
先获取BluetoothAdapterd,再获取BluetoothDevice。根据扫描的蓝牙设备地址获取BluetoothDevice对象。使用BluetoothDevice.connectGatt进行连接。返回BluetoothGatt实例。
然后使用connectGatt( )方法进行链接。这个方法需要三个参数:一个Context对象,自动连接(boolean值,表示只要BLE设备可用是否自动连接到它),和BluetoothGattCallback调用。后面会详细介绍BluetoothGattCallback的实现。
BluetoothManager mBluetoothManager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE); BluetoothAdapter mBluetoothAdapter = mBluetoothManager.getAdapter(); BluetoothDevice mDevice = mBluetoothAdapter.getRemoteDevice(address);
4.发现BLE设备服务
mBluetoothGatt.discoverServices();
5.发送Characteristic
发送消息通过读写Characteristic来完成,app完成与GATT服务端连接和发现services后,就可以读写 writeCharacteristic,每个服务和characteristic都有一个UUID来唯一确定,所有想要开发BLE必须知道你想要用哪个服务的那个characteristic也就是要知道对应的UUID。
private void writeCharacteristic(String writeValue) { BluetoothGattCharacteristic characteristic = getCharacteristic(CHARACTERISTIC_UUID); if (characteristic == null) return; characteristic.setValue(writeValue); mBluetoothGatt.writeCharacteristic(characteristic); } private void readCharacteristic() { BluetoothGattCharacteristic characteristic = getCharacteristic(CHARACTERISTIC_UUID); if (characteristic != null) mBluetoothGatt.readCharacteristic(characteristic); }
6.BluetoothGattCallback实现
根据BluetoothGattCallback判断当前状态。获取是否连接成功、是否断开连接、读写Characteristic是否成功等。
private final BluetoothGattCallback mGattCallbacks = new BluetoothGattCallback() { @Override //获取连接状态方法,BLE设备连接上或断开时,会调用到此方 public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { if (DEBUG) Log.d(TAG, "onConnectionStateChange"); if (status == BluetoothGatt.GATT_SUCCESS) { if (newState == BluetoothProfile.STATE_CONNECTED) { showMessage("Bluetooth LE connected"); } else if (status == BluetoothProfile.STATE_DISCONNECTED) { showMessage("Bluetooth LE disconnected"); } } } //成功发现设备的services时,调用此方法 @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { if ((status == BluetoothGatt.GATT_SUCCESS) && (mBluetoothGatt.getService(SERVICE_UUID) != null)) { showMessage("Discover service Successful !!!"); } } //读写characteristic时会调用到以下方法 @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { if ((status == BluetoothGatt.GATT_SUCCESS) && (characteristic.getUuid().equals(CHARACTERISTIC_UUID))) { showMessage(characteristic.getStringValue(0)); } } @Override public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { BluetoothGattCharacteristic mCharacteristic = getCharacteristic(CHARACTERISTIC_UUID); if ((status == BluetoothGatt.GATT_SUCCESS) && (characteristic.getStringValue(0).equals(mCharacteristic.getStringValue(0)))) { showMessage("CharacteristicWrite Successful !!!"); } } };
7.断开链接
mBluetoothGatt.disconnect();
以上是客户端(进行消息发送)的实现,下面介绍服务端实现方法。
服务端实现比较简单,首先创建BluetoothManager,使用openGattServer实例mGattServer。openGattServer需要一个BluetoothGattServerCallback回调。创建BluetoothGattService,再把BluetoothGattService添加到BluetoothGattServer中。
BluetoothManager mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); BluetoothGattServer mGattServer = mBluetoothManager.openGattServer(this, mCallbacks); BluetoothGattService mService = createService(); mGattServer.addService(mService);
BluetoothGattServerCallback回调的实现,在这个回调里面可以获取到服务端发送过来的消息,连接状态等
private final BluetoothGattServerCallback mCallbacks = new BluetoothGattServerCallback() { @Override //获取连接状态方法,BLE设备连接上或断开时,会调用到此方 public void onConnectionStateChange(BluetoothDevice device, int status, int newState) { if (DEBUG) Log.d(TAG, "onConnectionStateChange: newState=" + newState); if (status == BluetoothGatt.GATT_SUCCESS) { if (newState == BluetoothProfile.STATE_CONNECTED) { mDevice = device; String devicename = device.getName(); String address = device.getAddress(); notifyConnected(devicename); beginNotification(); } else if (status == BluetoothProfile.STATE_DISCONNECTED) { stopNotification(); notifyDisconnected(); mDevice = null; } } } //service添加成功会调用此方 @Override public void onServiceAdded(int status, BluetoothGattService service) { if (DEBUG) Log.d(TAG, "onServiceAdded()"); if (status == BluetoothGatt.GATT_SUCCESS) notifyServiceAdded(); } //读写Characteristic,在此获得客户端发来的消息 @Override public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId,BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded,int offset, byte[] value) { if (DEBUG) Log.d(TAG, "onCharacteristicWriteRequest: preparedWrite=" + preparedWrite); try{ mCharacteristicString = new String(value); //客户端发来的消息 }catch(Exception e){ } notifyCharacteristicWriteRequest(mCharacteristicString); } } @Override public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) { if (DEBUG) Log.d(TAG, "onCharacteristicReadRequest()"); notifyCharacteristicReadRequest(); } };
再发几张我这个测试应用的操作截图
1.在server端点击Start Server,上面文本提示BLE SERVICE ADDED
2.在Client端,输入服务端手机的蓝牙地址,然后点在onnect
3.进行配对,两台手机分别点击配对
4.客户端点击Discover service,Toast提示Discover service Successful。
服务端显示Device Connect。
5.客户端输入要发送的字符"123456",点击Write Characteristic。
服务端接收到发送过来的字符,显示Device Write:123456
6.客户端点击Disconnect断开连接
服务端显示Device Disconnected