Android -- Android Bluetooth Low Energy 学习笔记

#Android Bluetooth Low Energy 基础

1、关于Android平台的BLE

蓝牙4.0于2010年发布,相对于上个版本3.0,它的特点是更省电、成本低 延迟低等特点,现在最新的蓝牙协议是2013年底发布的蓝牙4.1,蓝牙4.1在4.0 基础上进行升级,使得可穿戴设备的批量数据传输速度更高。Android是从4.3 才开始提供BLE API,这也就限定了BLE的应用只能运行在Android 4.3及其以上 的系统。在Android平台上的蓝牙4.0主要有两种工作模式:经典蓝牙(classic bluetooth) 、低功耗蓝牙(bluetooth low energy,缩写为BLE)

2、角色与职责

当一个Android设备与一个BLE设备进行交互通信时,主要存在以下两种关系
中心设备与外围设备:中心设备扮演扫描的角色,寻找外围设备的广播消息。Android设备 作为中心设备,与之连接通信的设备作为外围设备。

GATT服务器与GATT客户端:这种关系决定了当连接建立后两个设备如何通信。

注:目前Android系统提供的API使得Android设备只能作为中心设备

3、组成部分

BLE分为三个部分Service、Characteristic、Descriptor,每个部分都拥有不同的 UUID来标识。一个BLE设备可以拥有多个Service,一个Service可以包含多个Characteristic, 一个Characteristic包含一个Value和多个Descriptor,一个Descriptor包含一个Value。 通信数据一般存储在Characteristic内,目前一个Characteristic中存储的数据最大为20 byte。 与Characteristic相关的权限字段主要有READ、WRITE、WRITE_NO_RESPONSE、NOTIFY。 Characteristic具有的权限属性可以有一个或者多个。

4、核心代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220

private BluetoothAdapter mBtAdapter = null;
private BluetoothGatt mBtGatt = null;
private int mState = 0;
private Context mContext;
private BluetoothGattCharacteristic mWriteCharacteristic = null;
private BluetoothGattCharacteristic mReadCharacteristric = null;

private final String TAG = "BLE_Demo";

// 设备连接状态
private final int CONNECTED = 0x01;
private final int DISCONNECTED = 0x02;
private final int CONNECTTING = 0x03;

// 读写相关的Service、Characteristic的UUID
public static final UUID TRANSFER_SERVICE_READ = UUID.fromString("34567817-2432-5678-1235-3c1d5ab44e17");
public static final UUID TRANSFER_SERVICE_WRITE = UUID.fromString("34567817-2432-5678-1235-3c1d5ab44e18");
public static final UUID TRANSFER_CHARACTERISTIC_READ = UUID.fromString("23487654-5678-1235-2432-3c1d5ab44e94");
public static final UUID TRANSFER_CHARACTERISTIC_WRITE = UUID.fromString("23487654-5678-1235-2432-3c1d5ab44e93");

// BLE设备连接通信过程中回调
private BluetoothGattCallback mBtGattCallback = new BluetoothGattCallback() {

// 连接状态发生改变时的回调
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status,
int newState) {

if (status == BluetoothGatt.GATT_SUCCESS) {
mState = CONNECTED;
Log.d(TAG, "connected OK");
mBtGatt.discoverServices();
} else if (newState == BluetoothGatt.GATT_FAILURE) {
mState = DISCONNECTED;
Log.d(TAG, "connect failed");
}
}

// 远端设备中的服务可用时的回调
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {

if (status == BluetoothGatt.GATT_SUCCESS) {
BluetoothGattService btGattWriteService = mBtGatt
.getService(TRANSFER_SERVICE_WRITE);
BluetoothGattService btGattReadService = mBtGatt
.getService(TRANSFER_SERVICE_READ);
if (btGattWriteService != null) {
mWriteCharacteristic = btGattWriteService
.getCharacteristic(TRANSFER_CHARACTERISTIC_WRITE);
}
if (btGattReadService != null) {
mReadCharacteristric = btGattReadService
.getCharacteristic(TRANSFER_CHARACTERISTIC_READ);
if (mReadCharacteristric != null) {
mBtGatt.readCharacteristic(mReadCharacteristric);
}
}
}
}

