Android 安卓手机作为可编程外围设备

Android 安卓手机作为可编程外围设备,android,bluetooth-lowenergy,gatt,Android,Bluetooth Lowenergy,Gatt,我正试图让nrf52 DK充当中央设备,并接受来自android设备的警报通知。我在nrf端使用了开箱即用的nordic alert通知示例,它应该能够处理通知 在android end中,我使用的是修改后的Blegat示例,我还添加了gatt服务器部件 目前,整个shebang的工作原理如下: 1.nrf板宣传自己和手机扫描(此时角色是传统的,因为nrf板中没有UI)。 2.我已经打开了gattserver,创建了alert_notification_服务,并为其添加了特性,还向gattser

我正试图让nrf52 DK充当中央设备,并接受来自android设备的警报通知。我在nrf端使用了开箱即用的nordic alert通知示例,它应该能够处理通知

在android end中,我使用的是修改后的Blegat示例,我还添加了gatt服务器部件

目前,整个shebang的工作原理如下: 1.nrf板宣传自己和手机扫描(此时角色是传统的,因为nrf板中没有UI)。 2.我已经打开了gattserver,创建了alert_notification_服务,并为其添加了特性,还向gattserver添加了所有内容。 3.我通过常规gatt连接连接到nrf板

我可以看到该服务是由板连接的,它尝试读取两个特征,并为其中一个写入描述符。但是,通知(出于测试目的,我正在为新警报使用硬编码内容)不能正常工作

以下是终端的跟踪输出:

       04-08 16:01:24.006 BluetoothLeScanner: onScanResult() - ScanResult{mDevice=CE:CE:67:C2:71:FE, mScanRecord=ScanRecord [mAdvertiseFlags=6, mServiceUuids=null, mManufacturerSpecificData={}, mServiceData={}, mTxPowerLevel=-2147483648, mDeviceName=Nordic_Alert_Notif.], mRssi=-35, mTimestampNanos=1475540620066358}
       04-08 16:01:24.071 BluetoothAdapter: stopLeScan()
       04-08 16:01:24.085 Timeline: Timeline: Activity_launch_request id:com.example.android.bluetoothlegatt time:98765127
       04-08 16:01:24.105 BluetoothAdapter: stopLeScan()
       04-08 16:01:24.106 BluetoothAdapter: scan not started yet
       04-08 16:01:24.250 BluetoothGattServer: registerCallback()
       04-08 16:01:24.250 BluetoothGattServer: registerCallback() - UUID=11b1f22d-460c-4b9a-82c4-aa176dac8a1c
       04-08 16:01:24.252 BluetoothGattServer: onServerRegistered() - status=0 serverIf=9
       04-08 16:01:24.253 BluetoothGattServer: addService() - service: 00001811-0000-1000-8000-00805f9b34fb
       04-08 16:01:24.267 BluetoothLeService: Trying to create a new connection.
       04-08 16:01:24.269 BluetoothGattServer: onServiceAdded() - service=00001811-0000-1000-8000-00805f9b34fbstatus=0
       04-08 16:01:24.270 BluetoothGatt: connect() - device: CE:CE:67:C2:71:FE, auto: false
       04-08 16:01:24.270 BluetoothGatt: registerApp()
       04-08 16:01:24.270 BluetoothGatt: registerApp() - UUID=9f766219-eb65-4f92-aedd-22ec8d845d54
       04-08 16:01:24.271 BluetoothLeService: onServiceAdded
       04-08 16:01:24.272 BluetoothGatt: onClientRegistered() - status=0 clientIf=10
       04-08 16:01:24.331 Timeline: Timeline: Activity_idle id: android.os.BinderProxy@3650f763 time:98765373
       04-08 16:01:24.349 BluetoothGattServer: onServerConnectionState() - status=0 serverIf=6 device=CE:CE:67:C2:71:FE
       04-08 16:01:24.349 BluetoothLeService: onConnectionStateChage device CE:CE:67:C2:71:FE
       04-08 16:01:24.350 BluetoothGattServer: onServerConnectionState() - status=0 serverIf=8 device=CE:CE:67:C2:71:FE
       04-08 16:01:24.350 BluetoothLeService: onConnectionStateChage device CE:CE:67:C2:71:FE
       04-08 16:01:24.350 BluetoothGattServer: onServerConnectionState() - status=0 serverIf=9 device=CE:CE:67:C2:71:FE
       04-08 16:01:24.350 BluetoothLeService: onConnectionStateChage device CE:CE:67:C2:71:FE
       04-08 16:01:24.353 BluetoothGattServer: onServerConnectionState() - status=0 serverIf=7 device=CE:CE:67:C2:71:FE
       04-08 16:01:24.353 BluetoothLeService: onConnectionStateChage device CE:CE:67:C2:71:FE
       04-08 16:01:24.356 BluetoothGatt: onClientConnectionState() - status=0 clientIf=10 device=CE:CE:67:C2:71:FE
       04-08 16:01:24.356 foo: onConnectionStateChange
       04-08 16:01:24.356 foo: status connected
       04-08 16:01:24.356 BluetoothGatt: discoverServices() - device: CE:CE:67:C2:71:FE
       04-08 16:01:24.364 BluetoothGatt: onSearchComplete() = Device=CE:CE:67:C2:71:FE Status=0
       04-08 16:01:24.364 foo: onServicesDiscovered
       04-08 16:01:24.736 BluetoothLeService: onCharacteristicReadRequest UUID: 00002a47-0000-1000-8000-00805f9b34fb from device: CE:CE:67:C2:71:FE
       04-08 16:01:24.833 BluetoothLeService: onCharacteristicReadRequest UUID: 00002a48-0000-1000-8000-00805f9b34fb from device: CE:CE:67:C2:71:FE
       04-08 16:01:24.930 BluetoothLeService: ondescriptorwriterequest UUID: 00002902-0000-1000-8000-00805f9b34fbValue: 1
       04-08 16:01:24.931 /BluetoothLeService: sending nofication!
