Android BLE for Heart Rate从Product接收数据

时间:2016-06-01 07:06:16

标签: java android bluetooth bluetooth-lowenergy

我正在使用BLE开发心率检测代码。我能够连接到gatt服务器,甚至广播更新。但我似乎无法发现任何心率。我错过了什么吗?

这是我的代码。

public class BleActivity extends Activity {

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";

private BluetoothDevicesAdapter bluetoothDevicesAdapter;
private BluetoothAdapter mBluetoothAdapter;
private Handler mHandler = new Handler();

private static final long SCAN_PERIOD = 5000;
private ProgressDialog progressDialog;

private BluetoothGatt mGatt;

@Bind(R.id.bleDeviceListView)
ListView listView;

@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_ble);

    ButterKnife.bind(this);

    bluetoothDevicesAdapter = new BluetoothDevicesAdapter(getApplicationContext());
    listView.setAdapter(bluetoothDevicesAdapter);

    final BluetoothManager bluetoothManager =
            (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
    mBluetoothAdapter = bluetoothManager.getAdapter();

}

@OnClick(R.id.scanButton)
public void onScanClicked() {

    scanLeDevice();

}

@OnItemClick(R.id.bleDeviceListView)
public void onItemClicked(int position) {

    connectToDevice((BluetoothDevice) bluetoothDevicesAdapter.getItem(position));

}

@Override
protected void onPause() {
    super.onPause();

    unregisterReceiver(mGattUpdateReceiver);

}

@Override
protected void onResume() {
    super.onResume();

    registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());

    //CONFIRMS IF BLUETOOTH IS ENABLED
    if (!mBluetoothAdapter.isEnabled()) {
        if (!mBluetoothAdapter.isEnabled()) {

            GenericDialogBox.EnableBluetoothBox(BleActivity.this, "Notice", "This app requires bluetooth. Enable?", mBluetoothAdapter);

        }
    }

}

private void scanLeDevice() {

    bluetoothDevicesAdapter.clear();
    bluetoothDevicesAdapter.notifyDataSetChanged();
    progressDialog = new ProgressDialog(BleActivity.this);
    progressDialog.setCancelable(false);
    progressDialog.setMessage("Scanning Devices");
    progressDialog.show();

    mHandler.postDelayed(new Runnable() {
        @Override
        public void run() {

            mBluetoothAdapter.stopLeScan(leScanCallback);
            progressDialog.hide();
            mBluetoothAdapter.stopLeScan(leScanCallback);
            progressDialog.dismiss();
            progressDialog = null;

        }
    }, SCAN_PERIOD);

    mBluetoothAdapter.startLeScan(leScanCallback);

}

private BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() {
    @Override
    public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) {

        runOnUiThread(new Runnable() {
            @Override
            public void run() {

                bluetoothDevicesAdapter.addDevice(device);
                bluetoothDevicesAdapter.notifyDataSetChanged();

            }
        });

    }
};

public void connectToDevice(BluetoothDevice device) {
    if (mGatt == null) {

        mGatt = device.connectGatt(this, false, btleGattCallback);

        progressDialog = new ProgressDialog(BleActivity.this);
        progressDialog.setMessage("Connecting to Gatt Server.");
        progressDialog.setCancelable(false);
        progressDialog.show();

    }
}

