From d74602d60943b08709b166a64c803eef181ff6dd Mon Sep 17 00:00:00 2001 From: Francesco-Voto Date: Sun, 14 Feb 2021 14:41:03 +0100 Subject: [PATCH] Create diffeten modules in android environmnet --- .../ovalmoney/fitness/RNFitnessPackage.java | 40 ++-- .../fitness/managers/ActivitiesManager.java | 204 ++++++++++++++++ .../fitness/managers/AuthManager.java | 177 ++++++++++++++ .../fitness/managers/BodyManager.java | 221 ++++++++++++++++++ .../{manager => managers}/FitnessError.java | 0 .../{manager => managers}/Manager.java | 0 .../modules/RNFitnessActivitiesModule.java | 58 +++++ .../fitness/modules/RNFitnessAuthModule.java | 86 +++++++ .../fitness/modules/RNFitnessBodyModule.java | 51 ++++ 9 files changed, 824 insertions(+), 13 deletions(-) create mode 100644 android/src/main/java/com/ovalmoney/fitness/managers/ActivitiesManager.java create mode 100644 android/src/main/java/com/ovalmoney/fitness/managers/AuthManager.java create mode 100644 android/src/main/java/com/ovalmoney/fitness/managers/BodyManager.java rename android/src/main/java/com/ovalmoney/fitness/{manager => managers}/FitnessError.java (100%) rename android/src/main/java/com/ovalmoney/fitness/{manager => managers}/Manager.java (100%) create mode 100644 android/src/main/java/com/ovalmoney/fitness/modules/RNFitnessActivitiesModule.java create mode 100644 android/src/main/java/com/ovalmoney/fitness/modules/RNFitnessAuthModule.java create mode 100644 android/src/main/java/com/ovalmoney/fitness/modules/RNFitnessBodyModule.java diff --git a/android/src/main/java/com/ovalmoney/fitness/RNFitnessPackage.java b/android/src/main/java/com/ovalmoney/fitness/RNFitnessPackage.java index 6ee1a92..e116e3c 100644 --- a/android/src/main/java/com/ovalmoney/fitness/RNFitnessPackage.java +++ b/android/src/main/java/com/ovalmoney/fitness/RNFitnessPackage.java @@ -1,5 +1,7 @@ package com.ovalmoney.fitness; +import androidx.annotation.NonNull; + import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -9,19 +11,31 @@ import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.uimanager.ViewManager; import com.facebook.react.bridge.JavaScriptModule; +import com.ovalmoney.fitness.modules.RNFitnessActivitiesModule; +import com.ovalmoney.fitness.modules.RNFitnessAuthModule; +import com.ovalmoney.fitness.modules.RNFitnessBodyModule; + public class RNFitnessPackage implements ReactPackage { - @Override - public List createNativeModules(ReactApplicationContext reactContext) { - return Arrays.asList(new RNFitnessModule(reactContext)); - } - // Deprecated from RN 0.47 - public List> createJSModules() { - return Collections.emptyList(); - } + @NonNull + @Override + public List createNativeModules(@NonNull ReactApplicationContext reactContext) { + return Arrays.asList( + new RNFitnessModule(reactContext), + new RNFitnessAuthModule(reactContext), + new RNFitnessActivitiesModule(reactContext), + new RNFitnessBodyModule(reactContext) + ); + } + + // Deprecated from RN 0.47 + public List> createJSModules() { + return Collections.emptyList(); + } - @Override - public List createViewManagers(ReactApplicationContext reactContext) { - return Collections.emptyList(); - } -} \ No newline at end of file + @NonNull + @Override + public List createViewManagers(@NonNull ReactApplicationContext reactContext) { + return Collections.emptyList(); + } +} diff --git a/android/src/main/java/com/ovalmoney/fitness/managers/ActivitiesManager.java b/android/src/main/java/com/ovalmoney/fitness/managers/ActivitiesManager.java new file mode 100644 index 0000000..108ed37 --- /dev/null +++ b/android/src/main/java/com/ovalmoney/fitness/managers/ActivitiesManager.java @@ -0,0 +1,204 @@ +package com.ovalmoney.fitness.managers; + +import android.content.Context; + +import androidx.annotation.NonNull; + +import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.Promise; +import com.facebook.react.bridge.WritableArray; +import com.facebook.react.bridge.WritableMap; +import com.google.android.gms.auth.api.signin.GoogleSignIn; +import com.google.android.gms.auth.api.signin.GoogleSignInAccount; +import com.google.android.gms.fitness.Fitness; +import com.google.android.gms.fitness.data.Bucket; +import com.google.android.gms.fitness.data.DataPoint; +import com.google.android.gms.fitness.data.DataSet; +import com.google.android.gms.fitness.data.DataSource; +import com.google.android.gms.fitness.data.DataType; +import com.google.android.gms.fitness.data.Field; +import com.google.android.gms.fitness.request.DataReadRequest; +import com.google.android.gms.fitness.result.DataReadResponse; +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.OnFailureListener; +import com.google.android.gms.tasks.OnSuccessListener; +import com.google.android.gms.tasks.Task; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.List; +import java.util.Locale; +import java.util.concurrent.TimeUnit; + +public class ActivitiesManager { + + private final static DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.getDefault()); + + private static TimeUnit getInterval(String customInterval) { + if(customInterval.equals("minute")) { + return TimeUnit.MINUTES; + } + if(customInterval.equals("hour")) { + return TimeUnit.HOURS; + } + return TimeUnit.DAYS; + } + + public void subscribeToActivity(Context context, final Promise promise){ + final GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(context); + if(account == null){ + promise.resolve(false); + return; + } + Fitness.getRecordingClient(context, account) + .subscribe(DataType.TYPE_ACTIVITY_SAMPLES) + .addOnSuccessListener(new OnSuccessListener() { + @Override + public void onSuccess(Void aVoid) { + promise.resolve(true); + } + }) + .addOnFailureListener(new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception e) { + promise.resolve(false); + } + }); + + } + + public void subscribeToSteps(Context context, final Promise promise){ + final GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(context); + if(account == null){ + promise.resolve(false); + return; + } + Fitness.getRecordingClient(context, account) + .subscribe(DataType.TYPE_STEP_COUNT_DELTA) + .addOnSuccessListener(new OnSuccessListener() { + @Override + public void onSuccess(Void aVoid) { + promise.resolve(true); + } + }) + .addOnFailureListener(new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception e) { + promise.resolve(false); + } + }); + } + + public void getSteps(Context context, double startDate, double endDate, String customInterval, final Promise promise){ + DataSource ESTIMATED_STEP_DELTAS = new DataSource.Builder() + .setDataType(DataType.TYPE_STEP_COUNT_DELTA) + .setType(DataSource.TYPE_DERIVED) + .setStreamName("estimated_steps") + .setAppPackageName("com.google.android.gms") + .build(); + + TimeUnit interval = getInterval(customInterval); + + DataReadRequest readRequest = new DataReadRequest.Builder() + .aggregate(ESTIMATED_STEP_DELTAS, DataType.AGGREGATE_STEP_COUNT_DELTA) + .bucketByTime(1, interval) + .setTimeRange((long) startDate, (long) endDate, TimeUnit.MILLISECONDS) + .build(); + + Fitness.getHistoryClient(context, GoogleSignIn.getLastSignedInAccount(context)) + .readData(readRequest) + .addOnSuccessListener(new OnSuccessListener() { + @Override + public void onSuccess(DataReadResponse dataReadResponse) { + if (dataReadResponse.getBuckets().size() > 0) { + WritableArray steps = Arguments.createArray(); + for (Bucket bucket : dataReadResponse.getBuckets()) { + List dataSets = bucket.getDataSets(); + for (DataSet dataSet : dataSets) { + processStep(dataSet, steps); + } + } + promise.resolve(steps); + } + } + }) + .addOnFailureListener(new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception e) { + promise.reject(e); + } + }) + .addOnCompleteListener(new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + } + }); + } + + public void getDistances(Context context, double startDate, double endDate, String customInterval, final Promise promise) { + TimeUnit interval = getInterval(customInterval); + + DataReadRequest readRequest = new DataReadRequest.Builder() + .aggregate(DataType.TYPE_DISTANCE_DELTA, DataType.AGGREGATE_DISTANCE_DELTA) + .bucketByTime(1, interval) + .setTimeRange((long) startDate, (long) endDate, TimeUnit.MILLISECONDS) + .build(); + + Fitness.getHistoryClient(context, GoogleSignIn.getLastSignedInAccount(context)) + .readData(readRequest) + .addOnSuccessListener(new OnSuccessListener() { + @Override + public void onSuccess(DataReadResponse dataReadResponse) { + if (dataReadResponse.getBuckets().size() > 0) { + WritableArray distances = Arguments.createArray(); + for (Bucket bucket : dataReadResponse.getBuckets()) { + List dataSets = bucket.getDataSets(); + for (DataSet dataSet : dataSets) { + processDistance(dataSet, distances); + } + } + promise.resolve(distances); + } + } + }) + .addOnFailureListener(new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception e) { + promise.reject(e); + } + }) + .addOnCompleteListener(new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + } + }); + } + + private void processStep(DataSet dataSet, WritableArray map) { + + WritableMap stepMap = Arguments.createMap(); + + for (DataPoint dp : dataSet.getDataPoints()) { + for(Field field : dp.getDataType().getFields()) { + stepMap.putString("startDate", dateFormat.format(dp.getStartTime(TimeUnit.MILLISECONDS))); + stepMap.putString("endDate", dateFormat.format(dp.getEndTime(TimeUnit.MILLISECONDS))); + stepMap.putDouble("quantity", dp.getValue(field).asInt()); + map.pushMap(stepMap); + } + } + } + + private void processDistance(DataSet dataSet, WritableArray map) { + + WritableMap distanceMap = Arguments.createMap(); + + for (DataPoint dp : dataSet.getDataPoints()) { + for(Field field : dp.getDataType().getFields()) { + distanceMap.putString("startDate", dateFormat.format(dp.getStartTime(TimeUnit.MILLISECONDS))); + distanceMap.putString("endDate", dateFormat.format(dp.getEndTime(TimeUnit.MILLISECONDS))); + distanceMap.putDouble("quantity", dp.getValue(field).asFloat()); + map.pushMap(distanceMap); + } + } + } +} diff --git a/android/src/main/java/com/ovalmoney/fitness/managers/AuthManager.java b/android/src/main/java/com/ovalmoney/fitness/managers/AuthManager.java new file mode 100644 index 0000000..de75284 --- /dev/null +++ b/android/src/main/java/com/ovalmoney/fitness/managers/AuthManager.java @@ -0,0 +1,177 @@ +package com.ovalmoney.fitness.managers; + +import android.app.Activity; +import android.content.Intent; +import android.util.Log; + +import androidx.annotation.NonNull; + +import com.facebook.react.bridge.ActivityEventListener; +import com.facebook.react.bridge.Promise; +import com.google.android.gms.auth.api.signin.GoogleSignIn; +import com.google.android.gms.auth.api.signin.GoogleSignInAccount; +import com.google.android.gms.auth.api.signin.GoogleSignInOptions; +import com.google.android.gms.common.ConnectionResult; +import com.google.android.gms.common.GoogleApiAvailability; +import com.google.android.gms.fitness.Fitness; +import com.google.android.gms.fitness.FitnessOptions; +import com.google.android.gms.fitness.data.DataType; +import com.google.android.gms.tasks.OnCanceledListener; +import com.google.android.gms.tasks.OnFailureListener; +import com.google.android.gms.tasks.OnSuccessListener; +import com.ovalmoney.fitness.permission.Request; + +import java.util.ArrayList; + +import static com.ovalmoney.fitness.permission.Permissions.ACTIVITY; +import static com.ovalmoney.fitness.permission.Permissions.CALORIES; +import static com.ovalmoney.fitness.permission.Permissions.DISTANCES; +import static com.ovalmoney.fitness.permission.Permissions.HEART_RATE; +import static com.ovalmoney.fitness.permission.Permissions.SLEEP_ANALYSIS; +import static com.ovalmoney.fitness.permission.Permissions.STEPS; + +public class AuthManager implements ActivityEventListener { + + private final static int GOOGLE_FIT_PERMISSIONS_REQUEST_CODE = 111; + private final static int GOOGLE_PLAY_SERVICE_ERROR_DIALOG = 2404; + + private Promise promise; + + private static boolean isGooglePlayServicesAvailable(final Activity activity) { + GoogleApiAvailability googleApiAvailability = GoogleApiAvailability.getInstance(); + int status = googleApiAvailability.isGooglePlayServicesAvailable(activity); + if(status != ConnectionResult.SUCCESS) { + if(googleApiAvailability.isUserResolvableError(status)) { + googleApiAvailability.getErrorDialog(activity, status, GOOGLE_PLAY_SERVICE_ERROR_DIALOG).show(); + } + return false; + } + return true; + } + + private FitnessOptions.Builder addPermissionToFitnessOptions(final FitnessOptions.Builder fitnessOptions, final ArrayList permissions){ + int length = permissions.size(); + for(int i = 0; i < length; i++){ + Request currentRequest = permissions.get(i); + switch(currentRequest.permissionKind){ + case STEPS: + fitnessOptions + .addDataType(DataType.TYPE_STEP_COUNT_DELTA, currentRequest.permissionAccess) + .addDataType(DataType.TYPE_STEP_COUNT_CUMULATIVE, currentRequest.permissionAccess); + break; + case DISTANCES: + fitnessOptions.addDataType(DataType.TYPE_DISTANCE_DELTA, currentRequest.permissionAccess); + break; + case CALORIES: + fitnessOptions.addDataType(DataType.TYPE_CALORIES_EXPENDED, currentRequest.permissionAccess); + break; + case ACTIVITY: + fitnessOptions.addDataType(DataType.TYPE_ACTIVITY_SEGMENT, currentRequest.permissionAccess); + break; + case HEART_RATE: + fitnessOptions.addDataType(DataType.TYPE_HEART_RATE_BPM, currentRequest.permissionAccess); + break; + case SLEEP_ANALYSIS: + default: + break; + } + } + + return fitnessOptions; + } + + public boolean isAuthorized(final Activity activity, final ArrayList permissions){ + if(isGooglePlayServicesAvailable(activity)) { + final FitnessOptions fitnessOptions = addPermissionToFitnessOptions(FitnessOptions.builder(), permissions) + .build(); + return GoogleSignIn.hasPermissions(GoogleSignIn.getLastSignedInAccount(activity), fitnessOptions); + } + return false; + } + + public void requestPermissions(@NonNull Activity currentActivity, final ArrayList permissions, Promise promise) { + try { + this.promise = promise; + FitnessOptions fitnessOptions = addPermissionToFitnessOptions(FitnessOptions.builder(), permissions) + .build(); + GoogleSignIn.requestPermissions( + currentActivity, + GOOGLE_FIT_PERMISSIONS_REQUEST_CODE, + GoogleSignIn.getLastSignedInAccount(currentActivity.getApplicationContext()), + fitnessOptions); + }catch(Exception e){ + Log.e(getClass().getName(), e.getMessage()); + } + } + + + public void logout(@NonNull Activity currentActivity, final Promise promise) { + final GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN).build(); + GoogleSignIn.getClient(currentActivity, gso) + .revokeAccess() + .addOnCanceledListener(new OnCanceledListener() { + @Override + public void onCanceled() { + promise.resolve(false); + } + }) + .addOnSuccessListener(new OnSuccessListener() { + @Override + public void onSuccess(Void aVoid) { + promise.resolve(true); + } + }) + .addOnFailureListener(new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception e) { + promise.reject(e); + } + }); + } + + public void disconnect(@NonNull Activity currentActivity, final Promise promise) { + GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(currentActivity.getApplicationContext()); + + if (account == null) { + promise.reject(new Exception()); + return; + } + + Fitness.getConfigClient( + currentActivity, + account + ) + .disableFit() + .addOnCanceledListener(new OnCanceledListener() { + @Override + public void onCanceled() { + promise.resolve(false); + } + }) + .addOnSuccessListener(new OnSuccessListener() { + @Override + public void onSuccess(Void aVoid) { + promise.resolve(true); + } + }) + .addOnFailureListener(new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception e) { + promise.reject(e); + } + }); + } + + @Override + public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) { + if (resultCode == Activity.RESULT_OK && requestCode == GOOGLE_FIT_PERMISSIONS_REQUEST_CODE) { + promise.resolve(true); + } + if (resultCode == Activity.RESULT_CANCELED && requestCode == GOOGLE_FIT_PERMISSIONS_REQUEST_CODE) { + promise.resolve(false); + } + } + + @Override + public void onNewIntent(Intent intent) { } +} diff --git a/android/src/main/java/com/ovalmoney/fitness/managers/BodyManager.java b/android/src/main/java/com/ovalmoney/fitness/managers/BodyManager.java new file mode 100644 index 0000000..5423f2b --- /dev/null +++ b/android/src/main/java/com/ovalmoney/fitness/managers/BodyManager.java @@ -0,0 +1,221 @@ +package com.ovalmoney.fitness.managers; + +import android.content.Context; +import android.os.Build; + +import androidx.annotation.NonNull; +import androidx.annotation.RequiresApi; + +import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.Promise; +import com.facebook.react.bridge.WritableArray; +import com.facebook.react.bridge.WritableMap; +import com.google.android.gms.auth.api.signin.GoogleSignIn; +import com.google.android.gms.fitness.Fitness; +import com.google.android.gms.fitness.FitnessActivities; +import com.google.android.gms.fitness.data.Bucket; +import com.google.android.gms.fitness.data.DataPoint; +import com.google.android.gms.fitness.data.DataSet; +import com.google.android.gms.fitness.data.DataType; +import com.google.android.gms.fitness.data.Field; +import com.google.android.gms.fitness.data.Session; +import com.google.android.gms.fitness.request.DataReadRequest; +import com.google.android.gms.fitness.request.SessionReadRequest; +import com.google.android.gms.fitness.result.DataReadResponse; +import com.google.android.gms.fitness.result.SessionReadResponse; +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.OnFailureListener; +import com.google.android.gms.tasks.OnSuccessListener; +import com.google.android.gms.tasks.Task; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.List; +import java.util.Locale; +import java.util.concurrent.TimeUnit; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +public class BodyManager { + private final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.getDefault()); + + private static TimeUnit getInterval(String customInterval) { + if(customInterval.equals("minute")) { + return TimeUnit.MINUTES; + } + if(customInterval.equals("hour")) { + return TimeUnit.HOURS; + } + return TimeUnit.DAYS; + } + + public void getCalories(Context context, double startDate, double endDate, String customInterval, final Promise promise) { + TimeUnit interval = getInterval(customInterval); + + DataReadRequest readRequest = new DataReadRequest.Builder() + .aggregate(DataType.TYPE_CALORIES_EXPENDED, DataType.AGGREGATE_CALORIES_EXPENDED) + .bucketByTime(1, interval) + .setTimeRange((long) startDate, (long) endDate, TimeUnit.MILLISECONDS) + .build(); + + Fitness.getHistoryClient(context, GoogleSignIn.getLastSignedInAccount(context)) + .readData(readRequest) + .addOnSuccessListener(new OnSuccessListener() { + @Override + public void onSuccess(DataReadResponse dataReadResponse) { + if (dataReadResponse.getBuckets().size() > 0) { + WritableArray calories = Arguments.createArray(); + for (Bucket bucket : dataReadResponse.getBuckets()) { + List dataSets = bucket.getDataSets(); + for (DataSet dataSet : dataSets) { + processCalories(dataSet, calories); + } + } + promise.resolve(calories); + } + } + }) + .addOnFailureListener(new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception e) { + promise.reject(e); + } + }) + .addOnCompleteListener(new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + } + }); + } + + public void getHeartRate(Context context, double startDate, double endDate, String customInterval,final Promise promise) { + TimeUnit interval = getInterval(customInterval); + + DataReadRequest readRequest = new DataReadRequest.Builder() + .aggregate(DataType.TYPE_HEART_RATE_BPM, DataType.AGGREGATE_HEART_RATE_SUMMARY) + .bucketByTime(1, interval) + .setTimeRange((long) startDate, (long) endDate, TimeUnit.MILLISECONDS) + .build(); + + Fitness.getHistoryClient(context, GoogleSignIn.getLastSignedInAccount(context)) + .readData(readRequest) + .addOnSuccessListener(new OnSuccessListener() { + @Override + public void onSuccess(DataReadResponse dataReadResponse) { + if (dataReadResponse.getBuckets().size() > 0) { + WritableArray heartRates = Arguments.createArray(); + for (Bucket bucket : dataReadResponse.getBuckets()) { + List dataSets = bucket.getDataSets(); + for (DataSet dataSet : dataSets) { + processHeartRate(dataSet, heartRates); + } + } + promise.resolve(heartRates); + } + } + }) + .addOnFailureListener(new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception e) { + promise.reject(e); + } + }) + .addOnCompleteListener(new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + } + }); + } + + @RequiresApi(api = Build.VERSION_CODES.N) + public void getSleepAnalysis(Context context, double startDate, double endDate, final Promise promise) { + if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.N){ + promise.reject(String.valueOf(FitnessError.ERROR_METHOD_NOT_AVAILABLE), "Method not available"); + return; + } + + SessionReadRequest request = new SessionReadRequest.Builder() + .readSessionsFromAllApps() + .read(DataType.TYPE_ACTIVITY_SEGMENT) + .setTimeInterval((long) startDate, (long) endDate, TimeUnit.MILLISECONDS) + .build(); + + Fitness.getSessionsClient(context, GoogleSignIn.getLastSignedInAccount(context)) + .readSession(request) + .addOnSuccessListener(new OnSuccessListener() { + @Override + public void onSuccess(SessionReadResponse response) { + List sleepSessions = response.getSessions() + .stream() + .filter(new Predicate() { + @Override + public boolean test(Session s) { + return s.getActivity().equals(FitnessActivities.SLEEP); + } + }) + .collect(Collectors.toList()); + + WritableArray sleep = Arguments.createArray(); + + for (Object session : sleepSessions) { + List dataSets = response.getDataSet((Session) session); + + for (DataSet dataSet : dataSets) { + processSleep(dataSet, (Session) session, sleep); + } + } + + promise.resolve(sleep); + } + }) + .addOnFailureListener(new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception e) { + promise.reject(e); + } + }); + } + + private void processHeartRate(DataSet dataSet, WritableArray map) { + + WritableMap heartRateMap = Arguments.createMap(); + + for (DataPoint dp : dataSet.getDataPoints()) { + for(Field field : dp.getDataType().getFields()) { + heartRateMap.putString("startDate", dateFormat.format(dp.getStartTime(TimeUnit.MILLISECONDS))); + heartRateMap.putString("endDate", dateFormat.format(dp.getEndTime(TimeUnit.MILLISECONDS))); + heartRateMap.putDouble("quantity", dp.getValue(field).asFloat()); + map.pushMap(heartRateMap); + } + } + } + + private void processCalories(DataSet dataSet, WritableArray map) { + + WritableMap distanceMap = Arguments.createMap(); + + for (DataPoint dp : dataSet.getDataPoints()) { + for(Field field : dp.getDataType().getFields()) { + distanceMap.putString("startDate", dateFormat.format(dp.getStartTime(TimeUnit.MILLISECONDS))); + distanceMap.putString("endDate", dateFormat.format(dp.getEndTime(TimeUnit.MILLISECONDS))); + distanceMap.putDouble("quantity", dp.getValue(field).asFloat()); + map.pushMap(distanceMap); + } + } + } + + private void processSleep(DataSet dataSet, Session session, WritableArray map) { + + WritableMap sleepMap = Arguments.createMap(); + + for (DataPoint dp : dataSet.getDataPoints()) { + for (Field field : dp.getDataType().getFields()) { + sleepMap.putString("value", dp.getValue(field).asActivity()); + sleepMap.putString("sourceId", session.getIdentifier()); + sleepMap.putString("startDate", dateFormat.format(dp.getStartTime(TimeUnit.MILLISECONDS))); + sleepMap.putString("endDate", dateFormat.format(dp.getEndTime(TimeUnit.MILLISECONDS))); + map.pushMap(sleepMap); + } + } + } +} diff --git a/android/src/main/java/com/ovalmoney/fitness/manager/FitnessError.java b/android/src/main/java/com/ovalmoney/fitness/managers/FitnessError.java similarity index 100% rename from android/src/main/java/com/ovalmoney/fitness/manager/FitnessError.java rename to android/src/main/java/com/ovalmoney/fitness/managers/FitnessError.java diff --git a/android/src/main/java/com/ovalmoney/fitness/manager/Manager.java b/android/src/main/java/com/ovalmoney/fitness/managers/Manager.java similarity index 100% rename from android/src/main/java/com/ovalmoney/fitness/manager/Manager.java rename to android/src/main/java/com/ovalmoney/fitness/managers/Manager.java diff --git a/android/src/main/java/com/ovalmoney/fitness/modules/RNFitnessActivitiesModule.java b/android/src/main/java/com/ovalmoney/fitness/modules/RNFitnessActivitiesModule.java new file mode 100644 index 0000000..7e9e50e --- /dev/null +++ b/android/src/main/java/com/ovalmoney/fitness/modules/RNFitnessActivitiesModule.java @@ -0,0 +1,58 @@ +package com.ovalmoney.fitness.modules; + +import com.facebook.react.bridge.Promise; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; +import com.ovalmoney.fitness.managers.ActivitiesManager; + +public class RNFitnessActivitiesModule extends ReactContextBaseJavaModule { + + private final ActivitiesManager manager; + + public RNFitnessActivitiesModule(ReactApplicationContext reactContext) { + super(reactContext); + this.manager = new ActivitiesManager(); + } + + @Override + public String getName() { + return "ActivitiesFitness"; + } + + @ReactMethod + public void subscribeToActivity(Promise promise){ + try { + manager.subscribeToActivity(getCurrentActivity(), promise); + }catch(Error e){ + promise.reject(e); + } + } + + @ReactMethod + public void subscribeToSteps(Promise promise){ + try { + manager.subscribeToSteps(getCurrentActivity(), promise); + }catch(Error e){ + promise.reject(e); + } + } + + @ReactMethod + public void getSteps(double startDate, double endDate, String interval, Promise promise){ + try { + manager.getSteps(getCurrentActivity(), startDate, endDate, interval, promise); + }catch(Error e){ + promise.reject(e); + } + } + + @ReactMethod + public void getDistances(double startDate, double endDate, String interval, Promise promise){ + try { + manager.getDistances(getCurrentActivity(), startDate, endDate, interval, promise); + }catch(Error e){ + promise.reject(e); + } + } +} diff --git a/android/src/main/java/com/ovalmoney/fitness/modules/RNFitnessAuthModule.java b/android/src/main/java/com/ovalmoney/fitness/modules/RNFitnessAuthModule.java new file mode 100644 index 0000000..79dbf94 --- /dev/null +++ b/android/src/main/java/com/ovalmoney/fitness/modules/RNFitnessAuthModule.java @@ -0,0 +1,86 @@ +package com.ovalmoney.fitness.modules; + +import android.app.Activity; +import android.util.Log; + +import com.facebook.react.bridge.Promise; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.ReadableMap; +import com.google.android.gms.fitness.FitnessOptions; +import com.ovalmoney.fitness.managers.AuthManager; +import com.ovalmoney.fitness.permission.Request; + +import java.util.ArrayList; + +public class RNFitnessAuthModule extends ReactContextBaseJavaModule { + + private final static String TAG = com.ovalmoney.fitness.RNFitnessModule.class.getName(); + + private final AuthManager manager; + + public RNFitnessAuthModule(ReactApplicationContext reactContext) { + super(reactContext); + this.manager = new AuthManager(); + reactContext.addActivityEventListener(this.manager); + } + + @Override + public String getName() { + return "AuthFitness"; + } + + @ReactMethod + public void isAuthorized(ReadableArray permissions, Promise promise){ + promise.resolve(manager.isAuthorized(getCurrentActivity(), createRequestFromReactArray(permissions))); + } + + @ReactMethod + public void requestPermissions(ReadableArray permissions, Promise promise){ + final Activity activity = getCurrentActivity(); + if(activity != null) { + manager.requestPermissions(activity,createRequestFromReactArray(permissions), promise); + }else{ + promise.reject(new Throwable()); + } + } + + @ReactMethod + public void logout(Promise promise){ + final Activity activity = getCurrentActivity(); + if(activity != null) { + manager.logout(activity, promise); + }else{ + promise.reject(new Throwable()); + } + } + + @ReactMethod + public void disconnect(Promise promise){ + final Activity activity = getCurrentActivity(); + if(activity != null) { + manager.disconnect(activity, promise); + }else{ + promise.reject(new Throwable()); + } + + } + + private ArrayList createRequestFromReactArray(ReadableArray permissions){ + ArrayList requestPermissions = new ArrayList<>(); + int size = permissions.size(); + for(int i = 0; i < size; i++) { + try { + ReadableMap singlePermission = permissions.getMap(i); + final int permissionKind = singlePermission.getInt("kind"); + final int permissionAccess = singlePermission.hasKey("access") ? singlePermission.getInt("access") : FitnessOptions.ACCESS_READ; + requestPermissions.add(new Request(permissionKind, permissionAccess)); + } catch (NullPointerException e) { + Log.e(TAG, e.getMessage()); + } + } + return requestPermissions; + } +} diff --git a/android/src/main/java/com/ovalmoney/fitness/modules/RNFitnessBodyModule.java b/android/src/main/java/com/ovalmoney/fitness/modules/RNFitnessBodyModule.java new file mode 100644 index 0000000..bd8ca1a --- /dev/null +++ b/android/src/main/java/com/ovalmoney/fitness/modules/RNFitnessBodyModule.java @@ -0,0 +1,51 @@ +package com.ovalmoney.fitness.modules; + +import com.facebook.react.bridge.Promise; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; +import com.ovalmoney.fitness.managers.AuthManager; +import com.ovalmoney.fitness.managers.BodyManager; + +public class RNFitnessBodyModule extends ReactContextBaseJavaModule { + + private final BodyManager manager; + + public RNFitnessBodyModule(ReactApplicationContext reactContext) { + super(reactContext); + this.manager = new BodyManager(); + } + + @Override + public String getName() { + return "BodyFitness"; + } + + @ReactMethod + public void getCalories(double startDate, double endDate, String interval, Promise promise){ + try { + manager.getCalories(getCurrentActivity(), startDate, endDate, interval, promise); + }catch(Error e){ + promise.reject(e); + } + } + + @ReactMethod + public void getHeartRate(double startDate, double endDate, String interval, Promise promise){ + try { + manager.getHeartRate(getCurrentActivity(), startDate, endDate, interval, promise); + }catch(Error e){ + promise.reject(e); + } + } + + @ReactMethod + public void getSleepAnalysis(double startDate, double endDate, Promise promise){ + try { + manager.getSleepAnalysis(getCurrentActivity(), startDate, endDate, promise); + }catch(Error e){ + promise.reject(e); + } + } +} +