Java Android可从产品接收心率数据

Java Android可从产品接收心率数据,java,android,bluetooth,bluetooth-lowenergy,Java,Android,Bluetooth,Bluetooth Lowenergy,我正在使用BLE开发一个心率检测代码。我能够连接到关贸总协定服务器,甚至广播更新。但我似乎检测不到任何心率。我错过什么了吗 这是我的密码 public class BleActivity extends Activity { public final static String ACTION_GATT_CONNECTED = "com.example.bluetooth.le.ACTION_GATT_CONNECTED"; public final static String

我正在使用BLE开发一个心率检测代码。我能够连接到关贸总协定服务器,甚至广播更新。但我似乎检测不到任何心率。我错过什么了吗

这是我的密码

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;
}
公共类b活动扩展活动{
公共最终静态字符串动作\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”;
专用蓝牙设备适配器蓝牙设备适配器;
私人蓝牙适配器mBluetoothAdapter;
私有处理程序mHandler=新处理程序();
专用静态最终长扫描周期=5000;
私有进程对话;
私人蓝牙GATT mGatt;
@绑定(R.id.bleDeviceListView)
列表视图列表视图;
@TargetApi(Build.VERSION\u code.JELLY\u BEAN\u MR2)
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_表);
把(这个)绑起来;
bluetoothDevicesAdapter=新的bluetoothDevicesAdapter(getApplicationContext());
setAdapter(蓝牙设备适配器);
最终BluetoothManager BluetoothManager=
(BluetoothManager)getSystemService(Context.BLUETOOTH\u服务);
mBluetoothAdapter=bluetoothManager.getAdapter();
}
@OnClick(R.id.scanButton)
公共无效onScanClicked(){
扫描设备();
}
@OnItemClick(R.id.bleDeviceListView)
已单击公共位置(内部位置){
connectToDevice((蓝牙设备)蓝牙设备适配器.getItem(位置));
}
@凌驾
受保护的void onPause(){
super.onPause();
未注册接收者(MGATTDUpdateReceiver);
}
@凌驾
受保护的void onResume(){
super.onResume();
registerReceiver(mGattUpdateReceiver,makeGatupdateIntentFilter());
//确认蓝牙是否已启用
如果(!mBluetoothAdapter.isEnabled()){
如果(!mBluetoothAdapter.isEnabled()){
GenericDialogBox.EnableBluetoothBox(BleActivity.this,“注意”,“此应用程序需要bluetooth.Enable?”,mBluetoothAdapter);
}
}
}
私有无效扫描设备(){
bluetoothDevicesAdapter.clear();
bluetoothDevicesAdapter.notifyDataSetChanged();
progressDialog=新建progressDialog(BleActivity.this);
progressDialog.setCancelable(假);
progressDialog.setMessage(“扫描设备”);
progressDialog.show();
mHandler.postDelayed(新的Runnable(){
@凌驾
公开募捐{
mBluetoothAdapter.stopLeScan(leScanCallback);
progressDialog.hide();
mBluetoothAdapter.stopLeScan(leScanCallback);
progressDialog.disclose();
progressDialog=null;
}
},扫描周期);
mBluetoothAdapter.startescan(leScanCallback);
}
private BluetoothAdapter.LeScanCallback LeScanCallback=新的BluetoothAdapter.LeScanCallback(){
@凌驾
public void onLeScan(最终BluetoothDevice设备、最终int rssi、最终字节[]扫描记录){
runOnUiThread(新的Runnable(){
@凌驾
公开募捐{
蓝牙设备适配器。添加设备(设备);
bluetoothDevicesAdapter.notifyDataSetChanged();
}
});
}
};
public void connectToDevice(蓝牙设备){
如果(mGatt==null){
mGatt=device.connectGatt(this,false,btlegatcallback);
progressDialog=新建progressDialog(BleActivity.this);
setMessage(“连接到Gatt服务器”);
progressDialog.setCancelable(假);
progressDialog.show();
}
}
私有最终BluetoothGattCallback btleGattCallback=新BluetoothGattCallback(){
@凌驾
特征变更后的公共无效(蓝牙gatt,最终蓝牙gatt特征特征){
广播更新(动作数据可用,特征);
}
@凌驾
连接状态更改的公共无效(最终蓝牙gatt gatt、最终int状态、最终int新闻状态){
串接;
Log.e(“onConnectionStateChange”,“Status:+Status”);
交换机(新闻状态){
案例BluetoothProfile.STATE\u已连接:
意向=行动与关贸总协定连接;
Log.e(“gattCallback”、“STATE_CONNECTED”);
progressDialog.disclose();
progressDialog=null;
广播更新(意向);
mGatt.discoverServices();
打破
案例BluetoothProfile.STATE\u已断开连接:
intentAction=动作与关贸总协定断开;
Log.e(“gattCallback”、“STATE_DISCONNECTED”);
BluetoothDevice mDevice=gatt.getDevice();
mGatt=null;
广播更新(意向);
打破
违约:
Log.e(“gattCallback”、“STATE_OTHER”);
}
}
@凌驾
发现服务上的公共无效(最终蓝牙gatt、最终int状态){
如果(状态==蓝牙GATT.GATT\U成功){
List services=gatt.getServices();
蓝牙特征热字符;
对于(int i=0;ipublic 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;
}