1、 权限和相关属性这是最基本的啦
<uses-featureandroid:name="android.hardware.bluetooth_le"android:required="true"/>
<uses-permissionandroid:name="android.permission.BLUETOOTH"/>
<uses-permissionandroid:name="android.permission.BLUETOOTH_ADMIN"/>
android 6以后还需要增加动态权限申请 不然无法获取蓝牙设备
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
2、初始化蓝牙
private void initBluetooth() {
BluetoothManager mBluetoothManager = (BluetoothManager) this.getSystemService(Context.BLUETOOTH_SERVICE);
if (mBluetoothManager != null) {
BluetoothAdapter mBluetoothAdapter = mBluetoothManager.getAdapter();
if (mBluetoothAdapter != null) {
if (!mBluetoothAdapter.isEnabled()) {
mBluetoothAdapter.enable(); //打开蓝牙
}
}
}
}
3、获取本地ble对象(BluetoothAdapter),它对应本地Android设备的蓝牙模块,可能这么称呼为本地ble对象不太准确,但我老人家开心这么称呼。从此段代码开始可以把这些有关ble通信的代码写到一个class中当做一个ble工具class,以便代码清晰查看和方便调用。这里我们就当这个工具类叫BleManager
相关API参考如下:
BluetoothManager:从名字可以看出是用来管理蓝牙设备的,用它来获取BluetoothAdapter; BluetoothAdapter:蓝牙适配器,针对蓝牙模块的操作,比如:关闭,打开,扫描等; LeScanCallback:在蓝牙扫描过程中,发现一个设备,就会回调一次; BluetoothDevice:代表一个远程的蓝牙设备 BluetoothGatt:代表一个Bluetooth GATT Profile,用来控制蓝牙开关,和特征的读写等; BluetoothGattCallback:这个可就厉害了,针对蓝牙的连接状态,读写等操作,这里都会有相应的回调; BluetoothGattService:表示一个服务; BluetoothGattCharacteristic:表示一个特征; BluetoothGattDescriptor:表示一个描述;
private BluetoothAdapter mBluetoothAdapter;
private BluetoothDevice mBluetoothDevice;
private BluetoothGatt mBluetoothGatt;
private boolean isScanning = false;
private BleManager(Context context) {
this.mContext = context;
BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE); //BluetoothManager只在android4.3以上有
if (bluetoothManager == null) {
TLog.e(TAG, "Unable to initialize BluetoothManager.");
return;
}
mBluetoothAdapter = bluetoothManager.getAdapter();
}
4、既然获得了BluetoothAdapter对象,那么接下来就可以搜索ble设备了,这时就需要用到BluetoothAdapter的startLeScan()这个方法了
public void startLeScan() {
if (mBluetoothAdapter == null) {
return;
}
if (isScanning) {
return;
}
isScanning = true;
mBluetoothAdapter.startLeScan(mLeScanCallback); //此mLeScanCallback为回调函数
mHandler.sendEmptyMessageDelayed(STOP_LESCAN, 10000); //这个搜索10秒,如果搜索不到则停止搜索
}
在4.3之前的api是通过注册广播来处理搜索时发生的一些事件,而支持ble的新的api中,是通过回调的方式来处理的,而mLeScanCallback就是一个接口对象
private LeScanCallback mLeScanCallback = new LeScanCallback() {
@Override
public void onLeScan(BluetoothDevice device, int arg1, byte[] arg2) {
TLog.i(TAG, "onLeScan() DeviceName------>"+device.getName()); //在这里可通过device这个对象来获取到搜索到的ble设备名称和一些相关信息
if(device.getName() == null){
return;
}
if (device.getName().contains("Ble_Name")) { //判断是否搜索到你需要的ble设备
TLog.i(TAG, "onLeScan() DeviceAddress------>"+device.getAddress());
mBluetoothDevice = device; //获取到周边设备
stopLeScan(); //1、当找到对应的设备后,立即停止扫描;2、不要循环搜索设备,为每次搜索设置适合的时间限制。避免设备不在可用范围的时候持续不停扫描,消耗电量。
connect(); //连接
}
}
};
private Handler mHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case STOP_LESCAN:
T.showLong(mContext, mContext.getResources().getString(R.string.msg_connect_failed));
mBluetoothAdapter.stopLeScan(mLeScanCallback);
broadcastUpdate(Config.ACTION_GATT_DISCONNECTED);
isScanning = false;
TLog.i(TAG, "Scan time is up");
break;
}
};
};
5、搜索到当然就是连接了,就是上面那个connect()方法了
public boolean connect() {
if (mBluetoothDevice == null) {
TLog.i(TAG, "BluetoothDevice is null.");
return false;
}
//两个设备通过BLE通信,首先需要建立GATT连接。这里我们讲的是Android设备作为client端,连接GATT Server
mBluetoothGatt =mBluetoothDevice.connectGatt(mContext,false,mGattCallback); //mGattCallback为回调接口
if(mBluetoothGatt !=null)
{
if (mBluetoothGatt.connect()) {
TLog.d(TAG, "Connect succeed.");
return true;
} else {
TLog.d(TAG, "Connect fail.");
return false;
}
} else
{
TLog.d(TAG, "BluetoothGatt null.");
return false;
}
}
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
gatt.discoverServices(); //执行到这里其实蓝牙已经连接成功了
TLog.i(TAG, "Connected to GATT server.");
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
if (mBluetoothDevice != null) {
TLog.i(TAG, "重新连接");
connect();
} else {
TLog.i(TAG, "Disconnected from GATT server.");
}
}
}
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
TLog.i(TAG, "onServicesDiscovered");
getBatteryLevel(); //获取电量
} else {
TLog.i(TAG, "onServicesDiscovered status------>" + status);
}
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
TLog.d(TAG, "onCharacteristicRead------>" + Utils.bytesToHexString(characteristic.getValue()));
//判断UUID是否相等
if (Values.UUID_KEY_BATTERY_LEVEL_CHARACTERISTICS.equals(characteristic.getUuid().toString())) {
}
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
TLog.d(TAG, "onCharacteristicChanged------>" + Utils.bytesToHexString(characteristic.getValue()));
//判断UUID是否相等
if (Values.UUID_KEY_BATTERY_LEVEL_CHARACTERISTICS.equals(characteristic.getUuid().toString())) {
}
}
//接受Characteristic被写的通知,收到蓝牙模块的数据后会触发onCharacteristicWrite
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
TLog.d(TAG, "status = " + status);
TLog.d(TAG, "onCharacteristicWrite------>" + Utils.bytesToHexString(characteristic.getValue()));
}
};
public void getBatteryLevel() {
BluetoothGattCharacteristic batteryLevelGattC = getCharcteristic(
Values.UUID_KEY_BATTERY_LEVEL_SERVICE, Values.UUID_KEY_BATTERY_LEVEL_CHARACTERISTICS);
if (batteryLevelGattC != null) {
readCharacteristic(batteryLevelGattC);
setCharacteristicNotification(batteryLevelGattC, true); //设置当指定characteristic值变化时,发出通知。
}
}
6、获取服务与特征
//a.获取服务
public BluetoothGattService getService(UUID uuid) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
TLog.e(TAG, "BluetoothAdapter not initialized");
return null;
}
return mBluetoothGatt.getService(uuid);
}
//b.获取特征
private BluetoothGattCharacteristic getCharcteristic(String serviceUUID, String characteristicUUID) {
//得到服务对象
BluetoothGattService service = getService(UUID.fromString(serviceUUID)); //调用上面获取服务的方法
if (service == null) {
TLog.e(TAG, "Can not find 'BluetoothGattService'");
return null;
}
//得到此服务结点下Characteristic对象
final BluetoothGattCharacteristic gattCharacteristic = service.getCharacteristic(UUID.fromString(characteristicUUID));
if (gattCharacteristic != null) {
return gattCharacteristic;
} else {
TLog.e(TAG, "Can not find 'BluetoothGattCharacteristic'");
return null;
}
}
//获取数据
public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
TLog.e(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.readCharacteristic(characteristic);
}
public boolean setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
TLog.e(TAG, "BluetoothAdapter not initialized");
return false;
}
return mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
}
7、写入数据,在上面的方法中我们已经得到了设备服务和服务里的特征characteristic,那么就可以对这个特征写入或者说是赋值
public void write(byte[] data) { //一般都是传byte
//得到可写入的characteristic Utils.isAIRPLANE(mContext) &&
if (!mBleManager.isEnabled()) {
TLog.e(TAG, "writeCharacteristic 开启飞行模式");
//closeBluetoothGatt();
isGattConnected = false;
broadcastUpdate(Config.ACTION_GATT_DISCONNECTED);
return;
}
BluetoothGattCharacteristic writeCharacteristic = getCharcteristic(Values.UUID_KEY_SERVICE, Values.UUID_KEY_WRITE); //这个UUID都是根据协议号的UUID
if (writeCharacteristic == null) {
TLog.e(TAG, "Write failed. GattCharacteristic is null.");
return;
}
writeCharacteristic.setValue(data); //为characteristic赋值
writeCharacteristicWrite(writeCharacteristic);
}
public void writeCharacteristicWrite(BluetoothGattCharacteristic characteristic) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
TLog.e(TAG, "BluetoothAdapter not initialized");
return;
}
TLog.e(TAG, "BluetoothAdapter 写入数据");
boolean isBoolean = false;
isBoolean = mBluetoothGatt.writeCharacteristic(characteristic);
TLog.e(TAG, "BluetoothAdapter_writeCharacteristic = " + isBoolean); //如果isBoolean返回的是true则写入成功
}
8、写到这其实基本差不多了,最后再就是在activity中调用了,其实在调用的时候直接在需要搜索蓝牙的activity调用startLeScan()这个方法就可以了,至于搜索到的结果也显示在这个方法里面了,找到了对应的设备名称然后再连接,对于中间一系列的回调函数,startLeScan(); ?调用此方法,如果搜索到有设备则自然的去连接它了,到时候连接时回回调mGattCallback 这个回调函数,如果成功你可以发送一个广播出来提醒用户蓝牙与设备连接成功;
?搜索成功后,你就可以根据你的需要写入信息传送了。简单说说,就是你在一个button事件中调用上面的write(byte[] byte)这个方法,对于里面的参数byte就是根据你们所设置的byte了,最后写入的成功与否就看writeCharacteristicWrite这个方法下面的返回值是true还是false了,true表示成成功。
|