守则:

public class BluetoothLeService extends Service {
private final static String TAG = BluetoothLeService.class.getSimpleName();

private BluetoothManager mBluetoothManager;
private BluetoothAdapter mBluetoothAdapter;
private String mBluetoothDeviceAddress;
private BluetoothGatt mBluetoothGatt;
private int mConnectionState = STATE_DISCONNECTED;
private BluetoothGattCharacteristic mSupportedNewAlertCategory;
private BluetoothGattCharacteristic mNewAlert;
private BluetoothGattCharacteristic mSupportedUnreadCategory;
private BluetoothGattCharacteristic mUnreadAlertStatus;
private BluetoothGattCharacteristic mAlertNotificationControlPoint;
private BluetoothDevice mBluetoothDevice;
private BluetoothGattServer mGattServer;
private BluetoothGattService mAlertNotificationService;
private static final int STATE_DISCONNECTED = 0;
private static final int STATE_CONNECTING = 1;
private static final int STATE_CONNECTED = 2;

public final static String ACTION_GATT_CONNECTED =
        "com.example.bluetooth.le.ACTION_GATT_CONNECTED";
public final static String ACTION_GATT_DISCONNECTED =
        "com.example.bluetooth.le.ACTION_GATT_DISCONNECTED";
public final static String ACTION_GATT_SERVICES_DISCOVERED =
        "com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";
public final static String ACTION_DATA_AVAILABLE =
        "com.example.bluetooth.le.ACTION_DATA_AVAILABLE";
public final static String EXTRA_DATA =
        "com.example.bluetooth.le.EXTRA_DATA";


// Implements callback methods for GATT events that the app cares about.  For example,
// connection change and services discovered.
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
        Log.d("foo", "onConnectionStateChange");
        if (newState == BluetoothProfile.STATE_CONNECTED) {
            Log.d("foo", "status connected");
            gatt.discoverServices();
        }
        if (false) {
            String intentAction;
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                intentAction = ACTION_GATT_CONNECTED;
                mConnectionState = STATE_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:" +
                        mBluetoothGatt.discoverServices());

            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                intentAction = ACTION_GATT_DISCONNECTED;
                mConnectionState = STATE_DISCONNECTED;
                Log.i(TAG, "Disconnected from GATT server.");
                broadcastUpdate(intentAction);
            }
        }
    }

    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
        Log.d("foo", "onServicesDiscovered");
        if (status == BluetoothGatt.GATT_SUCCESS) {
        } else {
            Log.w(TAG, "onServicesDiscovered received: " + status);
        }
    }

    @Override
    public void onCharacteristicRead(BluetoothGatt gatt,
                                     BluetoothGattCharacteristic characteristic,
                                     int status) {
        Log.d(TAG, "setCharacterostisRead (GATT)");
        if (status == BluetoothGatt.GATT_SUCCESS) {
            broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
        }
    }

    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt,
                                        BluetoothGattCharacteristic characteristic) {
        broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
    }
};

