Android
Bluetooth Low Energy
Sök…
Introduktion
Denna dokumentation är tänkt som en förbättring jämfört med den ursprungliga dokumentationen och den kommer att fokusera på den senaste Bluetooth LE API introducerad i Android 5.0 (API 21). Både centrala och perifera roller kommer att täckas såväl som hur man börjar skanna och annonsera.
Hitta BLE-enheter
Följande behörigheter krävs för att använda Bluetooth-API: er:
android.permission.BLUETOOTH android.permission.BLUETOOTH_ADMIN
Om du inriktar dig på enheter med Android 6.0 ( API-nivå 23 ) eller högre och vill utföra skannings- / reklamoperationer kräver du en platstillstånd:
android.permission.ACCESS_FINE_LOCATION
eller
android.permission.ACCESS_COARSE_LOCATION
Obs.- Enheter med Android 6.0 (API-nivå 23) eller högre måste också ha Location Services aktiverade.
Ett BluetoothAdapter-objekt krävs för att starta skannings- / reklamoperationer:
BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
bluetoothAdapter = bluetoothManager.getAdapter();
startScan (ScanCallback callback)
i klassen BluetoothLeScanner är det mest grundläggande sättet att starta en skanningsoperation. Ett ScanCallback
objekt krävs för att få resultat:
bluetoothAdapter.getBluetoothLeScanner().startScan(new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
Log.i(TAG, "Remote device name: " + result.getDevice().getName());
}
});
Ansluter till en GATT-server
När du har upptäckt ett önskat BluetoothDevice-objekt kan du ansluta till det genom att använda dess connectGatt()
-metod som tar som parametrar ett Context-objekt, ett boolean som anger om du automatiskt ska ansluta till BLE-enheten och en BluetoothGattCallback-referens där anslutningshändelser och klientoperationer resultaten kommer att levereras:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
device.connectGatt(context, false, bluetoothGattCallback, BluetoothDevice.TRANSPORT_AUTO);
} else {
device.connectGatt(context, false, bluetoothGattCallback);
}
onConnectionStateChange
i BluetoothGattCallback för att ta emot anslutningar och avkopplingshändelser:
BluetoothGattCallback bluetoothGattCallback =
new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status,
int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
Log.i(TAG, "Connected to GATT server.");
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
Log.i(TAG, "Disconnected from GATT server.");
}
}
};
Skriva och läsa från egenskaper
När du är ansluten till en Gatt-server kommer du att interagera med den genom att skriva och läsa från serverns egenskaper. För att göra detta måste du först ta reda på vilka tjänster som finns tillgängliga på denna server och vilka egenskaper som är tillgängliga i varje tjänst:
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status,
int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
Log.i(TAG, "Connected to GATT server.");
gatt.discoverServices();
}
. . .
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
List<BluetoothGattService> services = gatt.getServices();
for (BluetoothGattService service : services) {
List<BluetoothGattCharacteristic> characteristics = service.getCharacteristics();
for (BluetoothGattCharacteristic characteristic : characteristics) {
///Once you have a characteristic object, you can perform read/write
//operations with it
}
}
}
}
En grundläggande skrivoperation går så här:
characteristic.setValue(newValue);
characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
gatt.writeCharacteristic(characteristic);
När skrivprocessen är klar kommer onCharacteristicWrite
metoden för din BluetoothGattCallback
att kallas:
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicWrite(gatt, characteristic, status);
Log.d(TAG, "Characteristic " + characteristic.getUuid() + " written);
}
En grundläggande skrivoperation går så här:
gatt.readCharacteristic(characteristic);
När skrivprocessen är klar kommer onCharacteristicRead
metoden för din BluetoothGattCallback
att kallas:
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
byte[] value = characteristic.getValue();
}
Prenumerera på aviseringar från Gatt-servern
Du kan begära att bli meddelad från Gatt-servern när värdet på en karakteristik har ändrats:
gatt.setCharacteristicNotification(characteristic, true);
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);
Alla aviseringar från servern kommer att tas emot i metoden onCharacteristicChanged
på din BluetoothGattCallback:
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
byte[] newValue = characteristic.getValue();
}
Annonsera en BLE-enhet
Du kan använda Bluetooth LE Advertising för att sända datapaket till alla enheter i närheten utan att behöva upprätta en anslutning först. Tänk på att det finns en strikt gräns på 31 byte av annonsdata. Reklam för din enhet är också det första steget mot att låta andra användare ansluta till dig.
Eftersom inte alla enheter stöder Bluetooth LE Advertising är det första steget att kontrollera att din enhet har alla nödvändiga krav för att stödja den. Efteråt kan du initiera ett BluetoothLeAdvertiser
objekt och med det kan du starta annonsering:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && bluetoothAdapter.isMultipleAdvertisementSupported())
{
BluetoothLeAdvertiser advertiser = bluetoothAdapter.getBluetoothLeAdvertiser();
AdvertiseData.Builder dataBuilder = new AdvertiseData.Builder();
//Define a service UUID according to your needs
dataBuilder.addServiceUuid(SERVICE_UUID);
dataBuilder.setIncludeDeviceName(true);
AdvertiseSettings.Builder settingsBuilder = new AdvertiseSettings.Builder();
settingsBuilder.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_POWER);
settingsBuilder.setTimeout(0);
//Use the connectable flag if you intend on opening a Gatt Server
//to allow remote connections to your device.
settingsBuilder.setConnectable(true);
AdvertiseCallback advertiseCallback=new AdvertiseCallback() {
@Override
public void onStartSuccess(AdvertiseSettings settingsInEffect) {
super.onStartSuccess(settingsInEffect);
Log.i(TAG, "onStartSuccess: ");
}
@Override
public void onStartFailure(int errorCode) {
super.onStartFailure(errorCode);
Log.e(TAG, "onStartFailure: "+errorCode );
}
};
advertising.startAdvertising(settingsBuilder.build(),dataBuilder.build(),advertiseCallback);
}
Använda en Gatt-server
För att din enhet ska fungera som en kringutrustning måste du först öppna en BluetoothGattServer
och fylla den med minst en BluetoothGattService
och en BluetoothGattCharacteristic
:
BluetoothGattServer server=bluetoothManager.openGattServer(context, bluetoothGattServerCallback);
BluetoothGattService service = new BluetoothGattService(SERVICE_UUID, BluetoothGattService.SERVICE_TYPE_PRIMARY);
Detta är ett exempel på en BluetoothGattCharacteristic med fullständig skrivning, läsning och anmälan behörigheter. Enligt dina behov kanske du vill finjustera behörigheterna som du ger denna egenskap:
BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(CHARACTERISTIC_UUID,
BluetoothGattCharacteristic.PROPERTY_READ | BluetoothGattCharacteristic.PROPERTY_WRITE |
BluetoothGattCharacteristic.PROPERTY_NOTIFY,
BluetoothGattCharacteristic.PERMISSION_READ | BluetoothGattCharacteristic.PERMISSION_WRITE);
characteristic.addDescriptor(new BluetoothGattDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"), BluetoothGattCharacteristic.PERMISSION_WRITE));
service.addCharacteristic(characteristic);
server.addService(service);
BluetoothGattServerCallback
ansvarar för att ta emot alla händelser relaterade till din BluetoothGattServer
:
BluetoothGattServerCallback bluetoothGattServerCallback= new BluetoothGattServerCallback() {
@Override
public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
super.onConnectionStateChange(device, status, newState);
}
@Override
public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicReadRequest(device, requestId, offset, characteristic);
}
@Override
public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
super.onCharacteristicWriteRequest(device, requestId, characteristic, preparedWrite, responseNeeded, offset, value);
}
@Override
public void onDescriptorReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattDescriptor descriptor) {
super.onDescriptorReadRequest(device, requestId, offset, descriptor);
}
@Override
public void onDescriptorWriteRequest(BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
super.onDescriptorWriteRequest(device, requestId, descriptor, preparedWrite, responseNeeded, offset, value);
}
När du får en begäran om att skriva / läsa till en egenskap eller deskriptor måste du skicka ett svar på det för att begäran ska kunna slutföras:
@Override
public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicReadRequest(device, requestId, offset, characteristic);
server.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, YOUR_RESPONSE);
}