// 某Characteristic的状态为可读时的回调
@Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status) {

if (status == BluetoothGatt.GATT_SUCCESS) {
readCharacterisricValue(characteristic);

// 订阅远端设备的characteristic,
// 当此characteristic发生改变时当回调mBtGattCallback中的onCharacteristicChanged方法
mBtGatt.setCharacteristicNotification(mReadCharacteristric,
true);
BluetoothGattDescriptor descriptor = mReadCharacteristric
.getDescriptor(UUID
.fromString("00002902-0000-1000-8000-00805f9b34fb"));
if (descriptor != null) {
byte[] val = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE;
descriptor.setValue(val);
mBtGatt.writeDescriptor(descriptor);
}
}
}

// 写入Characteristic成功与否的回调
@Override
public void onCharacteristicWrite(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status) {

switch (status) {
case BluetoothGatt.GATT_SUCCESS:
Log.d(TAG, "write data success");
break;// 写入成功
case BluetoothGatt.GATT_FAILURE:
Log.d(TAG, "write data failed");
break;// 写入失败
case BluetoothGatt.GATT_WRITE_NOT_PERMITTED:
Log.d(TAG, "write not permitted");
break;// 没有写入的权限
}
}

// 订阅了远端设备的Characteristic信息后,
// 当远端设备的Characteristic信息发生改变后,回调此方法
@Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
readCharacterisricValue(characteristic);
}

};

/**
* 读取BluetoothGattCharacteristic中的数据
*
* @param characteristic
*/
private void readCharacterisricValue(
BluetoothGattCharacteristic characteristic) {
byte[] data = characteristic.getValue();
StringBuffer buffer = new StringBuffer("0x");
int i;
for (byte b : data) {
i = b & 0xff;
buffer.append(Integer.toHexString(i));
}
Log.d(TAG, "read data:" + buffer.toString());
}

/**
* 与指定的设备建立连接
*
* @param device
*/
public void connect(BluetoothDevice device) {

mBtGatt = device.connectGatt(mContext, false, mBtGattCallback);
mState = CONNECTTING;
}

/**
* 初始化
*
* @param context
* @return 如果初始化成功则返回true
*/
public boolean init(Context context) {
BluetoothManager btMrg = (BluetoothManager) context
.getSystemService(Context.BLUETOOTH_SERVICE);
if (btMrg == null)
return false;
mBtAdapter = btMrg.getAdapter();
if (mBtAdapter == null)
return false;
mContext = context;
return true;
}

// BLE设备搜索过程中的回调,在此可以根据外围设备广播的消息来对设备进行过滤
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {

@Override
public void onLeScan(final BluetoothDevice device, int rssi,
byte[] scanRecord) {

ArrayUtils.reverse(scanRecord);// 数组反转
// 将Byte数组的数据以十六进制表示并拼接成字符串
StringBuffer str = new StringBuffer();
int i = 0;
for (byte b : scanRecord) {
i = (b & 0xff);
str.append(Integer.toHexString(i));
}
String discoveryServceID = str.toString();
Log.d(TAG, device.getName() + " scanRecord:\n" + discoveryServceID);

// 查询是否含有指定的Service UUID信息
if (discoveryServceID.indexOf(TRANSFER_SERVICE_WRITE.toString()
.replace("-", "")) != -1) {

Log.d(TAG, device.getName() + " has available service UUID");

// 在这是处理匹配的设备……

}

}

};

/**
* 开始BLE设备扫描
*/
public void startScan() {
mBtAdapter.startLeScan(mLeScanCallback);
}

/**
* 停止BLE设备扫描
*/
public void stopScan() {
mBtAdapter.stopLeScan(mLeScanCallback);
}

/**
* 发送数据
*
* @param data
* 待发送的数据,最大长度为20
*/
private void sendData(byte[] data) {

if (data != null && data.length > 0 && data.length < 21) {
if (mWriteCharacteristic.setValue(data)
&& mBtGatt.writeCharacteristic(mWriteCharacteristic)) {
Log.d(TAG, "send data OK");
}
}
}

#Android Bluetooth Low Energy 数据的写入与读取 第一天
1 、启动ble设备连接的方法首先要得到一个BluetoothDevice, 这个可以通过,android搜索一配对或者为配对的蓝牙设备获取得到BluetoothDevice的对象,也可以通过搜索ble设备去得到一个BluetoothDevice的对象(下面会仔细说索搜ble设备)需要注意的是,当一个ble设备作为一个蓝牙设备连接到了android 设备上的话,我们通过搜索ble设备的api是搜索不到的。