private void broadcastUpdate(final String action) {
    final Intent intent = new Intent(action);
    sendBroadcast(intent);
}

private void broadcastUpdate(final String action,
                             final BluetoothGattCharacteristic characteristic) {
    final Intent intent = new Intent(action);

    // This is special handling for the Heart Rate Measurement profile.  Data parsing is
    // carried out as per profile specifications:
    // http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml

    // For all other profiles, writes the data formatted in HEX.
    final byte[] data = characteristic.getValue();
    if (data != null && data.length > 0) {
        final StringBuilder stringBuilder = new StringBuilder(data.length);
        for(byte byteChar : data)
            stringBuilder.append(String.format("%02X ", byteChar));
        intent.putExtra(EXTRA_DATA, new String(data) + "\n" + stringBuilder.toString());
    }
    sendBroadcast(intent);
}

public class LocalBinder extends Binder {
    BluetoothLeService getService() {
        return BluetoothLeService.this;
    }
}

@Override
public IBinder onBind(Intent intent) {
    return mBinder;
}

@Override
public boolean onUnbind(Intent intent) {
    // After using a given device, you should make sure that BluetoothGatt.close() is called
    // such that resources are cleaned up properly.  In this particular example, close() is
    // invoked when the UI is disconnected from the Service.
    close();
    return super.onUnbind(intent);
}

private final IBinder mBinder = new LocalBinder();

/**
 * Initializes a reference to the local Bluetooth adapter.
 *
 * @return Return true if the initialization is successful.
 */
public boolean initialize() {
    // For API level 18 and above, get a reference to BluetoothAdapter through
    // BluetoothManager.
    if (mBluetoothManager == null) {
        mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        if (mBluetoothManager == null) {
            Log.e(TAG, "Unable to initialize BluetoothManager.");
            return false;
        }
    }

    mBluetoothAdapter = mBluetoothManager.getAdapter();
    if (mBluetoothAdapter == null) {
        Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
        return false;
    }

    return true;
}

