android蓝牙4.0BLE
程序员文章站
2024-03-24 23:32:04
...
android4.4以后支持蓝牙4.0BLE,android5.0以后支持作为BLE外部设备peripheral,android5.0之前的版本只能作为BLE的中心设备central。
android的例子BluetoothAdvertisements,可以作为外设被发现,但没有提供服务,和收发数据。
下面的代码提供了服务,可以被中心设备发现,和收发数据。
import java.util.UUID;
import android.app.Notification;
import android.app.Service;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattServer;
import android.bluetooth.BluetoothGattServerCallback;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.AdvertiseCallback;
import android.bluetooth.le.AdvertiseData;
import android.bluetooth.le.AdvertiseSettings;
import android.bluetooth.le.BluetoothLeAdvertiser;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
public class GattServerService extends Service {
private static final String TAG = GattServerService.class.getSimpleName();
public static final String START_ADVERTISING = "GattServerService.start.advertising";
public static final String ADVERTISING_STATE = "GattServerService.advertising.state";
public static final String ADVERTISING_ON = "on";
public static final String ADVERTISING_OFF = "off";
public static final String BLE_CMD = "GattServerService.ble.cmd";
public static final String LOCAL_CMD = "GattServerService.local.cmd";
private static final String BLE_ERROR = "ble_error";
public static final int MAX_SENDED_VALUE_LEN = 255;
private static final long ADVERTISING_TIME = 60 * 1000;
private static final UUID CMD_UUID = UUID
.fromString("0000b81d-0000-1000-8000-00805f9b34fb");
private BluetoothLeAdvertiser mBluetoothLeAdvertiser;
private BluetoothGattServer mBluetoothGattServer;
private AdvertiseCallback mAdvertiseCallback;
private Handler mHandler = new Handler();
private Runnable mStopAdvertisingRunnable;
private BluetoothDevice mConnectedDevice;
private BluetoothGattCharacteristic mCmdCharacteristic;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
Log.d(TAG, "onCreate");
super.onCreate();
startForeground(0, new Notification());
initBluetooth();
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(START_ADVERTISING);
intentFilter.addAction(LOCAL_CMD);
registerReceiver(mBroadcastReceiver, intentFilter);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy");
super.onDestroy();
stopAdvertising();
mBluetoothLeAdvertiser = null;
if (mBluetoothGattServer != null) {
if (mConnectedDevice != null) {
mBluetoothGattServer.cancelConnection(mConnectedDevice);
mConnectedDevice = null;
}
mBluetoothGattServer.close();
mBluetoothGattServer = null;
}
}
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (START_ADVERTISING.equals(action)) {
startAdvertising();
} else if (LOCAL_CMD.equals(action)) {
byte[] value = intent.getByteArrayExtra(LOCAL_CMD);
onLocalCmdReceived(value);
}
}
};
private void startAdvertising() {
Log.d(TAG, "startAdvertising");
if (mAdvertiseCallback == null && mBluetoothLeAdvertiser != null) {
mAdvertiseCallback = new AdvertiseCallback() {
@Override
public void onStartSuccess(AdvertiseSettings settingsInEffect) {
super.onStartSuccess(settingsInEffect);
Log.d(TAG, "AdvertiseCallback.onStartSuccess");
if (mStopAdvertisingRunnable != null) {
mHandler.removeCallbacks(mStopAdvertisingRunnable);
mStopAdvertisingRunnable = null;
}
mStopAdvertisingRunnable = new Runnable() {
@Override
public void run() {
mStopAdvertisingRunnable = null;
stopAdvertising();
}
};
mHandler.postDelayed(mStopAdvertisingRunnable,
ADVERTISING_TIME);
onAdvertisingStateChanged();
}
@Override
public void onStartFailure(int errorCode) {
super.onStartFailure(errorCode);
Log.d(TAG, "AdvertiseCallback.onStartFailure");
mAdvertiseCallback = null;
onAdvertisingStateChanged();
}
};
AdvertiseSettings.Builder settingsBuilder = new AdvertiseSettings.Builder();
settingsBuilder
.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_POWER);
settingsBuilder.setTimeout(0);
AdvertiseSettings advertiseSettings = settingsBuilder.build();
AdvertiseData.Builder dataBuilder = new AdvertiseData.Builder();
// dataBuilder.addServiceUuid(Constants.Service_UUID);
dataBuilder.setIncludeDeviceName(true);
AdvertiseData advertiseData = dataBuilder.build();
mBluetoothLeAdvertiser.startAdvertising(advertiseSettings,
advertiseData, mAdvertiseCallback);
}
}
private void stopAdvertising() {
Log.d(TAG, "stopAdvertising");
if (mStopAdvertisingRunnable != null) {
mHandler.removeCallbacks(mStopAdvertisingRunnable);
mStopAdvertisingRunnable = null;
}
if (mAdvertiseCallback != null) {
if (mBluetoothLeAdvertiser != null) {
mBluetoothLeAdvertiser.stopAdvertising(mAdvertiseCallback);
}
mAdvertiseCallback = null;
onAdvertisingStateChanged();
}
}
private void initBluetooth() {
BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
if (mBluetoothLeAdvertiser == null) {
mBluetoothLeAdvertiser = bluetoothManager.getAdapter()
.getBluetoothLeAdvertiser();
}
if (mBluetoothGattServer == null) {
mBluetoothGattServer = bluetoothManager.openGattServer(
GattServerService.this, mBluetoothGattServerCallback);
BluetoothGattService gattService = new BluetoothGattService(
CMD_UUID, BluetoothGattService.SERVICE_TYPE_PRIMARY);
BluetoothGattCharacteristic gattCharacteristic = new BluetoothGattCharacteristic(
CMD_UUID, BluetoothGattCharacteristic.PROPERTY_READ
| BluetoothGattCharacteristic.PROPERTY_WRITE
| BluetoothGattCharacteristic.PROPERTY_NOTIFY,
BluetoothGattCharacteristic.PERMISSION_READ
| BluetoothGattCharacteristic.PERMISSION_WRITE);
gattCharacteristic.setValue("");
gattService.addCharacteristic(gattCharacteristic);
mBluetoothGattServer.addService(gattService);
}
}
private void notifyCmdCharacteristicChanged(byte[] value) {
Log.d(TAG, "notifyCmdCharacteristicChanged: ");
if (mBluetoothGattServer != null && mConnectedDevice != null
&& mCmdCharacteristic != null && value != null
&& value.length < MAX_SENDED_VALUE_LEN) {
dumpBytes(value);
mCmdCharacteristic.setValue(value);
boolean rst = mBluetoothGattServer.notifyCharacteristicChanged(
mConnectedDevice, mCmdCharacteristic, true);
if (!rst) {
try {
throw new Exception(BLE_ERROR);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
private BluetoothGattServerCallback mBluetoothGattServerCallback = new BluetoothGattServerCallback() {
private byte[] cmdBuffer = null;
@Override
public void onConnectionStateChange(BluetoothDevice device, int status,
int newState) {
super.onConnectionStateChange(device, status, newState);
Log.d(TAG, "onConnectionStateChange: status=" + status
+ ", newState=" + newState);
if (newState == BluetoothProfile.STATE_CONNECTED) {
mConnectedDevice = device;
stopAdvertising();
} else {
mConnectedDevice = null;
}
}
@Override
public void onServiceAdded(int status, BluetoothGattService service) {
super.onServiceAdded(status, service);
Log.d(TAG, "onServiceAdded: status=" + status);
if (status == BluetoothGatt.GATT_SUCCESS) {
mCmdCharacteristic = service.getCharacteristic(CMD_UUID);
}
}
@Override
public void onCharacteristicReadRequest(BluetoothDevice device,
int requestId, int offset,
BluetoothGattCharacteristic characteristic) {
super.onCharacteristicReadRequest(device, requestId, offset,
characteristic);
Log.d(TAG, "onCharacteristicReadRequest: requestId=" + requestId
+ ", offset=" + offset);
byte[] value = characteristic.getValue();
dumpBytes(value);
if (mBluetoothGattServer != null) {
mBluetoothGattServer.sendResponse(device, requestId,
BluetoothGatt.GATT_SUCCESS, offset, new byte[] { 0 });
}
}
@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);
Log.d(TAG, "onCharacteristicWriteRequest: requestId=" + requestId
+ ", offset=" + offset + ", preparedWrite=" + preparedWrite
+ ", responseNeeded=" + responseNeeded);
dumpBytes(value);
if (value != null && value.length > 0) {
if (preparedWrite) {
if (cmdBuffer == null) {
cmdBuffer = value;
} else {
byte[] tmp = new byte[cmdBuffer.length + value.length];
System.arraycopy(cmdBuffer, 0, tmp, 0, cmdBuffer.length);
System.arraycopy(value, 0, tmp, cmdBuffer.length,
value.length);
cmdBuffer = tmp;
}
} else {
cmdBuffer = null;
onBleCmdReceived(value);
}
}
if (mBluetoothGattServer != null) {
mBluetoothGattServer.sendResponse(device, requestId,
BluetoothGatt.GATT_SUCCESS, offset, value);
}
}
@Override
public void onDescriptorReadRequest(BluetoothDevice device,
int requestId, int offset, BluetoothGattDescriptor descriptor) {
super.onDescriptorReadRequest(device, requestId, offset, descriptor);
Log.d(TAG, "onDescriptorReadRequest: requestId=" + requestId
+ ", offset=" + offset);
}
@Override
public void onDescriptorWriteRequest(BluetoothDevice device,
int requestId, BluetoothGattDescriptor descriptor,
boolean preparedWrite, boolean responseNeeded, int offset,
byte[] value) {
super.onDescriptorReadRequest(device, requestId, offset, descriptor);
Log.d(TAG, "onDescriptorWriteRequest: requestId=" + requestId
+ ", offset=" + offset);
}
@Override
public void onExecuteWrite(BluetoothDevice device, int requestId,
boolean execute) {
super.onExecuteWrite(device, requestId, execute);
Log.d(TAG, "onExecuteWrite: requestId=" + requestId + ", execute="
+ execute);
onBleCmdReceived(cmdBuffer);
cmdBuffer = null;
if (mBluetoothGattServer != null) {
mBluetoothGattServer.sendResponse(device, requestId,
BluetoothGatt.GATT_SUCCESS, 0, null);
}
}
@Override
public void onNotificationSent(BluetoothDevice device, int status) {
super.onNotificationSent(device, status);
Log.d(TAG, "onNotificationSent: status=" + status);
}
@Override
public void onMtuChanged(BluetoothDevice device, int mtu) {
super.onMtuChanged(device, mtu);
Log.d(TAG, "onMtuChanged: mtu=" + mtu);
}
};
private void onAdvertisingStateChanged() {
Intent intent = new Intent(ADVERTISING_STATE);
String state = mAdvertiseCallback != null ? ADVERTISING_ON
: ADVERTISING_OFF;
intent.putExtra(ADVERTISING_STATE, state);
sendBroadcast(intent);
Log.d(TAG, "onAdvertisingStateChanged:" + state);
}
private void onLocalCmdReceived(byte[] value) {
notifyCmdCharacteristicChanged(value);
}
private void onBleCmdReceived(byte[] value) {
Intent intent = new Intent(BLE_CMD);
intent.putExtra(BLE_CMD, value);
sendBroadcast(intent);
Log.d(TAG, "onBleCmdReceived: ");
dumpBytes(value);
}
private void dumpBytes(byte[] value) {
if (value != null && value.length > 0) {
StringBuilder sb = new StringBuilder(2 * value.length);
for (byte b : value) {
sb.append(Byte.toHexString(b, true));
}
Log.d(TAG, sb.toString());
}
Log.d(TAG, "empty value");
}
}
下面的代码参照android的例子BluetoothLeGatt,和BLE外设收发数据
package com.example.android.bluetoothlegatt;
import java.util.UUID;
import android.app.Notification;
import android.app.Service;
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.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.text.TextUtils;
import android.util.Log;
public class GattClientService extends Service {
private static final String TAG = GattClientService.class.getSimpleName();
private static final UUID CMD_UUID = UUID
.fromString("0000b81d-0000-1000-8000-00805f9b34fb");
public static final String GATT_CONNECT = "com.example.android.bluetoothlegatt.connect";
public static final String GATT_CONNECT_ON = "on";
public static final String GATT_CONNECT_OFF = "off";
public static final String GATT_CONNECT_ADDR = "com.example.android.bluetoothlegatt.connect.addr";
public static final String CONNECT_STATE = "com.example.android.bluetoothlegatt.connect.state";
public static final String CMD_LOCAL = "com.example.android.bluetoothlegatt.cmd.local";
public static final String CMD_BLE = "com.example.android.bluetoothlegatt.cmd.ble";
public static final int STATE_DISCONNECTED = 0;
public static final int STATE_CONNECTED = 1;
private BluetoothAdapter mBluetoothAdapter;
private BluetoothGatt mBluetoothGatt;
private BluetoothGattCharacteristic mCmdGattCharacteristic;
private String mBleAddr;
private int mConnectionState = STATE_DISCONNECTED;
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status,
int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
mConnectionState = STATE_CONNECTED;
mBluetoothGatt.discoverServices();
} else {
mConnectionState = STATE_DISCONNECTED;
}
onBleConnectionStateChange(mConnectionState);
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
BluetoothGattService service = gatt.getService(CMD_UUID);
if (service != null) {
mCmdGattCharacteristic = service
.getCharacteristic(CMD_UUID);
if (mCmdGattCharacteristic != null) {
mBluetoothGatt.setCharacteristicNotification(
mCmdGattCharacteristic, true);
}
}
}
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
Log.d(TAG, "onCharacteristicChanged");
byte[] value = characteristic.getValue();
onValueReaded(value);
}
};
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (GATT_CONNECT.equals(action)) {
String on = intent.getStringExtra(GATT_CONNECT);
String addr = intent.getStringExtra(GATT_CONNECT_ADDR);
if (GATT_CONNECT_ON.equals(on)) {
connect(addr);
} else {
disconnect();
}
} else if (CMD_LOCAL.equals(action)) {
byte[] value = intent.getByteArrayExtra(CMD_LOCAL);
writeValue(value);
}
}
};
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
startForeground(0, new Notification());
BluetoothManager mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = mBluetoothManager.getAdapter();
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(GATT_CONNECT);
intentFilter.addAction(CMD_LOCAL);
registerReceiver(mBroadcastReceiver, intentFilter);
}
private boolean connect(String address) {
if (TextUtils.isEmpty(address)) {
return false;
}
if (address.equals(mBleAddr) && mBluetoothGatt != null
&& mConnectionState == STATE_CONNECTED) {
return true;
} else if (address.equals(mBleAddr) && mBluetoothGatt != null) {
return mBluetoothGatt.connect();
} else if (mBluetoothGatt != null) {
mBluetoothGatt.close();
mBluetoothGatt = null;
mBleAddr = null;
}
final BluetoothDevice device = mBluetoothAdapter
.getRemoteDevice(address);
if (device == null) {
return false;
}
mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
if (mBluetoothGatt == null) {
return false;
}
mBleAddr = address;
return true;
}
private void disconnect() {
if (mBluetoothGatt != null) {
mBluetoothGatt.disconnect();
}
}
private void onBleConnectionStateChange(int state) {
final Intent intent = new Intent(CONNECT_STATE);
intent.putExtra(CONNECT_STATE, state);
sendBroadcast(intent);
}
private void writeValue(byte[] value) {
Log.d(TAG, "writeValue");
dumpBytes(value);
if (mCmdGattCharacteristic != null && mBluetoothGatt != null
&& mConnectionState == STATE_CONNECTED) {
mCmdGattCharacteristic.setValue(value);
mBluetoothGatt.writeCharacteristic(mCmdGattCharacteristic);
}
}
private void onValueReaded(byte[] value) {
Log.d(TAG, "onValueReaded");
dumpBytes(value);
final Intent intent = new Intent(CMD_BLE);
intent.putExtra(CMD_BLE, value);
sendBroadcast(intent);
}
private void dumpBytes(byte[] value) {
if (value != null && value.length > 0) {
StringBuilder sb = new StringBuilder(2 * value.length);
for (byte b : value) {
sb.append(Byte.toHexString(b, true));
}
Log.d(TAG, sb.toString());
return;
}
Log.d(TAG, "empty value");
}
}
转载于:https://my.oschina.net/kyle960/blog/847638
上一篇: 【pytorch】使用scatter_()进行one-hot编码
下一篇: BLE 开发总结