2、得到一个蓝牙已配对设备

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mBluetoothAdapter.startDiscovery();

Set<BluetoothDevice> bledevices = mBluetoothAdapter.getBondedDevices();
if (bledevices.size() > 0)
{
for (BluetoothDevice bluetoothDevice : bledevices)
{
if (bluetoothDevice.getAddress().toString()
.equals(BLUETOOTH_DEVICE_MAC))
{
Log.v(TAG, "find with old: " + bluetoothDevice.getAddress());
bluetoothDevice.connectGatt(getActivity(), false,
mGattCallback);
}
}
}

3、如何索搜ble设备 :

使用BluetoothAdapter 的 startLeScan 方法, 

startLeScan 的参数是一个回调。

1
2
3
4
5
6
7
8
9
10
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback()
{

@Override
public void onLeScan(final BluetoothDevice device, int rssi,
byte[] scanRecord)
{
Log.v(TAG, "device: " + device);
}
};

在这个回调里可以索搜到BLE设备

4、使用索搜到的设备连接:

当我们搜索到设备的时候, 可以使用

1
device.connectGatt(getActivity(), false, mGattCallback);

进行连接,其中 mGattCallback 也是个回调方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback()
{

// 设备发生读操作时的回调
@Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status)
{
Log.v(TAG, "onCharacteristicRead: " + characteristic.getUuid());
}

// 设备发生写操作是的回调
@Override
public void onCharacteristicWrite(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status)
{
if (BluetoothGatt.GATT_SUCCESS == status)
{
Log.v(TAG, "onCharacteristicWrite: " + characteristic.getUuid());
}
super.onCharacteristicWrite(gatt, characteristic, status);
}

// 设备连接状态发生更改时的回调
// 我们要在这里进行discoverServices()
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status,
int newState)
{
gatt.discoverServices();
super.onConnectionStateChange(gatt, status, newState);
}

// 当BLE设备中的服务被找到时,回调如下方法
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status)
{
Log.v(TAG, "onServicesDiscovered: " + gatt.getServices().size());

super.onServicesDiscovered(gatt, status);
}

};

5、重点:数据的IO
无论数据或是写,都需要

1
2
3
4
BluetoothGattService mSVC = gatt.getService(UUID
.fromString("0000dfb0-0000-1000-8000-00805f9b34fb"));
BluetoothGattCharacteristic mCH = mSVC.getCharacteristic(UUID
.fromString("0000dfb1-0000-1000-8000-00805f9b34fb"));

得到一个BluetoothGattCharacteristic , 如上, 我们同过一个指定uuid的方式,在

public
void
onServicesDiscovered() 方法中

得到gatt ,调用gatt的读操作

1
gatt.readCharacteristic(mCH);

执行这部操作之后, 我们会在 onCharacteristicRead 方法回掉这个 Characteristic 的所带有的value

写操作则是

1
2
mCH.setValue(GAME_MODE);
gatt.writeCharacteristic(mCH);

同理,在 onCharacteristicWrite 方法中可以获得操作的提示。

20151120 , 目前我可以读到 

Characteristic 里的数据,结果也正确, 但是无法语言写入是否正确,目前执行了write的操作,系统显示写入正常, 但是看不到相应的变化,

指环的模式并没有变化。ps:我在提供的demo中执行写操作,指环的状态也为改变(之前改过机会,目前不知道情况)

Android Bluetooth Low Energy 数据的写入与读取 第二天

1、使用
writeCharacteristic 读写数据,(顺便说一句,今天反复的调试之后,公司这边的蓝牙设备终于可以切换模式了,不知道为什么之前尝试的总是不行),今天做下总结。

2、由于android ble 的接口都是异步的, 所以我们所调用的方法都要在回掉函数中进行,写一个简单的流程图, 方便理解:(图画的不专业, 凑合看看)

Paste_Image.png
3、写数据的时候将值这样写 ch.setValue(new byte[] { (byte) 0x00, (byte) 0xff });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
package youten.redo.ble.readwrite;

import java.util.Set;
import java.util.UUID;

import youten.redo.ble.util.BleUtil;
import youten.redo.ble.util.BleUuid;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.Toast;

