Skip to content
This repository has been archived by the owner on Dec 4, 2023. It is now read-only.

Updating mechanism to latest google mech for authorizing access to bp… #2

Open
wants to merge 1 commit into
base: update-to-latest
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 21 additions & 133 deletions src/android/HealthPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,6 @@ public class HealthPlugin extends CordovaPlugin {
private static final int REQUEST_DYN_PERMS = 2;
private static final int READ_PERMS = 1;
private static final int READ_WRITE_PERMS = 2;
private static final int REQUEST_OATH_HEALTH = 55;

private LinkedList<DataType> healthDatatypesToAuthRead = new LinkedList<DataType>();
private LinkedList<DataType> healthDatatypesToAuthWrite = new LinkedList<DataType>();

// Scope for read/write access to activity-related data types in Google Fit.
// These include activity type, calories consumed and expended, step counts, and others.
Expand Down Expand Up @@ -285,25 +281,6 @@ public void onActivityResult(int requestCode, int resultCode, Intent intent) {
// The user cancelled the login dialog before selecting any action.
authReqCallbackCtx.error("User cancelled the dialog");
} else authReqCallbackCtx.error("Authorisation failed, result code " + resultCode);
} else if (requestCode == REQUEST_OATH_HEALTH) {
if (resultCode == Activity.RESULT_OK) {
if (!healthDatatypesToAuthRead.isEmpty()) {
// do the read health data first
queryHealthDataForAuth();
} else {
// if we are finished with the read health data types, do the write ones
if (!healthDatatypesToAuthWrite.isEmpty()) {
// do the write health data
storeHealthDataForAuth();
} else {
// done
authReqSuccess();
}
}
} else if (resultCode == Activity.RESULT_CANCELED) {
// The user cancelled the login dialog before selecting any action.
authReqCallbackCtx.error("User cancelled the dialog");
} else authReqCallbackCtx.error("Authorisation failed, result code " + resultCode);
}
}

