android藍牙BLE的開發:
1、最新的api是使用 bluetoothLeScanner.startScan
廢棄了 adapter.startLeScan
2、順序
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import static android.bluetooth.BluetoothDevice.TRANSPORT_LE;
public class BlueActivity extends AppCompatActivity {
private ArrayList<String> data = null;
private ListView listView = null;
private ArrayAdapter adapter = null;
private Button button;
private BluetoothManager bluetoothManager;
private BluetoothAdapter bluetoothAdapter;//app可以使用藍牙適配器bluetoothAdapter與藍牙硬件交互
private BluetoothLeScanner bluetoothLeScanner;
//先定幾個服務類型的UUID
/*
* 服務 TYPE_SERVICE, "000019D0-0000-1000-8000-00805f9b34fb"
*/
public static UUID TYPE_SERVICE = UUID.fromString("000019D0-0000-1000-8000-00805f9b34fb");
/* Mandatory Current Time Information Characteristic
* 讀
* TYPE_CHARACTERISTIC, "00002E00-0000-1000-8000-00805f9b34fb"
* */
public static UUID TYPE_CHARACTERISTIC_READ = UUID.fromString("00002E00-0000-1000-8000-00805f9b34fb");
/*
* 寫
* TYPE_CHARACTERISTIC, "00002E01-0000-1000-8000-00805f9b34fb"
* */
public static UUID TYPE_CHARACTERISTIC_WRITE = UUID.fromString("00002E01-0000-1000-8000-00805f9b34fb");
private Handler handler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ble);
// 獲得數據
this.data = new ArrayList<>();
// 初始化控件
this.initView();
}
private void initView() {
// 獲得button
this.button = findViewById(R.id.search);
this.button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 掃描藍牙
scanBle();
}
});
// 初始化ListView
this.adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, this.data);
this.listView = findViewById(R.id.lv);
this.listView.setAdapter(adapter);
}
BluetoothGatt mBluetoothGatt;
// 藍牙掃描回調
private ScanCallback newBtsc = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
BluetoothDevice device = result.getDevice();
// 更新數據
data.add(device.getAddress() + "--" + device.getName());
adapter.notifyDataSetChanged();
// BLE中心設備連接外圍設備的數量有限(大概2~7個),在建立新連接之前必須釋放舊連接資源,否則容易出現連接錯誤133
// closeConn();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mBluetoothGatt = device.connectGatt(BlueActivity.this, true, bluetoothGattCallback,TRANSPORT_LE);
}else {
mBluetoothGatt = device.connectGatt(BlueActivity.this, true, bluetoothGattCallback);
}
Log.e("ble:", device.getAddress() + "--" + device.getName());
}
@Override
public void onBatchScanResults(List<ScanResult> results) {
super.onBatchScanResults(results);
}
@Override
public void onScanFailed(int errorCode) {
super.onScanFailed(errorCode);
}
};
private void closeConn() {
if (mBluetoothGatt != null) {
mBluetoothGatt.disconnect();
mBluetoothGatt.close();
}
}
// 掃描藍牙
private void scanBle() {
// 初始化藍牙適配器
bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
if (bluetoothManager == null) {
return;
}
bluetoothAdapter = bluetoothManager.getAdapter();
// 打開藍牙
if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled()) {
Intent enable = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enable, 1);
} else {
bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner();
bluetoothLeScanner.startScan(newBtsc);
// 設置掃描時間
handler.postDelayed(new Runnable() {
@Override
public void run() {
bluetoothLeScanner.stopScan(newBtsc);
}
}, 10000);
}
}
private String TAG = "tag";
BluetoothGattCallback bluetoothGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
String intentAction;
Log.i(TAG, "newState=="+newState);
if (newState == BluetoothProfile.STATE_CONNECTED) {
// intentAction = ACTION_GATT_CONNECTED;
// broadcastUpdate(intentAction);
Log.i(TAG, "Connected to GATT server.");
// Attempts to discover services after successful connection.
//鏈接成功,開始搜索服務
Log.i(TAG, "Attempting to start service discovery:" + gatt.discoverServices());
// writeandreadData(gatt);
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
// intentAction = ACTION_GATT_DISCONNECTED;
Log.i(TAG, "Disconnected from GATT server.");
// broadcastUpdate(intentAction);
} else if (newState == BluetoothProfile.STATE_CONNECTING) {
// intentAction = ACTION_GATT_CONNECTING;
Log.i(TAG, "connecting from GATT server.");
// broadcastUpdate(intentAction);
} else {
// intentAction = ACTION_GATT_DISCONNECTING;
Log.i(TAG, "Disconnecting from GATT server.");
// broadcastUpdate(intentAction);
}
}
//發現設備,(真正建立連接)
// 直到這裏纔是真正建立了可通信的連接
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
Log.i(TAG, String.format("onServicesDiscovered:%s,%s,%s", gatt.getDevice().getName(), gatt.getDevice().getAddress(), status));
if (status == BluetoothGatt.GATT_SUCCESS) { //BLE服務發現成功
// 遍歷獲取BLE服務Services/Characteristics/Descriptors的全部UUID
for (BluetoothGattService service : gatt.getServices()) {
StringBuilder allUUIDs = new StringBuilder("UUIDs={\nS=" + service.getUuid().toString());
for (BluetoothGattCharacteristic characteristic : service.getCharacteristics()) {
allUUIDs.append(",\nC=").append(characteristic.getUuid());
for (BluetoothGattDescriptor descriptor : characteristic.getDescriptors())
allUUIDs.append(",\nD=").append(descriptor.getUuid());
}
allUUIDs.append("}");
Log.i(TAG, "onServicesDiscovered:" + allUUIDs.toString());
}
}
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
UUID uuid = characteristic.getUuid();
String valueStr = new String(characteristic.getValue());
Log.i(TAG, String.format("onCharacteristicRead:%s,%s,%s,%s,%s", gatt.getDevice().getName(), gatt.getDevice().getAddress(), uuid, valueStr, status));
}
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
UUID uuid = characteristic.getUuid();
String valueStr = new String(characteristic.getValue());
Log.i(TAG, String.format("onCharacteristicWrite:%s,%s,%s,%s,%s", gatt.getDevice().getName(), gatt.getDevice().getAddress(), uuid, valueStr, status));
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
UUID uuid = characteristic.getUuid();
String valueStr = new String(characteristic.getValue());
Log.i(TAG, String.format("onCharacteristicChanged:%s,%s,%s,%s", gatt.getDevice().getName(), gatt.getDevice().getAddress(), uuid, valueStr));
}
@Override
public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
UUID uuid = descriptor.getUuid();
String valueStr = Arrays.toString(descriptor.getValue());
Log.i(TAG, String.format("onDescriptorRead:%s,%s,%s,%s,%s", gatt.getDevice().getName(), gatt.getDevice().getAddress(), uuid, valueStr, status));
}
@Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
UUID uuid = descriptor.getUuid();
String valueStr = Arrays.toString(descriptor.getValue());
Log.i(TAG, String.format("onDescriptorWrite:%s,%s,%s,%s,%s", gatt.getDevice().getName(), gatt.getDevice().getAddress(), uuid, valueStr, status));
}
};
BluetoothGattCharacteristic characteristic;
private void writeandreadData(BluetoothGatt bluetoothGatt) {
BluetoothGattService service = bluetoothGatt.getService(TYPE_SERVICE);
if (service != null) {
characteristic = service.getCharacteristic(TYPE_CHARACTERISTIC_READ);
if (characteristic != null) {
//設置characteristic的通知,觸發bluetoothGatt.onCharacteristicWrite()事件。
bluetoothGatt.setCharacteristicNotification(characteristic, true);
characteristic.setValue("0x06");
bluetoothGatt.writeCharacteristic(characteristic);
}
}
}
}