public class DeviceActivity extends Activity implements View.OnClickListener
{
private static final String TAG = "BLEDevice";

public static final String EXTRA_BLUETOOTH_DEVICE = "BT_DEVICE";
private BluetoothAdapter mBTAdapter;
private BluetoothDevice mDevice;
private BluetoothGatt mConnGatt;
private int mStatus;

private Button mReadManufacturerNameButton;
private Button mReadSerialNumberButton;
private Button mWriteAlertLevelButton;

private final BluetoothGattCallback mGattcallback = new BluetoothGattCallback()
{
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status,
int newState)
{
if (newState == BluetoothProfile.STATE_CONNECTED)
{
mStatus = newState;
Log.v(TAG, "connected and discoverServices");
mConnGatt.discoverServices();
} else if (newState == BluetoothProfile.STATE_DISCONNECTED)
{
mStatus = newState;
runOnUiThread(new Runnable()
{
public void run()
{
mReadManufacturerNameButton.setEnabled(false);
mReadSerialNumberButton.setEnabled(false);
mWriteAlertLevelButton.setEnabled(false);
};
});
}
};

@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status)
{
Log.v(TAG, "is have services");
for (BluetoothGattService service : gatt.getServices())
{
if ((service == null) || (service.getUuid() == null))
{
continue;
}
if (BleUuid.SERVICE_DEVICE_INFORMATION.equalsIgnoreCase(service
.getUuid().toString()))
{
mReadManufacturerNameButton
.setTag(service.getCharacteristic(UUID
.fromString(BleUuid.CHAR_MANUFACTURER_NAME_STRING)));
mReadSerialNumberButton
.setTag(service.getCharacteristic(UUID
.fromString(BleUuid.CHAR_SERIAL_NUMBEAR_STRING)));
runOnUiThread(new Runnable()
{
public void run()
{
mReadManufacturerNameButton.setEnabled(true);
mReadSerialNumberButton.setEnabled(true);
};
});
}
if (BleUuid.SERVICE_IMMEDIATE_ALERT.equalsIgnoreCase(service
.getUuid().toString()))
{
runOnUiThread(new Runnable()
{
public void run()
{
mWriteAlertLevelButton.setEnabled(true);
};
});
mWriteAlertLevelButton.setTag(service
.getCharacteristic(UUID
.fromString(BleUuid.CHAR_ALERT_LEVEL)));
}
}

runOnUiThread(new Runnable()
{
public void run()
{
setProgressBarIndeterminateVisibility(false);
};
});
};

@Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status)
{
if (status == BluetoothGatt.GATT_SUCCESS)
{

byte[] bytes = characteristic.getValue();
for (byte b : bytes)
{
Log.v("", "------characteristic------" + b);
}

if (BleUuid.CHAR_MANUFACTURER_NAME_STRING
.equalsIgnoreCase(characteristic.getUuid().toString()))
{
final String name = characteristic.getStringValue(0);

runOnUiThread(new Runnable()
{
public void run()
{
mReadManufacturerNameButton.setText(name);
setProgressBarIndeterminateVisibility(false);
};
});
} else if (BleUuid.CHAR_SERIAL_NUMBEAR_STRING
.equalsIgnoreCase(characteristic.getUuid().toString()))
{
final String name = characteristic.getStringValue(0);

runOnUiThread(new Runnable()
{
public void run()
{
mReadSerialNumberButton.setText(name);
setProgressBarIndeterminateVisibility(false);
};
});
}

}
}

@Override
public void onCharacteristicWrite(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status)
{

if (BluetoothGatt.GATT_SUCCESS == status)
{
Log.v(TAG,
"write - characteristic: " + characteristic.getUuid());
Log.v(TAG, "write - service "
+ characteristic.getService().getUuid());
}

// 再读取一次, 验证一下值是不是对的
gatt.readCharacteristic(characteristic);

runOnUiThread(new Runnable()
{
public void run()
{
setProgressBarIndeterminateVisibility(false);
};
});
};
};

@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.activity_device);

// state
mStatus = BluetoothProfile.STATE_DISCONNECTED;
mReadManufacturerNameButton = (Button) findViewById(R.id.read_manufacturer_name_button);
mReadManufacturerNameButton.setOnClickListener(this);
mReadSerialNumberButton = (Button) findViewById(R.id.read_serial_number_button);
mReadSerialNumberButton.setOnClickListener(this);
mWriteAlertLevelButton = (Button) findViewById(R.id.write_alert_level_button);
mWriteAlertLevelButton.setOnClickListener(this);
}