Expand Down Expand Up @@ -503,6 +480,8 @@ private void checkAuthorization(final JSONArray args, final CallbackContext call
int activityscope = 0;
int locationscope = 0;
int nutritionscope = 0;
int bloodgucosescope = 0;
int bloodpressurescope = 0;

HashSet<String> readWriteTypes = new HashSet<String>();
HashSet<String> readTypes = new HashSet<String>();
Expand Down Expand Up @@ -539,8 +518,10 @@ private void checkAuthorization(final JSONArray args, final CallbackContext call
locationscope = READ_PERMS;
if (nutritiondatatypes.get(readType) != null)
nutritionscope = READ_PERMS;
if (healthdatatypes.get(readType) != null)
healthDatatypesToAuthRead.add(healthdatatypes.get(readType));
if(healthdatatypes.get(readType) == HealthDataTypes.TYPE_BLOOD_GLUCOSE)
bloodgucosescope = READ_PERMS;
if(healthdatatypes.get(readType) == HealthDataTypes.TYPE_BLOOD_PRESSURE)
bloodpressurescope = READ_PERMS;
}

for (String readWriteType : readWriteTypes) {
Expand All @@ -552,9 +533,10 @@ private void checkAuthorization(final JSONArray args, final CallbackContext call
locationscope = READ_WRITE_PERMS;
if (nutritiondatatypes.get(readWriteType) != null)
nutritionscope = READ_WRITE_PERMS;
if (healthdatatypes.get(readWriteType) != null) {
healthDatatypesToAuthWrite.add(healthdatatypes.get(readWriteType));
}
if(healthdatatypes.get(readWriteType) == HealthDataTypes.TYPE_BLOOD_GLUCOSE)
bloodgucosescope = READ_WRITE_PERMS;
if(healthdatatypes.get(readWriteType) == HealthDataTypes.TYPE_BLOOD_PRESSURE)
bloodpressurescope = READ_WRITE_PERMS;
}

dynPerms.clear();
Expand Down Expand Up @@ -588,20 +570,24 @@ private void checkAuthorization(final JSONArray args, final CallbackContext call
} else if (nutritionscope == READ_WRITE_PERMS) {
builder.addScope(new Scope(Scopes.FITNESS_NUTRITION_READ_WRITE));
}
if (bloodgucosescope == READ_PERMS) {
builder.addScope(new Scope(Scopes.FITNESS_BLOOD_GLUCOSE_READ));
} else if (bloodgucosescope == READ_WRITE_PERMS) {
builder.addScope(new Scope(Scopes.FITNESS_BLOOD_GLUCOSE_READ_WRITE));
}
if (bloodpressurescope == READ_PERMS) {
builder.addScope(new Scope(Scopes.FITNESS_BLOOD_PRESSURE_READ));
} else if (bloodpressurescope == READ_WRITE_PERMS) {
builder.addScope(new Scope(Scopes.FITNESS_BLOOD_PRESSURE_READ_WRITE));
}

builder.addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {

@Override
public void onConnected(Bundle bundle) {
mClient.unregisterConnectionCallbacks(this);
Log.i(TAG, "Google Fit connected");
if (!healthDatatypesToAuthRead.isEmpty()) {
// need to query for all health data types
queryHealthDataForAuth();
} else if (!healthDatatypesToAuthWrite.isEmpty()) {
// need to authorise write health data types
storeHealthDataForAuth();
} else authReqSuccess();
authReqSuccess();
}

@Override
Expand Down Expand Up @@ -672,104 +658,6 @@ private boolean lightConnect() {
}
}

// starts a small query for granting access to the health data types
private void queryHealthDataForAuth() {
final DataType dt = healthDatatypesToAuthRead.pop();
final long ts = new Date().getTime();

cordova.getThreadPool().execute(new Runnable() {
@Override
public void run() {
DataReadRequest readRequest = new DataReadRequest.Builder()
.setTimeRange(ts - 60000, ts, TimeUnit.MILLISECONDS)
.read(dt)
.build();
DataReadResult dataReadResult = Fitness.HistoryApi.readData(mClient, readRequest).await();

if (dataReadResult.getStatus().isSuccess()) {
// already authorised, go on
onActivityResult(REQUEST_OATH_HEALTH, Activity.RESULT_OK, null);
} else {
if (authAutoresolve) {
if (dataReadResult.getStatus().hasResolution()) {
try {
dataReadResult.getStatus().startResolutionForResult(cordova.getActivity(), REQUEST_OATH_HEALTH);
} catch (IntentSender.SendIntentException e) {
authReqCallbackCtx.error("Cannot authorise health data type " + dt.getName() + ", cannot send intent: " + e.getMessage());
return;
}
} else {
authReqCallbackCtx.error("Cannot authorise health data type " + dt.getName() + ", " + dataReadResult.getStatus().getStatusMessage());
return;
}
} else {
// probably not authorized, send false
Log.d(TAG, "Connection to Fit failed, probably because of authorization, giving up now");
authReqCallbackCtx.sendPluginResult(new PluginResult(PluginResult.Status.OK, false));
return;
}
}
}
});
}

// store a bogus sample for granting access to the health data types
private void storeHealthDataForAuth() {
final DataType dt = healthDatatypesToAuthWrite.pop();
Calendar c = Calendar.getInstance();
c.add(Calendar.YEAR, -10); // ten years ago
final long ts = c.getTimeInMillis();

cordova.getThreadPool().execute(new Runnable() {
@Override
public void run() {
DataSource datasrc = new DataSource.Builder()
.setDataType(dt)
.setAppPackageName(cordova.getActivity())
.setType(DataSource.TYPE_RAW)
.build();

DataSet dataSet = DataSet.create(datasrc);
DataPoint datapoint = DataPoint.create(datasrc);
datapoint.setTimeInterval(ts, ts, TimeUnit.MILLISECONDS);
if (dt == HealthDataTypes.TYPE_BLOOD_GLUCOSE) {
datapoint.getValue(HealthFields.FIELD_BLOOD_GLUCOSE_LEVEL).setFloat(1);
} else if (dt == HealthDataTypes.TYPE_BLOOD_PRESSURE) {
datapoint.getValue(HealthFields.FIELD_BLOOD_PRESSURE_DIASTOLIC).setFloat(70);
datapoint.getValue(HealthFields.FIELD_BLOOD_PRESSURE_SYSTOLIC).setFloat(100);
}
dataSet.add(datapoint);

Status insertStatus = Fitness.HistoryApi.insertData(mClient, dataSet)
.await(1, TimeUnit.MINUTES);

if (insertStatus.isSuccess()) {
// already authorised, go on
onActivityResult(REQUEST_OATH_HEALTH, Activity.RESULT_OK, null);
} else {
if (authAutoresolve) {
if (insertStatus.hasResolution()) {
try {
insertStatus.startResolutionForResult(cordova.getActivity(), REQUEST_OATH_HEALTH);
} catch (IntentSender.SendIntentException e) {
authReqCallbackCtx.error("Cannot authorise health data type " + dt.getName() + ", cannot send intent: " + e.getMessage());
return;
}
} else {
authReqCallbackCtx.error("Cannot authorise health data type " + dt.getName() + ", " + insertStatus.getStatusMessage());
return;
}
} else {
// probably not authorized, send false
Log.d(TAG, "Connection to Fit failed, probably because of authorization, giving up now");
authReqCallbackCtx.sendPluginResult(new PluginResult(PluginResult.Status.OK, false));
return;
}
}
}
});
}


// queries for datapoints
private void query(final JSONArray args, final CallbackContext callbackContext) throws JSONException {
Expand Down