public BluetoothGattServerCallback serverCallback = new BluetoothGattServerCallback() {
    @Override
    public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
        byte value[] = {0x03, 0x04, 0x52, 0x69, 0x63, 0x68, 0x61, 0x72, 0x64};
        super.onConnectionStateChange(device, status, newState);

        Log.d(TAG, "onConnectionStateChage device " + device.getAddress());
        mNewAlert.setValue(value);
        mGattServer.notifyCharacteristicChanged(mBluetoothDevice, mNewAlert, true);
    }

    @Override
    public void onServiceAdded(int status, BluetoothGattService service) {
        super.onServiceAdded(status, service);
        mBluetoothGatt = mBluetoothDevice.connectGatt(getApplicationContext(), false, mGattCallback);

        Log.d(TAG, "onServiceAdded");
    }

    @Override
    public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) {
        super.onCharacteristicReadRequest(device, requestId, offset, characteristic);
        Log.d(TAG, "onCharacteristicReadRequest UUID: " + characteristic.getUuid().toString() +" from device: " + device.getAddress());

        if (characteristic.getUuid().equals(SampleGattAttributes.UUID_SUPPORTED_NEW_ALERT_CATEGORY)) {
            byte value[] = {0x1f};
            mSupportedNewAlertCategory.setValue(value);
            mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, 0, value);
        } else if (characteristic.getUuid().equals(SampleGattAttributes.UUID_SUPPORTED_UNREAD_ALERT_CATEGORY)) {
            byte value[] = {0x1f};
            mSupportedUnreadCategory.setValue(value);
            mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, 0, value);
        } else {
            byte value[] = {0x03, 0x04, 0x52, 0x69, 0x63, 0x68, 0x61, 0x72, 0x64};
            mNewAlert.setValue(value);
            mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, 0, value);
        }

    }

    @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 UUID: " + characteristic.getUuid().toString());
        mGattServer.notifyCharacteristicChanged(mBluetoothDevice, characteristic, true);
    }

    @Override
    public void onDescriptorReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattDescriptor descriptor) {
        super.onDescriptorReadRequest(device, requestId, offset, descriptor);
        Log.d(TAG, "ondescriptorReadrequest UUID: " + descriptor.getUuid().toString());


    }

    @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);
        Log.d(TAG, "ondescriptorwriterequest UUID: " + descriptor.getUuid().toString() + "Value: " + value[0]);
        if (value[0] == 1) {
            Log.d(TAG, "sending nofication!");
            mGattServer.notifyCharacteristicChanged(mBluetoothDevice, mNewAlert, true);
        }
    }

    @Override
    public void onNotificationSent(BluetoothDevice device, int status) {
        super.onNotificationSent(device, status);
        Log.d(TAG, "onNotificationSent");
    }
};
/**
 * 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) {
    if (mBluetoothAdapter == null || address == null) {
        Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
        return false;
    }

    // Previously connected device.  Try to reconnect.
    if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress)
            && mBluetoothGatt != null) {
        Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
        if (mBluetoothGatt.connect()) {
            mConnectionState = STATE_CONNECTING;
            return true;
        } else {
            return false;
        }
    }

    mBluetoothDevice = mBluetoothAdapter.getRemoteDevice(address);
    if (mBluetoothDevice == null) {
        Log.w(TAG, "Device not found.  Unable to connect.");
        return false;
    }

    mGattServer = mBluetoothManager.openGattServer(this, serverCallback);
    mSupportedNewAlertCategory = new BluetoothGattCharacteristic(SampleGattAttributes.UUID_SUPPORTED_NEW_ALERT_CATEGORY, BluetoothGattCharacteristic.PROPERTY_READ | BluetoothGattCharacteristic.PROPERTY_WRITE, BluetoothGattCharacteristic.PERMISSION_READ);
    mNewAlert = new BluetoothGattCharacteristic(SampleGattAttributes.UUID_NEW_ALERT, BluetoothGattCharacteristic.FORMAT_UINT8 | BluetoothGattCharacteristic.PROPERTY_NOTIFY | BluetoothGattCharacteristic.PROPERTY_READ, BluetoothGattCharacteristic.PERMISSION_READ);
    mSupportedUnreadCategory = new BluetoothGattCharacteristic(SampleGattAttributes.UUID_SUPPORTED_UNREAD_ALERT_CATEGORY, BluetoothGattCharacteristic.PROPERTY_READ| BluetoothGattCharacteristic.PROPERTY_WRITE, BluetoothGattCharacteristic.PERMISSION_READ);
    mUnreadAlertStatus = new BluetoothGattCharacteristic(SampleGattAttributes.UUID_UNREAD_ALERT_STATUS, BluetoothGattCharacteristic.PROPERTY_NOTIFY, BluetoothGattCharacteristic.PERMISSION_READ);
    mAlertNotificationControlPoint = new BluetoothGattCharacteristic(SampleGattAttributes.UUID_ALERT_NOTIFICATION_CONTROL_POINT, BluetoothGattCharacteristic.PROPERTY_READ, BluetoothGattCharacteristic.PERMISSION_READ);
    mAlertNotificationControlPoint.setValue(new byte[]{0});
    mAlertNotificationControlPoint.setValue(new byte[]{1});
    mAlertNotificationControlPoint.setValue(new byte[]{4});
    mAlertNotificationControlPoint.setValue(new byte[]{5});

    BluetoothGattDescriptor clientCharacteristicConfig = new BluetoothGattDescriptor(SampleGattAttributes.UUID_CLIENT_CHARACTERISTIC_CONFIG, BluetoothGattDescriptor.PERMISSION_READ | BluetoothGattDescriptor.PERMISSION_WRITE);
    clientCharacteristicConfig.setValue(new byte[]{1});
    mNewAlert.addDescriptor(clientCharacteristicConfig);
    mUnreadAlertStatus.addDescriptor(clientCharacteristicConfig);

    mAlertNotificationService = new BluetoothGattService(SampleGattAttributes.UUID_ALERT_NOTIFICATION_SERVICE, BluetoothGattService.SERVICE_TYPE_PRIMARY);

    mAlertNotificationService.addCharacteristic(mSupportedNewAlertCategory);
    mAlertNotificationService.addCharacteristic(mNewAlert);
    mAlertNotificationService.addCharacteristic(mSupportedUnreadCategory);
    mAlertNotificationService.addCharacteristic(mUnreadAlertStatus);
    mAlertNotificationService.addCharacteristic(mAlertNotificationControlPoint);

    mGattServer.addService(mAlertNotificationService);
    // We want to directly connect to the device, so we are setting the autoConnect
    // parameter to false.
    //        mGattServer.connect(mBluetoothDevice, true);

    Log.d(TAG, "Trying to create a new connection.");
    mBluetoothDeviceAddress = address;
    mConnectionState = STATE_CONNECTING;
    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() {
    if (mBluetoothAdapter == null || mBluetoothGatt == null) {
        Log.w(TAG, "BluetoothAdapter not initialized");
        return;
    }
    mBluetoothGatt.disconnect();
}

/**
 * After using a given BLE device, the app must call this method to ensure resources are
 * released properly.
 */