@Override
protected void onResume()
{
super.onResume();

init();
}

@Override
protected void onDestroy()
{
super.onDestroy();
if (mConnGatt != null)
{
if ((mStatus != BluetoothProfile.STATE_DISCONNECTING)
&& (mStatus != BluetoothProfile.STATE_DISCONNECTED))
{
mConnGatt.disconnect();
}
mConnGatt.close();
mConnGatt = null;
}
}

@Override
public void onClick(View v)
{
if (v.getId() == R.id.read_manufacturer_name_button)
{
if ((v.getTag() != null)
&& (v.getTag() instanceof BluetoothGattCharacteristic))
{
BluetoothGattCharacteristic ch = (BluetoothGattCharacteristic) v
.getTag();
if (mConnGatt.readCharacteristic(ch))
{
setProgressBarIndeterminateVisibility(true);
}
}
} else if (v.getId() == R.id.read_serial_number_button)
{
if ((v.getTag() != null)
&& (v.getTag() instanceof BluetoothGattCharacteristic))
{
BluetoothGattCharacteristic ch = (BluetoothGattCharacteristic) v
.getTag();
if (mConnGatt.readCharacteristic(ch))
{
setProgressBarIndeterminateVisibility(true);
}
}

} else if (v.getId() == R.id.write_alert_level_button)
{
if ((v.getTag() != null)
&& (v.getTag() instanceof BluetoothGattCharacteristic))
{
BluetoothGattCharacteristic ch = (BluetoothGattCharacteristic) v
.getTag();
ch.setValue(new byte[] { (byte) 0x00, (byte) 0xff });
if (mConnGatt.writeCharacteristic(ch))
{
Log.v(TAG, "1st wirte had readly");
setProgressBarIndeterminateVisibility(true);
}
}
}
}

private void init()
{
// BLE check
if (!BleUtil.isBLESupported(this))
{
Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT)
.show();
finish();
return;
}

// BT check
BluetoothManager manager = BleUtil.getManager(this);
if (manager != null)
{
mBTAdapter = manager.getAdapter();
}
if (mBTAdapter == null)
{
Toast.makeText(this, R.string.bt_unavailable, Toast.LENGTH_SHORT)
.show();
finish();
return;
}

// check BluetoothDevice
if (mDevice == null)
{
mDevice = getBTDeviceExtra();
if (mDevice == null)
{
finish();
return;
}
}

// button disable
mReadManufacturerNameButton.setEnabled(false);
mReadSerialNumberButton.setEnabled(false);
mWriteAlertLevelButton.setEnabled(false);

// connect to Gatt
if ((mConnGatt == null)
&& (mStatus == BluetoothProfile.STATE_DISCONNECTED))
{
Log.v(TAG, "try to connect with connectGatt");
// try to connect
mConnGatt = mDevice.connectGatt(this, false, mGattcallback);
mStatus = BluetoothProfile.STATE_CONNECTING;
} else
{
if (mConnGatt != null)
{
// re-connect and re-discover Services
Log.v(TAG, "try to connect with connect...");
mConnGatt.connect();
mConnGatt.discoverServices();
} else
{
Log.e(TAG, "state error");
finish();
return;
}
}
setProgressBarIndeterminateVisibility(true);
}

private BluetoothAdapter mBluetoothAdapter;

// 读取一个固定的mac 地址, 进行验证
private static final String BLUETOOTH_DEVICE_MAC = "D0:06:8E:75:56:16";

private BluetoothDevice getBTDeviceExtra()
{
BluetoothDevice bleDevice = null;
Intent intent = getIntent();
if (intent == null)
{
return null;
}

Bundle extras = intent.getExtras();
if (extras == null)
{
return null;
}

mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mBluetoothAdapter.startDiscovery();

Set<BluetoothDevice> bledevices = mBluetoothAdapter.getBondedDevices();
if (bledevices.size() > 0)
{
for (BluetoothDevice bluetoothDevice : bledevices)
{
Log.v(TAG,
"bletoothdevice mac address: "
+ bluetoothDevice.getAddress());
if (bluetoothDevice.getAddress().toString()
.equals(BLUETOOTH_DEVICE_MAC))
{
bleDevice = bluetoothDevice;
}
}
}

return bleDevice;
}

}