Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android : Streaming Heart Rate from Microsoft Band

I'm currently developing an Android App that receives heart rate data from Microsoft Band. Here my Activity modified from project sample Accelerometer :

    package com.microsoft.band.sdk.sampleapp;

import com.microsoft.band.BandClient;
import com.microsoft.band.BandClientManager;
import com.microsoft.band.BandException;
import com.microsoft.band.BandInfo;
import com.microsoft.band.BandIOException;
import com.microsoft.band.ConnectionState;
import com.microsoft.band.UserConsent;
import com.microsoft.band.sdk.sampleapp.streaming.R;
import com.microsoft.band.sensors.SampleRate;

import com.microsoft.band.sensors.BandHeartRateEvent;
import com.microsoft.band.sensors.BandHeartRateEventListener;
import com.microsoft.band.sensors.HeartRateConsentListener;



import android.os.Bundle;
import android.view.View;
import android.app.Activity;
import android.os.AsyncTask;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class BandStreamingAppActivity extends Activity {

    private BandClient client = null;
    private Button btnStart;
    private TextView txtStatus;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        txtStatus = (TextView) findViewById(R.id.txtStatus);
        btnStart = (Button) findViewById(R.id.btnStart);
        btnStart.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                txtStatus.setText("");
                new appTask().execute();
            }
        });
    }

    @Override
    protected void onResume() {
        super.onResume();
        txtStatus.setText("");
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (client != null) {
            try {
                client.getSensorManager().unregisterAccelerometerEventListeners();
            } catch (BandIOException e) {
                appendToUI(e.getMessage());
            }
        }
    }

    private class appTask extends AsyncTask<Void, Void, Void> {
        @Override
        protected Void doInBackground(Void... params) {
            try {
                if (getConnectedBandClient()) {
                    appendToUI("Band is connected.\n");
                    // client.getSensorManager().registerAccelerometerEventListener(mAccelerometerEventListener, SampleRate.MS128);
                    client.getSensorManager().registerHeartRateEventListener(heartRateListener);

                } else {
                    appendToUI("Band isn't connected. Please make sure bluetooth is on and the band is in range.\n");
                }
            } catch (BandException e) {
                String exceptionMessage="";
                switch (e.getErrorType()) {
                case UNSUPPORTED_SDK_VERSION_ERROR:
                    exceptionMessage = "Microsoft Health BandService doesn't support your SDK Version. Please update to latest SDK.";
                    break;
                case SERVICE_ERROR:
                    exceptionMessage = "Microsoft Health BandService is not available. Please make sure Microsoft Health is installed and that you have the correct permissions.";
                    break;
                default:
                    exceptionMessage = "Unknown error occured: " + e.getMessage();
                    break;
                }
                appendToUI(exceptionMessage);

            } catch (Exception e) {
                appendToUI(e.getMessage());
            }
            return null;
        }
    }

    private void appendToUI(final String string) {
        this.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                txtStatus.setText(string);
            }
        });
    }



    private BandHeartRateEventListener heartRateListener = new BandHeartRateEventListener() {
        @Override
        public void onBandHeartRateChanged(final BandHeartRateEvent event) {
            if (event != null) {
                appendToUI(String.format(" HR = %i", event.getHeartRate()));
            }
        }

    };


    private boolean getConnectedBandClient() throws InterruptedException, BandException {
        if (client == null) {
            BandInfo[] devices = BandClientManager.getInstance().getPairedBands();
            if (devices.length == 0) {
                appendToUI("Band isn't paired with your phone.\n");
                return false;
            }
            client = BandClientManager.getInstance().create(getBaseContext(), devices[0]);
        } else if (ConnectionState.CONNECTED == client.getConnectionState()) {
            return true;
        }

        appendToUI("Band is connecting...\n");
        return ConnectionState.CONNECTED == client.connect().await();
    }
}

But, I'm getting this error when App running :

Unknown Error occured : User has not given consent for use of heart rate data 

Then I check the documentation, it says :

  1. Implement HeartRateConsentListener interface

    @Override
        public void userAccepted(boolean consentGiven) {
        // handle user's heart rate consent decision
        };
    
  2. Ensure user has consented for heart rate sensor streaming

    // check current user heart rate consent
    if(client.getSensorManager().getCurrentHeartRateConsent() !=
    UserConsent.GRANTED) {
    // user has not consented, request it
    // the calling class is both an Activity and implements
    // HeartRateConsentListener
    bandClient.getSensorManager().requestHeartRateConsent(this, this);
    }
    

The problem is that I have no idea how to implement what the doc says on my code.

like image 799
Hendra Permana Avatar asked May 07 '15 01:05

Hendra Permana


1 Answers

You won't get user's HR data until he explicitly gives consent (he only needs to give his consent once).

So, instead of having this line of code: client.getSensorManager().registerHeartRateEventListener(heartRateListener); you have to check if UserConsent.GRANTED == true as said in the 3rd point of the documentation. If it is true, you can register HR sensor event listener as you were doing, but if it is false you have to call requestHeartRateConsent.

if(client.getSensorManager().getCurrentHeartRateConsent() == UserConsent.GRANTED) {
    startHRListener();
    } else {
// user has not consented yet, request it
client.getSensorManager().requestHeartRateConsent(BandStreamingAppActivity.this, mHeartRateConsentListener);
}

A purple dialog will appear on the screen. User can choose YES/NO. His choice will be the value of b and will also be saved at UserConsent.GRANTED. If b == true, now you can register the HR sensor event listener, if it is false do whatever you want in order to notify the user that HR acquisition won't work. All of this is handled at the HeartRateConsentListener interface, as said in the 2nd point of the documentation. The code you need is:

private HeartRateConsentListener mHeartRateConsentListener = new HeartRateConsentListener() {
        @Override
        public void userAccepted(boolean b) {
            // handle user's heart rate consent decision
            if (b == true) {
                // Consent has been given, start HR sensor event listener
                startHRListener();
            } else {
                // Consent hasn't been given
                appendToUI(String.valueOf(b));
            }
        }
    };

public void startHRListener() {
        try {
            // register HR sensor event listener
            client.getSensorManager().registerHeartRateEventListener(mHeartRateEventListener);
        } catch (BandIOException ex) {
            appendToUI(ex.getMessage(), band);
        } catch (BandException e) {
            String exceptionMessage="";
            switch (e.getErrorType()) {
                case UNSUPPORTED_SDK_VERSION_ERROR:
                    exceptionMessage = "Microsoft Health BandService doesn't support your SDK Version. Please update to latest SDK.";
                    break;
                case SERVICE_ERROR:
                    exceptionMessage = "Microsoft Health BandService is not available. Please make sure Microsoft Health is installed and that you have the correct permissions.";
                    break;
                default:
                    exceptionMessage = "Unknown error occurred: " + e.getMessage();
                    break;
            }
            appendToUI(exceptionMessage, band);

        } catch (Exception e) {
            appendToUI(e.getMessage(), band);
        }
    }
like image 84
netxu Avatar answered Sep 27 '22 18:09

netxu