Android手机连接蓝牙模块,并与蓝牙模块之间进行实时通讯。那么Android 手机端必须实现,蓝牙开关、扫描BLE模块、请求与BLE模块连接以及与BLE模块之间的数据互换。至于其他的包括检查手机是否支持蓝牙4.0之类的也是应该考虑到的。
那么就从检查手机是否支持蓝牙4.0开始吧。
if(!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
finish();
}
这段代码在网上很多,还有权限,自然也不能少。
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
第一个权限是应用使用蓝牙的权限,第二个权限是扫描蓝牙设备或者操作蓝牙设置等等的权限,第三个是将required设置为true则强制应用只能再支持ble的设备上运行。
然后就是开启蓝牙了,这点和之前的蓝牙版本操作一样,利用BluetoothAdapter的enable()方法就可以了,当然也可以用调用系统服务的方式,请求开启蓝牙。这里有个重要的问题,就是BluetoothAdapter不能再用BluetoothAdapter.getDefaultAdapter()来获得了,而应该用一下方式获得:
bManager=(BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
bAdapter=bManager.getAdapter();
打开了蓝牙之后,想要连接Ble模块,当然的先找到它了。以前的方式是bAdapter.startDiscovery(),然后注册监听器监听广播,通过广播获得扫描结果,对于蓝牙4.0,Android采用bAdapter.startLeScan(LeScanCallback);
的方式,如果你使用的Android 5.0 的Library的话,你会发现,这个方法已经废弃了,在它的注释里面有这么一句@deprecated use {@link BluetoothLeScanner#startScan(List, ScanSettings, ScanCallback)} instead.
也就是说它被BluetoothLeScanner的startScan(List,ScanSettings,ScanCallback)
代替了。不过为了兼容低版本,还是用这个方法比较好。因为如果你是Android5.0以下的手机,使用BluetoothLeScanner这个类会报错。
ScanCallback是一个监听器接口,当搜索到ble设备时会主动调用它唯一的方法void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord);
只需要在这个方法中处理设备列表即可。比起蓝牙4.0以前的确方便了很多。
搜索到指定设备,停止搜索,避免一直搜索。停止搜索的方法为:bAdapter.stopLeScan(ScanCallback);
搜索到设备了,就该连接设备了。Android 蓝牙4.0的连接,和之前版本的连接区别就很大了。Android Ble连接方式为: BluetoothGatt connectGatt(Context context, boolean autoConnect,BluetoothGattCallback callback);
返回值是一个BluetoothGatt对象,去掉Bluetooth就是Gatt了,GATT就是Generic Attribute Profile。这个让我去翻译,还真是为难我这种英语学了十几年四级都没过的人了。反正大致就是一个通用属性规范之类的意思吧,且当个代称。
连接之后呢?Ble连接之后就不是像以前那样,建立个Socket通信,请求ServerSocket允许连接,然后就开始眉来眼去的相互收发数据了。在取得BluetoothGatt后,需要读取蓝牙模块提供的Service、Characteristic,选择需要的通道进行数据交换。也可以直接通过UUID获取通道来进行通信。
获取蓝牙模块提供的Service、Characteristic方法如下:
public void getGattService(List<BluetoothGattService> gattServices){
if(gattServices==null)return;
Log.i("wuwang", "获得服务列表");
serviceList.clear();
characteristicList.clear();
String uuid;
String default_service=getResources().getString(R.string.unknow_service);
String default_characteristic=getResources().getString(R.string.unknow_characteric);
for(BluetoothGattService gService:gattServices){
Log.i("wuwang", "发现一个服务");
HashMap<String, String> sData=new HashMap<String, String>();
uuid=gService.getUuid().toString();
sData.put("name",SampleGattAttributes.lookup(uuid,default_service));
sData.put("uuid", uuid);
serviceList.add(sData);
Log.e("wuwang", SampleGattAttributes.lookup(uuid,default_service)+":"+uuid);
List<BluetoothGattCharacteristic> charaList=gService.getCharacteristics();
String cuuid;
for(BluetoothGattCharacteristic chara:charaList){
HashMap<String, String> cData=new HashMap<String, String>();
cuuid=chara.getUuid().toString();
cData.put("cname", SampleGattAttributes.lookup(cuuid, default_characteristic));
cData.put("cuuid", cuuid);
cData.put("puuid", uuid);
characteristicList.add(cData);
Log.d("wuwang", " "+SampleGattAttributes.lookup(cuuid, default_characteristic)+":"+cuuid);
}
}
}
在之前的BluetoothGatt connectGatt(Context context, boolean autoConnect,BluetoothGattCallback callback)
方法中,第三个参数也是一个监听器接口,getGattService方法可以放在BluetoothGattCallback的onConnectionStateChange方法实现中。
获取指定的BluetoothGattCharacteristic后,剩下的事情就好办了。Android手机端给蓝牙模块发送数据,就是在需要发数据的时候调用bCharacteristic.setValue(value);
和bGatt.writeCharacteristic(bCharacteristic);
即可。其中bCharacteristic为指定的BluetoothGattCharacteristic,Value为需要发送的数据。bGatt为之前获得BluetoothGatt。
而读取蓝牙模块发送来的数据,只许设置Characteristic通知,即调用bGatt.setCharacteristicNotification(bCharacteristic, true);
然后再之前ConnectGatt()第三个参数使用的BluetoothGattCallback接口中实现onCharacteristicChanged方法,并在其中获取数据即可:
bGatt.readCharacteristic(bCharacteristic);
final byte[] bytes=bCharacteristic.getValue();
大概就是这个样子了。