public void close() {
    if (mBluetoothGatt == null) {
        return;
    }
    mBluetoothGatt.close();
    mBluetoothGatt = null;
}

/**
 * Request a read on a given {@code BluetoothGattCharacteristic}. The read result is reported
 * asynchronously through the {@code BluetoothGattCallback#onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int)}
 * callback.
 *
 * @param characteristic The characteristic to read from.
 */
public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
    if (mBluetoothAdapter == null || mBluetoothGatt == null) {
        Log.w(TAG, "BluetoothAdapter not initialized");
        return;
    }
    Log.d(TAG, "readCharacteristics (GATT)");
    mBluetoothGatt.readCharacteristic(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) {
    if (mBluetoothAdapter == null || mBluetoothGatt == null) {
        Log.w(TAG, "BluetoothAdapter not initialized");
        return;
    }
    Log.d(TAG, "setCharacteristicNotification (GATT)");
    mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
}

/**
 * Retrieves a list of supported GATT services on the connected device. This should be
 * invoked only after {@code BluetoothGatt#discoverServices()} completes successfully.
 *
 * @return A {@code List} of supported services.
 */
public List<BluetoothGattService> getSupportedGattServices() {
    if (mBluetoothGatt == null) return null;

    Log.d(TAG, "getSupportedServices (GATT)");
    return mBluetoothGatt.getServices();
}
公共类BluetoothLeService扩展服务{
private final static String TAG=BluetoothLeService.class.getSimpleName();
私人蓝牙经理MBluetothorser;
私人蓝牙适配器mBluetoothAdapter;
私有字符串mBluetoothDeviceAddress;
私人蓝牙总协定;
private int mConnectionState=状态_已断开连接;
私人蓝牙特征MSSupportedNewalertCategory;
私人蓝牙特征性mNewAlert;
私人蓝牙GATT特征MSSupportedUnreadCategory;
私人蓝牙gatt特征状态;
私人蓝牙GATT特征性mAlertNotificationControlPoint;
私人蓝牙设备;
私有BluetoothGattServer mGattServer;
私人BluetoothGattService mAlertNotificationService;
私有静态最终int状态_DISCONNECTED=0;
私有静态最终int状态_CONNECTING=1;
专用静态最终int状态_CONNECTED=2;
公共最终静态字符串动作\u GATT\u已连接=
“com.example.bluetooth.le.ACTION\u GATT\u CONNECTED”;
公共最终静态字符串操作\u GATT\u断开连接=
“com.example.bluetooth.le.ACTION\u GATT\u DISCONNECTED”;
公共最终静态字符串操作\u GATT\u服务\u发现=
“com.example.bluetooth.le.ACTION\u GATT\u SERVICES\u DISCOVERED”;
公共最终静态字符串操作\u数据\u可用=
“com.example.bluetooth.le.ACTION\u数据可用”;
公共最终静态字符串额外_数据=
“com.example.bluetooth.le.EXTRA_DATA”;
//为应用程序关心的GATT事件实现回调方法。例如,
//发现连接更改和服务。
私有最终BluetoothGattCallback mGattCallback=新BluetoothGattCallback(){
@凌驾
连接状态更改的公共无效(蓝牙gatt gatt、int状态、int新闻状态){
Log.d(“foo”、“onConnectionStateChange”);
if(newState==BluetoothProfile.STATE\u CONNECTED){
日志d(“foo”,“连接状态”);
关贸总协定。发现服务();
}
if(false){
串接;
if(newState==BluetoothProfile.STATE\u CONNECTED){
意向=行动与关贸总协定连接;
mConnectionState=连接状态;
广播更新(意向);
Log.i(标记“连接到GATT服务器”);
//尝试在成功连接后发现服务。
Log.i(标记“正在尝试启动服务发现:”+
mBluetoothGatt.discoverServices());
}else if(newState==BluetoothProfile.STATE\u已断开连接){
intentAction=动作与关贸总协定断开;
mConnectionState=状态\断开连接;
Log.i(标签,“与GATT服务器断开连接”);
广播更新(意向);
}
}
}
@凌驾
发现服务上的公共无效(Bluetooth gatt,int状态){
Log.d(“foo”、“onServicesDiscovered”);
如果(状态==蓝牙GATT.GATT\U成功){
}否则{
Log.w(标记“OnServicesDiscovery已接收:+状态);
}
}
@凌驾
公共性质无效阅读(蓝牙gatt,
蓝牙特征,
int状态){
Log.d(标签“setCharacterostisRead(GATT)”);
如果(状态==蓝牙GATT.GATT\U成功){
广播更新(动作数据可用,特征);
}
}
@凌驾
特征变更后的公共无效(蓝牙gatt,
蓝牙(特征){
广播更新(动作数据可用,特征);
}
};
私有无效广播更新(最终字符串操作){
最终意图=新意图(行动);
发送广播(意图);
}
私有无效广播更新(最终字符串操作,
最终蓝牙(特征){
最终意图=新意图(行动);
//这是对心率测量配置文件的特殊处理
//根据剖面规范进行:
// http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml
//对于所有其他配置文件,写入十六进制格式的数据。
最后一个字节[]数据=characteristic.getValue();
if(data!=null&&data.length>0){
最终StringBuilder StringBuilder=新StringBuilder(data.length);
for(字节byteChar:data)
追加(String.format(“%02X”,byteChar));
intent.putExtra(额外的_数据,新字符串(数据)+“\n”+stringBuilder.toString());
}
发送广播(意图);
}
公共类LocalBinder扩展了Binder{
BluetoothLeService getService(){
返回BluetoothLeService.this;
}
}
@越过
@Override
public void onServiceAdded(int status, BluetoothGattService service) {

    super.onServiceAdded(status, service);
    serverCharacteristic =
            service.getCharacteristic(UUID.fromString(SampleGattAttributes.FAN_OPERATING_STATE));


}
        @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);
            byte[] mValue={0};
            serverCharacteristic.setValue(mValue);
            boolean confirm = mBluetoothGattServer.notifyCharacteristicChanged(device, serverCharacteristic , true);
            Log.i("TEST","confirm:"+confirm);
        }
public void sendData(byte[] data){


        String uuidHRService = "xxxxx";
        String uuidHRCharacteristic = "xxxxxxxx";
        BluetoothGattService mBluetoothLeService = null;
        BluetoothGattCharacteristic mBluetoothGattCharacteristic = null;

        for (BluetoothGattService service : mBluetoothGatt.getServices()) {
            if ((service == null) || (service.getUuid() == null)) {

                Log.i("Test","Something is null");
                continue;
            }
            if (uuidHRService.equalsIgnoreCase(service.getUuid().toString())) {

                Log.i("Test","service.getUuid().toString()="+service.getUuid().toString());
                mBluetoothLeService = service;
            }
        }

        //BluetoothGattService mBluetoothLeService = mBluetoothGatt.getService(UUID.fromString(uuidHRService));
        if(mBluetoothLeService!=null) {
           mBluetoothGattCharacteristic =
                    mBluetoothLeService.getCharacteristic(UUID.fromString(uuidHRCharacteristic));
        }
        else{
            Log.i("Test","mBluetoothLeService is null");
        }

        if(mBluetoothGattCharacteristic!=null) {
            mBluetoothGattCharacteristic.setValue(data);

            boolean write = mBluetoothGatt.writeCharacteristic(mBluetoothGattCharacteristic);

            Log.i("Test","writeCharacteristic:"+write);
        }
        else{
            Log.i("Test", "mBluetoothGattCharacteristic is null");
        }



    }
private BluetoothGatt mBluetoothGatt;
Blu
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
...etoothGattCharacteristic characteristic;
boolean enabled;
...
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
        UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);