欢迎大家访问我的博客http://blog.csdn.net/mikejaps,专注于android ios app 开发
最近做蓝牙BLE的开发,此项目和网上别人的稍微有点不同,手机需要连接多个BLE设备,此部分网上的资料很少,所以拿出来和大家分享一下
//初始化
private void initBt() {
manager = BluetoothManager.getInstance();
manager.setContext(this);
if (!getPackageManager().hasSystemFeature(
PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, "您的手机不支持BLE", Toast.LENGTH_SHORT).show();
finish();
}
BluetoothAdapter btaAdapter = BluetoothAdapter.getDefaultAdapter();
if (!btaAdapter.isEnabled()) {
btaAdapter.enable();
}
if (!manager.isScanning)
new ScanLeTask().execute();
}
//扫描ble 设备
private class ScanLeTask extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... params) {
manager.scanLeDevice(true, mLeScanCallback);
return null;
}
}
// Device scan callback.
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() {
Log.d(TAG, device.getName());
BtDevice mDevice = new BtDevice(device.getAddress(),
device.getName());
if (!mList.contains(mDevice)) {
mList.add(mDevice);
View view = getLayoutInflater().inflate(
R.layout.deviceitem, null);
view.setTag(mList.size() - 1);
TextView textView = (TextView) view
.findViewById(R.id.name);
Button button = (Button) view.findViewById(R.id.icon);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
View view = (View) v.getParent();
int index = (Integer) view.getTag();
manager.connect(mList.get(index).getAddr(),
index);
Log.d(TAG, "index is:" + index);
}
});
textView.setText(mDevice.getName());
container.addView(view);
}
}
});
}
};
//封装的核心类
public class BluetoothManager {
protected static final String TAG = "BluetoothManager";
private Context context;
public boolean isScanning;
private int index;
private Handler handler = new Handler();
// 10秒后停止查找搜索.
private static final long SCAN_PERIOD = 10000;
private static BluetoothAdapter btaAdapter = BluetoothAdapter
.getDefaultAdapter();
// public static BluetoothGatt mBluetoothGatt;
private int disconStatus;
public final static String ACTION_GATT_CONNECTED = "com.example.bluetooth.le.ACTION_GATT_CONNECTED";
public final static UUID UUID_HEART_RATE_MEASUREMENT = UUID
.fromString(SampleGattAttributes.HEART_RATE_MEASUREMENT);
private static BluetoothManager instance;
private BluetoothManager() {
}
public static BluetoothManager getInstance() {
if (instance == null) {
synchronized (BluetoothManager.class) {
if (instance == null) {
instance = new BluetoothManager();
}
}
}
return instance;
}
public void setContext(Context mContext) {
context = mContext;
}
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status,
int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
Log.d(TAG, "Connected to GATT server.");
// Attempts to discover services after successful connection.
Log.d(TAG,
"Attempting to start service discovery:"
+ gatt.discoverServices());
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
Log.d(TAG, "Disconnected from GATT server.");
if (disconStatus == 129) {
close(gatt);
Log.d(TAG, "----129----");
btaAdapter.disable();
try {
Thread.sleep(2500);
} catch (InterruptedException e) {
e.printStackTrace();
}
btaAdapter.enable();
}
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
if (gatt == null)
return;
// writeData(gatt, new byte[] { 0x11, 0x12 });
// displayGattServices(gatt.getServices());
Log.d(TAG, "BluetoothGatt.GATT_SUCCESS");
} else {
Log.d(TAG, "onServicesDiscovered received: " + status);
disconStatus = status;
}
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
// broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
Log.d(TAG, "onCharacteristicRead");
// Toast.makeText(BluetoothLeService.this,
// "onCharacteristicRead successfully", 100).show();
}
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
// broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
Log.d(TAG, "onCharacteristicChanged");
}
};
public void writeData(BluetoothGatt gatt, byte[] datas) {
if (/* btaAdapter == null || */gatt == null) {
Log.w(TAG, "BluetoothGatt is null can not writeData.");
return;
}
BluetoothGattService gattService = gatt.getService(UUID
.fromString(SampleGattAttributes.HEART_RATE_MEASUREMENT));
if (gattService == null) {
Log.w(TAG,
"the gattService for BluetoothGattService is null,can not write data");
return;
}
BluetoothGattCharacteristic characteristic = gattService
.getCharacteristic(UUID
.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
if (characteristic == null) {
Log.w(TAG,
"the uuid for BluetoothGattCharacteristic is null,can not write data");
return;
}
characteristic.setValue(datas);
// gatt.writeCharacteristic(characteristic);
Log.i(TAG,
"writeCharacteristic"
+ gatt.writeCharacteristic(characteristic));
}
/**
* Enables or disables notification on a give characteristic.
*
* @param characteristic
* Characteristic to act on.
* @param enabled
* If true, enable notification. False otherwise.
*/
public void setCharacteristicNotification(
BluetoothGattCharacteristic characteristic, boolean enabled) {
BluetoothGatt gatt = MainActivity.mList.get(index).getmBluetoothGatt();
if (btaAdapter == null || gatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
gatt.setCharacteristicNotification(characteristic, enabled);
// This is specific to Heart Rate Measurement.
if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) {
BluetoothGattDescriptor descriptor = characteristic
.getDescriptor(UUID
.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
descriptor
.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
gatt.writeDescriptor(descriptor);
}
}
private boolean isPrepared;
public void scanLeDevice(final boolean enable,
final BluetoothAdapter.LeScanCallback mLeScanCallback) {
if (!isPrepared) {
isPrepared = true;
Looper.prepare();
}
if (enable) {
// Stops scanning after a pre-defined scan period.
handler.postDelayed(new Runnable() {
@Override
public void run() {
isScanning = false;
btaAdapter.stopLeScan(mLeScanCallback);
Log.d(TAG, "STOP....");
}
}, SCAN_PERIOD);
isScanning = true;
btaAdapter.startLeScan(mLeScanCallback);
} else {
isScanning = false;
btaAdapter.stopLeScan(mLeScanCallback);
}
}
/**
* After using a given BLE device, the app must call this method to ensure
* resources are released properly.
*/
public void close(BluetoothGatt gatt) {
if (gatt == null) {
return;
}
gatt.close();
gatt = null;
}
/**
* Connects to the GATT server hosted on the Bluetooth LE device.
*
* @param address
* The device address of the destination device.
*
* @return Return true if the connection is initiated successfully. The
* connection result is reported asynchronously through the
* {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
* callback.
*/
public boolean connect(final String address, int index) {
this.index = index;
if (address == null) {
Log.w(TAG, " unspecified address.");
return false;
}
final BluetoothDevice device = btaAdapter.getRemoteDevice(address);
if (device == null) {
Log.w(TAG, "Device not found. Unable to connect.");
return false;
}
// We want to directly connect to the device, so we are setting the
// autoConnect
// parameter to false.
// MainActivity.mList.get(index).setmBluetoothGatt(gatt);
if (!MainActivity.gattMap.containsKey(MainActivity.mList.get(index)
.getAddr())) {
BluetoothGatt gatt = device.connectGatt(context, true,
mGattCallback);
MainActivity.gattMap.put(MainActivity.mList.get(index).getAddr(),
gatt);
Log.d(TAG, "Trying to create a new connection."
+ MainActivity.gattMap.size());
} else
Log.d(TAG, "allready connected." + MainActivity.gattMap.size());
return true;
}
/**
* Disconnects an existing connection or cancel a pending connection. The
* disconnection result is reported asynchronously through the
* {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
* callback.
*/
public void disconnect(int index) {
if (btaAdapter == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
MainActivity.mList.get(index).getmBluetoothGatt().disconnect();
}
}
//用于发送数据的线程池
public class BluetoothExecutor {
private static final String TAG = "TcpExecutor";
private static BluetoothExecutor instance = null;
private ThreadPoolExecutor executor;
private Semaphore semp;
private BluetoothManager manager;
private BluetoothExecutor() {
executor = new ThreadPoolExecutor(1, 7, 500, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<Runnable>(20));
semp = new Semaphore(1);
manager = BluetoothManager.getInstance();
}
public static BluetoothExecutor getInstans() {
if (instance == null) {
synchronized (BluetoothExecutor.class) {
if (instance == null)
instance = new BluetoothExecutor();
}
}
return instance;
}
public void execute(final byte[] chars) {
Log.d(TAG, "execute start" + executor.getActiveCount());
try {
semp.acquire();
final Set<String> set = MainActivity.gattMap.keySet();
Log.d(TAG, "Set<String>" + set);
for (int i = 0; i < MainActivity.gattMap.size(); i++) {
executor.execute(new Runnable() {
@Override
public void run() {
manager.writeData(
MainActivity.gattMap.get(set.iterator().next()),
chars);
}
});
}
while (executor.getActiveCount() != 0)
;
semp.release();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}