private final BluetoothGattCallback btleGattCallback = new BluetoothGattCallback() {

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

    @Override
    public void onConnectionStateChange(final BluetoothGatt gatt, final int status, final int newState) {
        String intentAction;
        Log.e("onConnectionStateChange", "Status: " + status);
        switch (newState) {
            case BluetoothProfile.STATE_CONNECTED:
                intentAction = ACTION_GATT_CONNECTED;
                Log.e("gattCallback", "STATE_CONNECTED");
                progressDialog.dismiss();
                progressDialog = null;

                broadcastUpdate(intentAction);
                mGatt.discoverServices();

                break;
            case BluetoothProfile.STATE_DISCONNECTED:
                intentAction = ACTION_GATT_DISCONNECTED;
                Log.e("gattCallback", "STATE_DISCONNECTED");
                BluetoothDevice mDevice = gatt.getDevice();
                mGatt = null;
                broadcastUpdate(intentAction);

                break;
            default:

                Log.e("gattCallback", "STATE_OTHER");
        }
    }

    @Override
    public void onServicesDiscovered(final BluetoothGatt gatt, final int status) {

        if (status == BluetoothGatt.GATT_SUCCESS) {

            List<BluetoothGattService> services = gatt.getServices();
            BluetoothGattCharacteristic therm_char;

            for (int i = 0; i < services.size(); i++) {
                therm_char = services.get(i).getCharacteristics().get(0);
                if(therm_char.getUuid().equals(SampleGattAttributes.HEART_RATE_MEASUREMENT)){
                    gatt.setCharacteristicNotification(therm_char, true);

                    BluetoothGattDescriptor descriptor = therm_char.getDescriptor(
                            UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
                    descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                    mGatt.writeDescriptor(descriptor);
                }
            }

            broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);

            Log.e("gattCallback", "Service discovered" + gatt.getServices() + " Status: " + status);

        } else {
            Log.e("BluetoothServices: ", "onServicesDiscovered received: " + status);
        }

    }

    @Override
    public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
        if (status == BluetoothGatt.GATT_SUCCESS) {
            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.
    if (UUID.fromString(SampleGattAttributes.HEART_RATE_MEASUREMENT).equals(characteristic.getUuid())) {
        int flag = characteristic.getProperties();
        int format = -1;
        if ((flag & 0x01) != 0) {
            format = BluetoothGattCharacteristic.FORMAT_UINT16;
            Log.d("Bluetooth Service: ", "Heart rate format UINT16.");
        } else {
            format = BluetoothGattCharacteristic.FORMAT_UINT8;
            Log.d("Bluetooth Service: ", "Heart rate format UINT8.");
        }
        final int heartRate = characteristic.getIntValue(format, 1);
        Log.d("Bluetooth Service: ", String.format("Received heart rate: %d", heartRate));
        intent.putExtra(EXTRA_DATA, String.valueOf(heartRate));

    } else {
        // 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);
}

private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        final String action = intent.getAction();
        if (ACTION_GATT_CONNECTED.equals(action)) {

            Toast.makeText(getApplicationContext(), "Connected to Service.", Toast.LENGTH_SHORT).show();

            invalidateOptionsMenu();
        } else if (ACTION_GATT_DISCONNECTED.equals(action)) {

            Toast.makeText(getApplicationContext(), "Connected to Service.", Toast.LENGTH_SHORT).show();

        } else if (ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {

            //Update Connection State

        } else if (ACTION_DATA_AVAILABLE.equals(action)) {

            Toast.makeText(getApplicationContext(), intent.getStringExtra(EXTRA_DATA), Toast.LENGTH_SHORT).show();

        }
    }
};

private static IntentFilter makeGattUpdateIntentFilter() {
    final IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction(ACTION_GATT_CONNECTED);
    intentFilter.addAction(ACTION_GATT_DISCONNECTED);
    intentFilter.addAction(ACTION_GATT_SERVICES_DISCOVERED);
    intentFilter.addAction(ACTION_DATA_AVAILABLE);
    return intentFilter;
}

这是sampleAttributes类。

public class SampleGattAttributes {
private static HashMap<String, String> attributes = new HashMap();
public static String HEART_RATE_MEASUREMENT = "00002a37-0000-1000-8000-00805f9b34fb";
public static String CLIENT_CHARACTERISTIC_CONFIG = "00002902-0000-1000-8000-00805f9b34fb";

static {
    // Sample Services.
    attributes.put("0000180d-0000-1000-8000-00805f9b34fb", "Heart Rate Service");
    attributes.put("0000180a-0000-1000-8000-00805f9b34fb", "Device Information Service");
    // Sample Characteristics.
    attributes.put(HEART_RATE_MEASUREMENT, "Heart Rate Measurement");
    attributes.put("00002a29-0000-1000-8000-00805f9b34fb", "Manufacturer Name String");
}

public static String lookup(String uuid, String defaultName) {
    String name = attributes.get(uuid);
    return name == null ? defaultName : name;
}

}

如果设备不时搜索任何更改,还有一种方法可以记录吗?

谢谢!

0 个答案:

没有答案