Coder Social home page Coder Social logo

react-native-google-fit's Introduction

react-native-google-fit

Gitter Group - ask questions, answer questions!

npm version Downloads

A React Native bridge module for interacting with Google Fit

Quick Links

Requirement

If you didn't set fitnessVersion manually, you can simply skip this part.
Note that 0.16.1 require fitness version above 20.0.0
Please read https://developers.google.com/fit/improvements why we made the changes.

Android 11

For Android 11, If you want to interact with Google Fit App.
For example, use openFit(),isAvailable(callback). Otherwise ignore it.
Add the following queries into your AndroidManifest.xml

<queries>
    <package android:name="com.google.android.apps.fitness" />
</queries>

USAGE

  1. import GoogleFit, { Scopes } from 'react-native-google-fit'

2. Authorize:

To check whethere GoogleFit is already authorized, simply use a function, then you can refer to the static property GoogleFit.isAuthorized

GoogleFit.checkIsAuthorized().then(() => {
    console.log(GoogleFit.isAuthorized) // Then you can simply refer to `GoogleFit.isAuthorized` boolean.
})

or with async/await syntax

await checkIsAuthorized();
console.log(GoogleFit.isAuthorized);
// The list of available scopes inside of src/scopes.js file
const options = {
  scopes: [
    Scopes.FITNESS_ACTIVITY_READ,
    Scopes.FITNESS_ACTIVITY_WRITE,
    Scopes.FITNESS_BODY_READ,
    Scopes.FITNESS_BODY_WRITE,
  ],
}
GoogleFit.authorize(options)
  .then(authResult => {
    if (authResult.success) {
      dispatch("AUTH_SUCCESS");
    } else {
      dispatch("AUTH_DENIED", authResult.message);
    }
  })
  .catch(() => {
    dispatch("AUTH_ERROR");
  })

// ...
// Call when authorized
GoogleFit.startRecording((callback) => {
  // Process data from Google Fit Recording API (no google fit app needed)
});

Note: If you are using the recording API for location/ distance data, you have to request the location-permission in your app's AndroidManifest.xml: <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Alternatively you can use event listeners (deprecated)

 GoogleFit.onAuthorize(() => {
   dispatch('AUTH SUCCESS')
 })

 GoogleFit.onAuthorizeFailure(() => {
   dispatch('AUTH ERROR')
 })

3. Retrieve Steps For Period

const opt = {
  startDate: "2017-01-01T00:00:17.971Z", // required ISO8601Timestamp
  endDate: new Date().toISOString(), // required ISO8601Timestamp
  bucketUnit: BucketUnit.DAY, // optional - default "DAY". Valid values: "NANOSECOND" | "MICROSECOND" | "MILLISECOND" | "SECOND" | "MINUTE" | "HOUR" | "DAY"
  bucketInterval: 1, // optional - default 1. 
};

GoogleFit.getDailyStepCountSamples(opt)
 .then((res) => {
     console.log('Daily steps >>> ', res)
 })
 .catch((err) => {console.warn(err)});

// or with async/await syntax
async function fetchData() {
  const res = await GoogleFit.getDailyStepCountSamples(opt)
  console.log(res);
}

// shortcut functions, 
// return weekly or daily steps of given date
// all params are optional, using new Date() without given date, 
// adjustment is 0 by default, determine the first day of week, 0 == Sunday, 1==Monday, etc.
GoogleFit.getDailySteps(date).then().catch()
GoogleFit.getWeeklySteps(date, adjustment).then().catch()

Response:

[
  { source: "com.google.android.gms:estimated_steps", steps: [
    {
      "date":"2019-06-29","value":2328
    },
    {
      "date":"2019-06-30","value":8010
      }
    ]
  },
  { source: "com.google.android.gms:merge_step_deltas", steps: [
    {
      "date":"2019-06-29","value":2328
    },
    {
      "date":"2019-06-30","value":8010
      }
    ]
  },
  { source: "com.xiaomi.hm.health", steps: [] }
];

Note: bucket Config for step reflects on rawStep entity.

Response:

// {bucketInterval: 15, bucketUnit: BucketUnit.MINUTE}
[
  { source: "com.google.android.gms:estimated_steps", 
    steps: [
    {
      "date":"2019-07-06","value": 135
    },
    ],
    rawSteps: [
      {"endDate": 1594012101944, "startDate": 1594012041944, "steps": 13}, 
      {"endDate": 1594020600000, "startDate": 1594020596034, "steps": 0}, 
      {"endDate": 1594020693175, "startDate": 1594020600000, "steps": 24}, 
      {"endDate": 1594068898912, "startDate": 1594068777409, "steps": 53}, 
      {"endDate": 1594073158830, "startDate": 1594073066166, "steps": 45}
    ]
  },
]

// {bucketInterval: 1, bucketUnit: BucketUnit.DAY}
[
    { source: "com.google.android.gms:estimated_steps",
        ...
      rawSteps: [
       {"endDate": 1594073158830, "startDate": 1594012041944, "steps": 135}
      ]
    }
]

4. Retrieve Weights

const opt = {
  unit: "pound", // required; default 'kg'
  startDate: "2017-01-01T00:00:17.971Z", // required
  endDate: new Date().toISOString(), // required
  bucketUnit: BucketUnit.DAY, // optional - default "DAY". Valid values: "NANOSECOND" | "MICROSECOND" | "MILLISECOND" | "SECOND" | "MINUTE" | "HOUR" | "DAY"
  bucketInterval: 1, // optional - default 1. 
  ascending: false // optional; default false
};

GoogleFit.getWeightSamples(opt).then((res)=> {
  console.log(res)
});
// or with async/await syntax
async function fetchData() {
  const res = await GoogleFit.getWeightSamples(opt)
  console.log(res);
}

Response:

[
  {
    "addedBy": "app_package_name",
    "value":72,
    "endDate":"2019-06-29T15:02:23.413Z",
    "startDate":"2019-06-29T15:02:23.413Z",
    "day":"Sat"
  },
  {
    "addedBy": "app_package_name",
    "value":72.4000015258789,
    "endDate":"2019-07-26T08:06:42.903Z",
    "startDate":"2019-07-26T08:06:42.903Z",
    "day":"Fri"
  }
]

5. Retrieve Heights

const opt = {
  startDate: "2017-01-01T00:00:17.971Z", // required
  endDate: new Date().toISOString(), // required
};

GoogleFit.getHeightSamples(opt).then((res)=> {
  console.log(res);
});

Response:

[
  {
    "addedBy": "app_package_name",
    "value":1.7699999809265137, // Meter
    "endDate":"2019-06-29T15:02:23.409Z",
    "startDate":"2019-06-29T15:02:23.409Z",
    "day":"Sat"
  }
]

6. Save Weights

const opt = {
  value: 200,
  date: new Date().toISOString(),
  unit: "pound"
};

GoogleFit.saveWeight(opt, (err, res) => {
  if (err) throw "Cant save data to the Google Fit";
});

7. Blood pressure and Heart rate methods (since version 0.8)

Heartrate Scopes: 
    [
        Scopes.FITNESS_ACTIVITY_READ,
        Scopes.FITNESS_ACTIVITY_WRITE,
        Scopes.FITNESS_HEART_RATE_READ,
        Scopes.FITNESS_HEART_RATE_WRITE,
    ];
Blood pressure: 
    [
        FITNESS_BLOOD_PRESSURE_READ,
        FITNESS_BLOOD_PRESSURE_WRITE,
        FITNESS_BLOOD_GLUCOSE_READ,
        FITNESS_BLOOD_GLUCOSE_WRITE,
    ];
const options = {
  startDate: "2017-01-01T00:00:17.971Z", // required
  endDate: new Date().toISOString(), // required
  bucketUnit: BucketUnit.DAY, // optional - default "DAY". Valid values: "NANOSECOND" | "MICROSECOND" | "MILLISECOND" | "SECOND" | "MINUTE" | "HOUR" | "DAY"
  bucketInterval: 1, // optional - default 1. 
}

async function fetchData() {
  const heartrate = await GoogleFit.getHeartRateSamples(opt)
  console.log(heartrate);

  const restingheartrate = await GoogleFit.getRestingHeartRateSamples(opt)
  console.log(restingheartrate);

  const bloodpressure = await GoogleFit.getBloodPressureSamples(opt)
  console.log(bloodpressure);
}

Response:

// heart rate
[
  {
    "value":80,
    "endDate":"2019-07-26T10:19:21.348Z",
    "startDate":"2019-07-26T10:19:21.348Z",
    "day":"Fri"
  }
]

// blood pressure
[
  {
    "systolic":120,
    "diastolic":80,
    "endDate":"2019-07-26T08:39:28.493Z",
    "startDate":"1970-01-01T00:00:00.000Z",
    "day":"Thu"
  }
]

Getting aggregated heart rate samples:

/**
 * Query for getting aggregated heart rate samples.
 * @param options
 * @param inLocalTimeZone
 */
getAggregatedHeartRateSamples: (
  options: StartAndEndDate & Partial<BucketOptions>,
  inLocalTimeZone: boolean
) => Promise<AggregatedHeartRateResponse[]>;

Response:

[{
  startDate: string,
  endDate: string,
  min: number,
  average: number,
  max: number,
  day: Day,
}]

8. Get all activities


Require scopes: Scopes.FITNESS_ACTIVITY_READ & Scopes.FITNESS_LOCATION_READ
Add <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> to AndroidManifest.xml

  let opt = {
    startDate: "2017-01-01T00:00:17.971Z", // required
    endDate: new Date().toISOString(), // required
    bucketUnit: BucketUnit.DAY, // optional - default "DAY". Valid values: "NANOSECOND" | "MICROSECOND" | "MILLISECOND" | "SECOND" | "MINUTE" | "HOUR" | "DAY"
    bucketInterval: 1, // optional - default 1. 
  };

  GoogleFit.getActivitySamples(opt).then((res)=> {
    console.log(res)
  });
  // or with async/await syntax
  async function fetchData() {
    const res = await GoogleFit.getActivitySamples(opt)
    console.log(res);
  }

Response:

 [ { 
  sourceName: 'Android',
  device: 'Android',
  sourceId: 'com.google.android.gms',
  calories: 764.189208984375,
  quantity: 6,
  end: 1539774300992,
  tracked: true,
  activityName: 'still',
  start: 1539727200000 },
{ sourceName: 'Android',
  device: 'Android',
  sourceId: 'com.google.android.gms',
  calories: 10.351096153259277,
  quantity: 138,
  end: 1539774486088,
  tracked: true,
  distance: 88.09545135498047,
  activityName: 'walking',
}]

Where:

sourceName = device - 'Android' or 'Android Wear' string
sourceId - return a value of dataSource.getAppPackageName(). For more info see: https://developers.google.com/fit/android/data-attribution
start/end - timestamps of activity in format of milliseconds since the Unix Epoch
tracked - bool flag, is this activity was entered by user or tracked by device. Detected by checking milliseconds of start/end timestamps. Since when user log activity in googleFit they can't set milliseconds
distance(opt) - A distance in meters.
activityName - string, equivalent one of these https://developers.google.com/fit/rest/v1/reference/activity-types 
calories(opt) - double value of burned Calories in kcal.
quantity(opt) - equivalent of steps number

Note that optional parametrs are not presented in all activities - only where google fit return some results for this field. Like no distance for still activity.

9. Retrieve Calories For Period

  const opt = {
    startDate: "2017-01-01T00:00:17.971Z", // required
    endDate: new Date().toISOString(), // required
    basalCalculation: true, // optional, to calculate or not basalAVG over the week
    bucketUnit: BucketUnit.DAY, // optional - default "DAY". Valid values: "NANOSECOND" | "MICROSECOND" | "MILLISECOND" | "SECOND" | "MINUTE" | "HOUR" | "DAY"
    bucketInterval: 1, // optional - default 1. 
  };

  GoogleFit.getDailyCalorieSamples(opt).then((res) => {
    console.log(res);
  });

Response:

[
  {
    "calorie":1721.948974609375,
    "endDate":"2019-06-27T15:13:27.000Z",
    "startDate":"2019-06-27T15:02:23.409Z",
    "day":"Thu"
  },
  {
    "calorie":1598.25,
    "endDate":"2019-06-28T15:13:27.000Z",
    "startDate":"2019-06-27T15:13:27.000Z",
    "day":"Thu"
  }
]

10. Retrieve Distance For Period:

  const opt = {
    startDate: "2017-01-01T00:00:17.971Z", // required
    endDate: new Date().toISOString(), // required
    bucketUnit: BucketUnit.DAY, // optional - default "DAY". Valid values: "NANOSECOND" | "MICROSECOND" | "MILLISECOND" | "SECOND" | "MINUTE" | "HOUR" | "DAY"
    bucketInterval: 1, // optional - default 1. 
  };

  GoogleFit.getDailyDistanceSamples(opt).then((res)=>{
    console.log(res);
  });

 // or with async/await syntax
  async function fetchData() {
    const res = await GoogleFit.getDailyDistanceSamples(opt)
    console.log(res);
  }

Response:

[
  {
    "distance":2254.958251953125,
    "endDate":"2019-06-30T15:45:32.987Z",
    "startDate":"2019-06-29T16:57:01.047Z",
    "day":"Sat"
  },
  {
    "distance":3020.439453125,
    "endDate":"2019-07-01T13:08:31.332Z",
    "startDate":"2019-06-30T16:58:44.818Z",
    "day":"Sun"
  }
]

11. Retrieve Daily Nutrition Data for Period:

You need to add FITNESS_NUTRITION_READ scope to your authorization to work with nutrition.

  const opt = {
    startDate: "2017-01-01T00:00:17.971Z", // required
    endDate: new Date().toISOString(), // required
    bucketUnit: BucketUnit.DAY, // optional - default "DAY". Valid values: "NANOSECOND" | "MICROSECOND" | "MILLISECOND" | "SECOND" | "MINUTE" | "HOUR" | "DAY"
    bucketInterval: 1, // optional - default 1. 
  };

  GoogleFit.getDailyNutritionSamples(opt, (err, res) => {
    console.log(res);
  });

Response:

[
  {
    "nutrients":{"sugar":14,"sodium":1,"calories":105,"potassium":422},
    "date":"2019-07-02"
  },
  {
    "nutrients":{"sugar":36,"iron":0,"fat.saturated":3.6000001430511475,"sodium":0.13500000536441803,"fat.total":6,"calories":225,"fat.polyunsaturated":0,"carbs.total":36,"potassium":0.21000000834465027,"cholesterol":0.029999999329447746,"protein":9.299999237060547},
    "date":"2019-07-25"
  }
]

12. Save Food

You need to add FITNESS_NUTRITION_WRITE scope to your authorization to work with nutrition.

  const opt = {
    mealType: MealType.BREAKFAST,
    foodName: "banana",
    date: moment().format(), //equals to new Date().toISOString()
    nutrients: {
        [Nutrient.TOTAL_FAT]: 0.4,
        [Nutrient.SODIUM]: 1,
        [Nutrient.SATURATED_FAT]: 0.1,
        [Nutrient.PROTEIN]: 1.3,
        [Nutrient.TOTAL_CARBS]: 27.0,
        [Nutrient.CHOLESTEROL]: 0,
        [Nutrient.CALORIES]: 105,
        [Nutrient.SUGAR]: 14,
        [Nutrient.DIETARY_FIBER]: 3.1,
        [Nutrient.POTASSIUM]: 422,
    }
} as FoodIntake;

GoogleFit.saveFood(opt, (err, res) => {
  console.log(err, res);
})

13. Retrieve Hydration

You need to add FITNESS_NUTRITION_WRITE scope to your authorization to work with hydration.

  const opt = {
    startDate: '2020-01-05T00:00:17.971Z', // required
    endDate = new Date().toISOString() // required
  };

GoogleFit.getHydrationSamples(opt).then(res) => {
  console.log(res);
});

Response:

[
  {
    "addedBy": "app_package_name",
    "date": "2020-02-01T00:00:00.000Z",
    "waterConsumed": "0.225"
  },
  {
    "addedBy": "app_package_name",
    "date": "2020-02-02T00:00:00.000Z",
    "waterConsumed": "0.325"
  },
]

14. Save Hydration

This method can update hydration data. An app cannot update data inserted by other apps.

const hydrationArray = [
  {
    // recommand use moment().valueOf() or other alternatives since Date.parse() without specification can generate wrong date.
    date: Date.parse('2020-02-01'), // required, timestamp  
    waterConsumed: 0.225, // required, hydration data for a 0.225 liter drink of water
  },
  {
    date: Date.parse('2020-02-02'),
    waterConsumed: 0.325,
  },
];

GoogleFit.saveHydration(hydrationArray, (err, res) => {
  if (err) throw "Cant save data to the Google Fit";
});

Delete Hydration

An app cannot delete data inserted by other apps. startDate and endDate MUST not be the same.

const options = {
  startDate: '2020-01-01T12:33:18.873Z', // required, timestamp or ISO8601 string
  endDate: new Date().toISOString(), // required, timestamp or ISO8601 string
};

GoogleFit.deleteHydration(options, (err, res) => {
  console.log(res);
});

15. Retrieve Sleep

You need to add FITNESS_SLEEP_READ scope to your authorization to work with sleep.

const opt = {
  startDate: '2020-01-01T12:33:18.873Z', // required, timestamp or ISO8601 string
  endDate: new Date().toISOString(), // required, timestamp or ISO8601 string
};

GoogleFit.getSleepSamples(opt).then((res) => {
  console.log(res)
});

Response:

[
  { 
    'addedBy': 'com.google.android.apps.fitness' 
    'endDate': '2020-11-03T07:47:00.000Z',
    'startDate': '2020-11-03T07:33:59.160Z',
    // To understand what is granularity: https://developers.google.com/fit/scenarios/read-sleep-data
    'granularity': [
      {
        'startDate': {
          'sleepStage': 2,
          'endDate': '2020-11-03T07:47:00.000Z',
          'startDate': '2020-11-03T07:33:59.160Z',
        }
      }
    ],
  },
  { 
    'addedBy': 'com.google.android.apps.fitness',
    'endDate': '2020-11-02T17:41:00.000Z',
    'startDate': '2020-11-02T10:41:00.000Z',
    'granularity': [],
  },
]

Save Sleep

You need to add FITNESS_SLEEP_READ and FITNESS_SLEEP_WRITE scope to your authorization to save sleep. To reduce the complexity of converting data type internally, startDate and endDate must be number in Epoch/Unix timestamp

Note: identifier must be a unique string Read https://developers.google.com/fit/sessions, https://developer.android.com/training/articles/user-data-ids for more infos.

  const opts: SleepSample = {
    startDate: 1604052985000, 
    endDate: 1604063785000, // or more general example parseInt(new Date().valueOf())
    sessionName: "1604052985000-1604063785000:sleep-session",
    identifier: "1604052985000-1604063785000:sleep-identifier", // warning: just an example, the string is probably not unique enough
    description: "some description",
    granularity: [
      {
        startDate: 1604052985000,
        endDate: 1604056585000,
        sleepStage: 4,
      },
      {
        startDate: 1604056585000,
        endDate: 1604060185000,
        sleepStage: 5,
      }
    ]
  }
  const result = await GoogleFit.saveSleep(opts);
  console.log(result); //either be true or error

16. Move Minutes:

Require Scopes.FITNESS_ACTIVITY_READ

const opt = {
  startDate: '2020-01-01T12:33:18.873Z', // required, timestamp or ISO8601 string
  endDate: new Date().toISOString(), // required, timestamp or ISO8601 string
  //bucket unit...
};

GoogleFit.getMoveMinutes(opt).then((res) => {
  console.log(res)
});

Response:

[
   {
      "dataSourceId":"derived:com.google.active_minutes:com.google.android.gms:aggregated",
      "dataTypeName":"com.google.active_minutes",
      "duration":73,
      "endDate":1622594700000,
      "originDataSourceId":"derived:com.google.step_count.delta:com.google.android.gms:estimated_steps",
      "startDate":1622574300000
   },
   {
      "dataSourceId":"derived:com.google.active_minutes:com.google.android.gms:aggregated",
      "dataTypeName":"com.google.active_minutes",
      "duration":0,
      "endDate":1622675040000,
      "originDataSourceId":"raw:com.google.active_minutes:com.google.android.apps.fitness:user_input",
      "startDate":1622671440000
   },
   {
      "dataSourceId":"derived:com.google.active_minutes:com.google.android.gms:aggregated",
      "dataTypeName":"com.google.active_minutes",
      "duration":17,
      "endDate":1622854200000,
      "originDataSourceId":"derived:com.google.step_count.delta:com.google.android.gms:estimated_steps",
      "startDate":1622852220000
   }
]

17. Workout [Experimental]:

Fields may be inconsistent and overwrite by Google Fit App, it could be bugs or some internal processes that we are not aware of.
That's why it's experimental. Use at your own risk.
List of ActivityType
List of Session Activities from official Doc

Add:

GoogleFit.saveWorkout({
    startDate: startDate,
    endDate: endDate,
    sessionName: `session name`,
    // below example is probably not unique enough, must be **UUID**
    identifier: `session:${Date.now()}-${dataType}:${startDate}-${endDate}`,
    activityType: ActivityType.Meditation, //dataType
    description: `some description`,
    // options field
    calories: 233, // most consistent field across all activities
    steps: 600, // may not working, for example: ActivityType.Meditation doesn't have step by default
    // experimental field
    // this may not work or overwrite by GoogleFit App, it works in ActivityType.Other_unclassified_fitness_activity
    intensity: 1 // display as heart points in Google Fit app
});

Deletion:
Warning: Deletion is an async actions, Oftentimes the deletion would not happen immediately.

await GoogleFit.deleteAllWorkout({
   startDate: startDate,
   endDate: endDate,
})

Get Workout:
This is complemental method to getActivitySamples(), For some unknown reasons, both were missing some data or have incorrect data.
Try to use both to create a full picture if neccessary

await GoogleFit.getWorkoutSession({
   startDate: startDate,
   endDate: endDate,
})
func session Id session name session identifier description duration intensity calories, steps. etc.
getActivitySamples() ✔️ ✔️ ✔️
getWorkoutSession() ✔️ ✔️ ✔️ ✔️ ✔️

There is not such a update workout method if the workout exists in a session based on current investigation.
So if you want to do an update, you can try to do delete then create based on the old session timestamp

// startDate & endDate are from the existing session you want to modify
const options = {
    startDate: startDate,
    endDate: endDate,
    sessionName: `new session name`,
    identifier: `session:${Date.now()}-${dataType}:${startDate}-${endDate}`, // UUID
    activityType: ActivityType.Meditation, //dataType
    description: `new description`,
    .....
    newData
};

const del = await GoogleFit.deleteAllWorkout(options);

if(del) {
    const result = await GoogleFit.saveWorkout(options);
    console.log(result)
}

Other methods:

observeSteps(callback); // On Step Changed Event

unsubscribeListeners(); // Put into componentWillUnmount() method to prevent leaks

isAvailable(callback); // Checks is GoogleFit available for current account / installed on device

isEnabled(callback); // Checks is permissions granted

deleteWeight(options, callback); // method to delete weights by options (same as in delete hydration)

openFit(); //method to open google fit app

saveHeight(options, callback);

deleteHeight(options, callback); // method to delete heights by options (same as in delete hydration)

disconnect(); // Closes the connection to Google Play services.

PLANS / TODO

  • code refactoring
  • optimization

Copyright (c) 2017-present, Stanislav Doskalenko [email protected]

Based on Asim Malik android source code, copyright (c) 2015, thanks mate!

react-native-google-fit's People

Contributors

13thdeus avatar aboveyunhai avatar adamivancza avatar bsquang avatar cersates avatar chrisgibbs44 avatar dependabot[bot] avatar dethell avatar ejohnf avatar firodj avatar frikkiesnyman avatar gaykov avatar haikov avatar jguix avatar kristerkari avatar ksetrin avatar marcusds avatar nullpointer07 avatar priezz avatar reboss avatar rhys-jmc avatar ruanlinos avatar sash20m avatar seandunford avatar skb1129 avatar spasecadet avatar stasdoskalenko avatar stasdoskalenkohover avatar thanhnt-hapo avatar venom42 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-native-google-fit's Issues

How to get steps between two times

Hi there, is there a way to get the steps taken between two times? I'm trying the getDailyStepSamples function as in the documentation but I keep getting three empty arrays.

Any help would be appreciated, thanks!

Question regarding the Xiao Mi Support

With version 0.3 comes Xiao mi support, please help me understand how that is.

If I am understanding the code correctly, it seems like MiFit is added as a data source. link to code
Thus the user still needs to authorize google fit before pulling activity data?

THanks!

Unable to instantiate activity ComponentInfo

Received the following error on pre-lollipop devices. Any ideas?

W/dalvikvm( 2532): VFY: unable to resolve virtual method 359: Landroid/app/Notification$Builder;.setLocalOnly (Z)Landroid/app/Notification$Builder; W/dalvikvm( 2532): VFY: unable to resolve virtual method 892: Landroid/content/pm/PackageManager;.getPackageInstaller ()Landroid/content/pm/PackageInstaller; W/dalvikvm( 2532): threadid=1: thread exiting with uncaught exception (group=0xa4d3cb20) E/AndroidRuntime( 2532): FATAL EXCEPTION: main E/AndroidRuntime( 2532): Process: track.android.debug, PID: 2532 E/AndroidRuntime( 2532): java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{track.android.debug/track.android.MainActivity}: java.lang.ClassNotFoundException: Didn't find class "track.android.MainActivity" on path: DexPathList[[zip file "/data/app/track.android.debug-2.apk"],nativeLibraryDirectories=[/data/app-lib/track.android.debug-2, /system/lib]] E/AndroidRuntime( 2532): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2110) E/AndroidRuntime( 2532): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2233) E/AndroidRuntime( 2532): at android.app.ActivityThread.access$800(ActivityThread.java:135) E/AndroidRuntime( 2532): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196) E/AndroidRuntime( 2532): at android.os.Handler.dispatchMessage(Handler.java:102) E/AndroidRuntime( 2532): at android.os.Looper.loop(Looper.java:136) E/AndroidRuntime( 2532): at android.app.ActivityThread.main(ActivityThread.java:5001) E/AndroidRuntime( 2532): at java.lang.reflect.Method.invokeNative(Native Method) E/AndroidRuntime( 2532): at java.lang.reflect.Method.invoke(Method.java:515) E/AndroidRuntime( 2532): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785) E/AndroidRuntime( 2532): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601) E/AndroidRuntime( 2532): at dalvik.system.NativeStart.main(Native Method) E/AndroidRuntime( 2532): Caused by: java.lang.ClassNotFoundException: Didn't find class "track.android.MainActivity" on path: DexPathList[[zip file "/data/app/track.android.debug-2.apk"],nativeLibraryDirectories=[/data/app-lib/track.android.debug-2, /system/lib]] E/AndroidRuntime( 2532): at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56) E/AndroidRuntime( 2532): at java.lang.ClassLoader.loadClass(ClassLoader.java:497) E/AndroidRuntime( 2532): at java.lang.ClassLoader.loadClass(ClassLoader.java:457) E/AndroidRuntime( 2532): at android.app.Instrumentation.newActivity(Instrumentation.java:1061) E/AndroidRuntime( 2532): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2101) E/AndroidRuntime( 2532): ... 11 more W/ActivityManager( 548): Force finishing activity track.android.debug/track.android.MainActivity

getStepsCount() & getDailyDistanceSamples() always returns no data.

I've got an issue with getting any steps from my account. I've authorized google fit, added signatures to firebase etc. but when I try to get steps using one of provided methods I am getting empty array or message that there is no steps data available at current time (event when i try to set time for last week or more). I've checked my fit data via web (http://fit.google.com) and there are plenty of samples, but I can't figure out what am I doing wrong.

any help maybe? I am using google play services 9.8.0, tested on physical device running on android 6.0.

getDailyCalorieSamples and BMR

I've been looking at this great library, so far so good. I have a question regarding getDailyCalorieSamples. It appears in the source code that BMR is being deducted from the calorie values, but actually it isn't. Some very brief research suggests that the AGGREGATE_BASAL_METABOLIC_RATE_SUMMARY data does not work, and by logging some additional data to console verifies this, it just returns empty datasets. Is it worth removing this from the source? It could cause future confusion if it gets fixed unexpectedly.

isEnabled() returns false

I don't know which factors influence the isEnabled() result (and what it means exactly), can anyone give me a hint? I also can't find any documentation really besides the readme

Calorie Data Mismatch

this issue is most likely not related to this library, but probably due to the Google Fit API

Has anyone encountered a data mismatch of the calorie data coming from Google Fit API and the calorie data shown in the Google Fit app? Is Google Fit adding extra inactive calorie data based on demographics? How is everyone's experience with calorie data?

Crashing after adding another library

I had to change my package name and application id of the project. I have updated the values on the Google API console and Android project (manifest & gradle files). But I am getting this error when I am trying to authorize the SDK:

screenshot_20180517-184901

How to access the access token from GoogleApiClient for connecting with REST Api

Hi,

I am trying to fetch the access token on the android device after the user authorise and then send this access token to my backend server so that we can fetch steps data using Google Fit Rest API.

I have tried this code to get the token after the connection is established:

// in GoogleFitManager inside **onConnected** callback
GoogleSignInAccount gsa = GoogleSignIn.getAccountForScopes(mReactContext.getApplicationContext(), new Scope(Scopes.FITNESS_ACTIVITY_READ));
new RetrieveTokenTask().execute(gsa.getEmail());

// --------------- //
private class RetrieveTokenTask extends AsyncTask<String, Void, String> {

        @Override
        protected String doInBackground(String... params) {
            String token = null;
            String accountName = params[0];
            String scopes = "oauth2:https://www.googleapis.com/auth/fitness.activity.read";
            try {
                token = GoogleAuthUtil.getToken(mActivity.getApplicationContext(), accountName, scopes);
            } catch (IOException e) {
                Log.e(TAG, "IOException");
                Log.e(TAG, e.getMessage());
            } catch (UserRecoverableAuthException e) {
                Log.e(TAG, "User recoverable auth exception");
                Log.e(TAG, e.getMessage());
            } catch (GoogleAuthException e) {
                Log.e(TAG, "Google auth exception");
                Log.e(TAG, e.toString());
            }
            return token;
        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            Log.d(TAG, "GOOGLE FIT TOKEN: " + s);
        }
    }

My problem is getEmail() is always returning default-account as value (not the actual email address used) which is causing the getToken call to fail. If I hard code account name to my email id then this works and I can access data using the Rest API. But I cannot get the user's email id this way.

Is there anyway to access the email id or the access token from the GoogleApiClient ?

Thanks

googleFit.authorize does not fire its callback

It tested it using just this snippet:

googleFit.authorize(() => console.log('Callback fired'))

It did not log that.

I already checked the index.android.js and tried something like this:

authorize(callback) {
        googleFit.authorize(
          msg => callback(msg, false),
          res => callback(false, res)
        );
callback('I should never get here.)
    }

and 'I should never get here' got logged to the console.

As I am not a Java dev, I did not dig deeper into the native code. It seems that the problem is on the Java side because googleFit.authorizefrom the index.android.js calls a native method right?

BuildToolsVersion compatibility with RN 0.56

The following needs to be upgraded to work with RN 0.56:

buildToolsVersion = "26.0.3"
minSdkVersion = 16
compileSdkVersion = 26
targetSdkVersion = 26
supportLibVersion = "26.1.0"

the app on PlayStore is able to connect to fit

My react native app is able to connect to google fit in release/debug mode (deploy directly to phone / through crashlytics )

But when I uploaded to to store and download from the phone, the box asking Allow/Deny does not appear.

Even stranger that if i downloaded the apk from console and install it directly it works.

Get steps from Google Account without having the Google Fit App

Heya,

I've been implementing your library and I've noticed you've got a start recording functionality.
I was wondering: if you don't have the Google Fit app itself and you are recording using:

GoogleFit.startRecording((callback) => {
  // Process data from Google Fit Recording API (no google fit app needed)
});

Will this pull all the steps from the associated Google Account using the API? Or just the steps recorded from the local device from this moment forwards? From my testing it seems the latter is the most likely.

Failed Authorization

Hi,

I am getting following error:

RNGoogleFit: Authorization - Failed Authorization Mgr:ConnectionResult{statusCode=SIGN_IN_REQUIRED, resolution=PendingIntent{b70bd65: android.os.BinderProxy@ef1db09}, message=null}`

startResolutionForResult() is being called and I can click on my google account to sign in but onActivityResult() always receives RESULT_CANCELED.

I am still quite new in react native and would really appreciate some help :)
Thank you

Error: Fragments should be static such that they can be re-instantiated by the system, and anonymous classes are not static [ValidFragment]

/node_modules/react-native-google-fit/android/src/main/java/com/reactnative/googlefit/GoogleFitManager.java:220: Error: Fragments should be static such that they can be re-instantiated by the system, and anonymous classes are not static [ValidFragment]
ErrorDialogFragment dialogFragment = new ErrorDialogFragment() {
~~~~~~~~~~~~~~~~~~~

Explanation for issues of type "ValidFragment":
From the Fragment documentation:
Every fragment must have an empty constructor, so it can be instantiated
when restoring its activity's state. It is strongly recommended that
subclasses do not have other constructors with parameters, since these
constructors will not be called when the fragment is re-instantiated;
instead, arguments can be supplied by the caller with setArguments(Bundle)
and later retrieved by the Fragment with getArguments().

What is APPLICATION_ID ?

Hey Man,

Good job for this well done library. I want to use it in my android project but at first I want to know what is the APPLICATION_ID that you mentioned in your documentation ?
Is that CLIENT_ID that we can get it with your link which mentioned in usage doc section ?

  • Dude please reform your documentation and usage instructions. Because I think it is not complete yet and this is only repository which exist in the community yet. Please take care of it ;)

startRecording working but ObserveSteps not working

After Authorize, I am able to get daily steps count data using getDailyStepCountSamples, But not able to get real-time steps count with observeSteps.

When I call startRecording, the callback is invoked with steps recording & inside the callback I am calling observeSteps.

Pedometer.startRecording(this.startAndroidStepRecording)
startAndroidStepRecording(type) {
    if (type != 'steps') return
    this.dispatch({ type: 'RH.Pedometer.Live.Callback', payload: { type } })
    Pedometer.observeSteps(this.observeStepsCallback)
  }

I have been observing LOGs from the Native code as well and I see no step count data received. I only see

RecordingApi: RecordingAPI - Connected
StepCounter: Register Fitness Listener: DataType{com.google.step_count.delta[steps(i)]}
StepCounter: Register Fitness Listener: DataType{com.google.step_count.cumulative[steps(i)]}
StepCounter: SensorApi successfully added
StepCounter: SensorApi successfully added

"Choose account" prompt not working

Hi,

I am having an issue when calling GoogleFit.authorizeFit(). The prompt to choose account shows up without any issues, however when trying to select the account, the prompt goes away and then shows up again after 1 second.

Here's the picture of what I am seeing:
screen shot 2017-03-09 at 4 29 59 pm

Has anyone experienced this problem? Thanks!

disconnect() function is not working okay

After invoking disconnect method isAuthorized and authorize is not working correctly.

HTC:

  1. Invoke authorize
  2. Invoke disconnect
  3. Invoke authorize

Expected result:

See android prompt with Google Account choosing.

Actual result:

Nothing happens because isAuthorized returns true

get activity types

Is it possible to get the type of activity with the distance sample?
I want to make a difference between e.g. a 5km walk, or a 10km run.

Thanks!

Using react-native-google-fit with Google Fit SDK

Hello again,

I tried to include the Google Fit SDK with my project and now I'm getting some errors when trying to interact with this package:

node_modules\react-native-google-fit\android\src\main\java\com\reactnative\googlefit\GoogleFitManager.java:40: error: GoogleFitManager is not abstract and does not override abstract method 

onActivityResult(int,int,Intent) in ActivityEventListener
public class GoogleFitManager implements
       
node_modules\react-native-googlefit\android\src\main\java\com\reactnative\googlefit\GoogleFitManager.java:197: error: method does not override or implement a method
from a supertype
    @Override
    
node_modules\react-native-google-fit\android\src\main\java\com\reactnative\googlefit\GoogleFitManager.java:212: error: method does not override or implement a method
from a supertype
    @Override
    
3 errors
:react-native-google-fit:compileReleaseJavaWithJavac FAILED

The lines referenced are:

40: public class GoogleFitManager implements
        ActivityEventListener {
...
197: @Override
    public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
...
212:  @Override
    public void onNewIntent(Intent intent) {
    } 

I assume that if react-native-google-fit can communicate with the Google Fit App when I have it installed it should also be able to communicate with the SDK in much the same way. Do you know how I can fix this? If pointed in the right direction I could try to make a PR.

Thanks.

observeSteps() not working

This is the code in the main screen of my RN app

componentDidMount() {    
        GoogleFit.isEnabled( () => {
            GoogleFit.authorize();

            GoogleFit.observeSteps((steps)=>{
                Reactotron.log(steps)
            });
            const options = {
                startDate: "2017-01-01T00:00:17.971Z",  // required ISO8601Timestamp
                endDate: (new Date()).toISOString()     // required ISO8601Timestamp
            };
            GoogleFit.getDailyStepCountSamples(options, (err, res) => {
                if (err) {
                    throw err;
                }
                Reactotron.log(res);
            })
        }) 
}

I receive the log from getDailyStepCountSamples() but observeSteps() doesn't give signs of life.

Why the authorization with OAuth 2.0 is needed?

From the developers Google doc (https://developers.google.com/android/guides/api-client) I read that authorizing with OAuth 2.0 is mainly needed for using Google Rest API, when you want the app to access Google APIs with the user's Google account over HTTP.

So, I would like to know why the installation of this module requires the authorization with OAuth 2.0? Does this module make use of the Google Rest API?

I hope to receive reply to this and previous issues, please.

Attempt to Invoke virtual method - Error

Hello,
I'm sure it's something I'm overlooking, but I am getting this error and Not sure how to resolve it.
Exception in native call java.lang.NullPointerException: Attempt to invoke virtual method 'com.reactnative.googlefit.StepHistory com.reactnative.googlefit.GoogleFitManager.getStepHistory()' on a null object reference
at com.reactnative.googlefit.GoogleFitModule.getDailySteps(GoogleFitModule.java:105)
at java.lang.reflect.Method.invoke(Native Method)

My code:
let dayStart = "2017-01-01T00:00:17.971Z"; //ISO Time String
let dayEnd = "2017-01-01T23:59:17.971Z"; //ISO Time String
GoogleFit.getSteps(dayStart, dayEnd);

Any help is much appreciated

UnsubscribeListeners serious issue

The method for unsubscribing to the listeners has two issues:

  1. Name is misspelled (usubscribe -> unsubscribe)
  2. SERIOUS: the method removes ALL of the DeviceEventEmitter listeners - this leads to tons of issues with the development process - hot reloading stops working, navigation events are lost, etc. A lot of React Native code depends on these listeners so they should not be removed.

Our proposal is to keep all listener instances and use the .remove() method on all of them when the method is called.
We will try to provide a PR in the next days to fix this.

Filter manual entered data

We are developing an App which give you "Coins" when you reached an achievement. You can manually enter steps in Google Fit. Is it possible to filter out this manual entered data.

Unable to resolve dependencies

After adding the package I can't build the project. Error:

A problem occurred configuring project ':app'.
> Could not resolve all dependencies for configuration ':app:_debugApk'.
   > A problem occurred configuring project ':react-native-google-fit'.
      > Could not resolve all dependencies for configuration ':react-native-google-fit:_debugPublishCopy'.
         > Could not find com.google.android.gms:play-services-auth:11.6.0.
           Searched in the following locations:
               file:/Users/wojciech/Library/Android/sdk/extras/google/m2repository/com/google/android/gms/play-services-auth/11.6.0/play-services-auth-11.6.0.pom
               file:/Users/wojciech/Library/Android/sdk/extras/google/m2repository/com/google/android/gms/play-services-auth/11.6.0/play-services-auth-11.6.0.jar
               file:/Users/wojciech/Documents/dev/uni/swifty-app/Swifty/android/sdk-manager/com/google/android/gms/play-services-auth/11.6.0/play-services-auth-11.6.0.jar
               file:/Users/wojciech/Library/Android/sdk/extras/android/m2repository/com/google/android/gms/play-services-auth/11.6.0/play-services-auth-11.6.0.pom
               file:/Users/wojciech/Library/Android/sdk/extras/android/m2repository/com/google/android/gms/play-services-auth/11.6.0/play-services-auth-11.6.0.jar
               file:/Users/wojciech/Documents/dev/uni/swifty-app/Swifty/android/sdk-manager/com/google/android/gms/play-services-auth/11.6.0/play-services-auth-11.6.0.jar
           Required by:
               Swifty:react-native-google-fit:unspecified
         > Could not find com.google.android.gms:play-services-fitness:11.6.0.
           Searched in the following locations:
               file:/Users/wojciech/Library/Android/sdk/extras/google/m2repository/com/google/android/gms/play-services-fitness/11.6.0/play-services-fitness-11.6.0.pom
               file:/Users/wojciech/Library/Android/sdk/extras/google/m2repository/com/google/android/gms/play-services-fitness/11.6.0/play-services-fitness-11.6.0.jar
               file:/Users/wojciech/Documents/dev/uni/swifty-app/Swifty/android/sdk-manager/com/google/android/gms/play-services-fitness/11.6.0/play-services-fitness-11.6.0.jar
               file:/Users/wojciech/Library/Android/sdk/extras/android/m2repository/com/google/android/gms/play-services-fitness/11.6.0/play-services-fitness-11.6.0.pom
               file:/Users/wojciech/Library/Android/sdk/extras/android/m2repository/com/google/android/gms/play-services-fitness/11.6.0/play-services-fitness-11.6.0.jar
               file:/Users/wojciech/Documents/dev/uni/swifty-app/Swifty/android/sdk-manager/com/google/android/gms/play-services-fitness/11.6.0/play-services-fitness-11.6.0.jar
           Required by:
               Swifty:react-native-google-fit:unspecified

I'd appreciate quick reply

getDailyStepCountSamples() callback is called multiple times and it slows down the app

When getDailyStepCountSamples() is called I see that its callback is called multiple times; a simple console.log() inside of it is executed three or four times

GoogleFit.isEnabled(() => {
                    GoogleFit.startRecording((callback) => {
                        const options = {
                            startDate: "2017-01-01T00:00:17.971Z", // required ISO8601Timestamp
                            endDate: (new Date(Date.now() - (new Date()).getTimezoneOffset() * 60000)).toISOString() // required ISO8601Timestamp
                        };
                        
                        GoogleFit.getDailyStepCountSamples(options, (err, res) => {
                            if (err) {
                                throw err;
                            }
                            console.log("GETDAILYSTEPCOUNT")
                            return
                        });
                    });
                });

It terribly slows down the app, in particular if you have inside getDailyStepCountSamples() some redux actions

TypeError: expected dynamic type double

Hi - I've been pulling my hair off over an issue I recently came around, and I would like some input from anyone who may be able to help.

So basically, when I am not debugging the application, I get the following error:

TypeError: expected dynamic type double, but had type null (constructing arguments for RNGoogleFit.getDailyStepCountSamples at argument index 0). You can see the screenshot here.

It's pretty annoying because when I run the app in debug mode (i.e. JS debug mode), I don't get the same error. Am I missing something?

This is how I am using the library:

import GoogleFit from 'react-native-google-fit';

function getDataForDates(begin, end, cb) {
  GoogleFit.getDailyStepCountSamples({
        startDate: new Date(begin).toString(),
        endDate: new Date(end).toString(),
      }, (err, results) => {
        if (err) {
          return cb(null, 0);
        }
        
        let steps = 0;
        
        for (const item of results) {
          if (item.steps.length > 0) {
            steps += item.steps[0];
          }
        }

        return cb(null, steps);
      });
}

GoogleFit.authorize() calls first onAuthorizeFailure and afterwards onAuthorize

On a recent project I saw that GoogleFit.authorize()
immediately calls onAuthorizeFailure and later on when the connection is established onAuthorize

I took a look to the implementation. I saw that it uses the deprecated GoogleApiClient. Furthermore events are added to call the JavaScript callback and you might end up with multiple callbacks.

The addOnConnectionFailedListener is the native method which fires too early.

It might be possible to check on the ConnectionResult in method onConnectionFailed(ConnectionResult result) to find a workaround.

But it would also be good to implement a real callback and not listen to the native events.

GoogleFitManager.java override issue

Hello,

I have tried to implement your library in react-native. I am using the following packages:

  • react: 16.3.0
  • react-native: 0.54.4
  • react-native-google-fit: 0.5.2

When trying to compile the project the following issues occurred in GoogleFitManager.java


GoogleFitManager.java:40: error: GoogleFitManager is not abstract and does not override abstract method onActivityResult(int,int,Intent) in ActivityEventListener

GoogleFitManager.java:199: error: method does not override or implement a method from a supertype

GoogleFitManager.java:214: error: method does not override or implement a method from a supertype

It seems like the GoogleFItManager class is trying to override an older version of ActivityEventListener.

I have looked into the library of react-native and was unable to identify why this error occurs, but it does seem to originate from there.

is this work on ios

I want to know that is this work on ios and also how can I implement running process like start and end button

java.lang.RuntimeException: Could not invoke RNGoogleFit.authorize

After I've installed react-native-maps package, despite the build is successful, application just stoped work with an exception.

Couldn't open the File - /data/system/users/0/personalist.xml - No such file or directory
09-10 11:53:19.712 16604-16959/com.myapp E/unknown:ReactNative: Exception in native call
    java.lang.RuntimeException: Could not invoke RNGoogleFit.authorize
        at com.facebook.react.bridge.JavaMethodWrapper.invoke(JavaMethodWrapper.java:383)
        at com.facebook.react.bridge.JavaModuleWrapper.invoke(JavaModuleWrapper.java:160)
        at com.facebook.react.bridge.queue.NativeRunnable.run(Native Method)
        at android.os.Handler.handleCallback(Handler.java:789)
        at android.os.Handler.dispatchMessage(Handler.java:98)
        at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:29)
        at android.os.Looper.loop(Looper.java:164)
        at com.facebook.react.bridge.queue.MessageQueueThreadImpl$3.run(MessageQueueThreadImpl.java:192)
        at java.lang.Thread.run(Thread.java:764)
     Caused by: java.lang.reflect.InvocationTargetException
        at java.lang.reflect.Method.invoke(Native Method)
        at com.facebook.react.bridge.JavaMethodWrapper.invoke(JavaMethodWrapper.java:372)
        at com.facebook.react.bridge.JavaModuleWrapper.invoke(JavaModuleWrapper.java:160) 
        at com.facebook.react.bridge.queue.NativeRunnable.run(Native Method) 
        at android.os.Handler.handleCallback(Handler.java:789) 
        at android.os.Handler.dispatchMessage(Handler.java:98) 
        at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:29) 
        at android.os.Looper.loop(Looper.java:164) 
        at com.facebook.react.bridge.queue.MessageQueueThreadImpl$3.run(MessageQueueThreadImpl.java:192) 
        at java.lang.Thread.run(Thread.java:764) 
     Caused by: java.lang.NoClassDefFoundError: Failed resolution of: Lcom/google/android/gms/fitness/request/OnDataPointListener;
        at com.reactnative.googlefit.GoogleFitModule.authorize(GoogleFitModule.java:75)
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.facebook.react.bridge.JavaMethodWrapper.invoke(JavaMethodWrapper.java:372) 
        at com.facebook.react.bridge.JavaModuleWrapper.invoke(JavaModuleWrapper.java:160) 
        at com.facebook.react.bridge.queue.NativeRunnable.run(Native Method) 
        at android.os.Handler.handleCallback(Handler.java:789) 
        at android.os.Handler.dispatchMessage(Handler.java:98) 
        at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:29) 
        at android.os.Looper.loop(Looper.java:164) 
        at com.facebook.react.bridge.queue.MessageQueueThreadImpl$3.run(MessageQueueThreadImpl.java:192) 
        at java.lang.Thread.run(Thread.java:764) 
     Caused by: java.lang.ClassNotFoundException: Didn't find class "com.google.android.gms.fitness.request.OnDataPointListener" on path: DexPathList[[zip file "/data/app/com.myapp-zNOyxL_4OhdJigH7nWT8oA==/base.apk"],nativeLibraryDirectories=[/data/app/com.myapp-zNOyxL_4OhdJigH7nWT8oA==/lib/arm, /data/app/com.myapp-zNOyxL_4OhdJigH7nWT8oA==/base.apk!/lib/armeabi-v7a, /system/lib, /system/vendor/lib]]
        at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:93)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
        at com.reactnative.googlefit.GoogleFitModule.authorize(GoogleFitModule.java:75) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.facebook.react.bridge.JavaMethodWrapper.invoke(JavaMethodWrapper.java:372) 
        at com.facebook.react.bridge.JavaModuleWrapper.invoke(JavaModuleWrapper.java:160) 
        at com.facebook.react.bridge.queue.NativeRunnable.run(Native Method) 
        at android.os.Handler.handleCallback(Handler.java:789) 
        at android.os.Handler.dispatchMessage(Handler.java:98) 
        at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:29) 
        at android.os.Looper.loop(Looper.java:164) 
        at com.facebook.react.bridge.queue.MessageQueueThreadImpl$3.run(MessageQueueThreadImpl.java:192) 
        at java.lang.Thread.run(Thread.java:764) 

Tested on real devices: Samsung s9, Samsung s7, Huawei Honor 9. Android 7, 8.
I happens on both: dev and release mode, And it happens only if you have installed GoogleFit app on your phone.

my android/build.gradle:

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
        google()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.1.2'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        mavenLocal()
        jcenter()
        maven {
            // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
            url "$rootDir/../node_modules/react-native/android"
        }
        maven {
            url "https://maven.google.com"
            name 'Google'
        }
        maven { url "https://jitpack.io" }
        google()
    }
}

subprojects {
    afterEvaluate {project ->
        if (project.hasProperty("android")) {
            android {
                compileSdkVersion 27
                buildToolsVersion "27.0.3"
            }
        }
    }
}

ext {
    buildToolsVersion = "26.0.3"
    minSdkVersion = 16
    compileSdkVersion = 26
    targetSdkVersion = 26
    supportLibVersion = "27+"
}

and android/app/build.gralde:

apply plugin: "com.android.application"

import com.android.build.OutputFile

project.ext.react = [
    entryFile: "index.js"
]

apply from: "../../node_modules/react-native/react.gradle"

def enableSeparateBuildPerCPUArchitecture = false

/**
 * Run Proguard to shrink the Java bytecode in release builds.
 */
def enableProguardInReleaseBuilds = false

android {
    compileSdkVersion rootProject.ext.compileSdkVersion
    buildToolsVersion rootProject.ext.buildToolsVersion

    defaultConfig {
        applicationId "com.myapp"
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionCode 1
        versionName "1.0"
        multiDexEnabled = true
        ndk {
            abiFilters "armeabi-v7a", "x86"
        }
    }
    signingConfigs {
        release {
            if (project.hasProperty('MYAPP_RELEASE_STORE_FILE')) {
                storeFile file(MYAPP_RELEASE_STORE_FILE)
                storePassword MYAPP_RELEASE_STORE_PASSWORD
                keyAlias MYAPP_RELEASE_KEY_ALIAS
                keyPassword MYAPP_RELEASE_KEY_PASSWORD
            }
        }
    }
    splits {
        abi {
            reset()
            enable enableSeparateBuildPerCPUArchitecture
            universalApk false  // If true, also generate a universal APK
            include "armeabi-v7a", "x86"
        }
    }
    buildTypes {
        release {
            minifyEnabled enableProguardInReleaseBuilds
            proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
            signingConfig signingConfigs.release
        }
    }
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            def versionCodes = ["armeabi-v7a":1, "x86":2]
            def abi = output.getFilter(OutputFile.ABI)
            if (abi != null) {  // null for the universal-debug, universal-release variants
                output.versionCodeOverride =
                        versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
            }
        }
    }
}

buildscript {
  repositories {
    maven { url 'https://maven.fabric.io/public' }
  }
  dependencies {
    // The Fabric Gradle plugin uses an open ended version to react
    // quickly to Android tooling updates
    classpath 'io.fabric.tools:gradle:1.+'
  }
}

apply plugin: 'io.fabric'

repositories {
    maven { url 'https://maven.fabric.io/public' }
}

dependencies {
    compile project(':react-native-check-app-install')
    compile (project(':react-native-camera')) {
        exclude group: "com.google.android.gms"
        exclude group: "com.android.support"
    }
    compile project(':react-native-fabric')
    compile project(':react-native-picker')
    compile project(':react-native-image-sequence')
    compile project(':react-native-google-fit')
    compile project(':react-native-webview-android')
    compile 'com.android.support:multidex:1.0.0'
    compile project(':react-native-vector-icons')
    compile project(':react-native-i18n')
    compile project(':react-native-pdf')
    compile project(':react-native-fetch-blob')
    compile project(':react-native-svg')
    compile project(':react-native-splash-screen')
    compile(project(':react-native-device-info')) {
        exclude group: 'com.google.android.gms'
    }
    compile project(':react-native-maps')

    compile fileTree(dir: "libs", include: ["*.jar"])
    compile "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
    compile "com.facebook.react:react-native:+"  // From node_modules
    compile('com.crashlytics.sdk.android:crashlytics:2.9.4@aar') {
        transitive = true;
    }

    compile "com.google.android.gms:play-services-base:+"
    compile "com.google.android.gms:play-services-maps:+"
}

task copyDownloadableDepsToLibs(type: Copy) {
    from configurations.compile
    into 'libs'
}

Way to check if already authorized?

Is there a way to check if the App is already authorized without calling GoogleFit.authorize()?
I want to let the user choose to enable access by clicking a button and not display that button if already authorized.

0.5.0 keep crash

android app keep crash on loading without any error message.

react-native-google-fit: 0.5.0
react-native: 0.44.0

Saving Google Fit Data

Hello,

I've started to use your library and I'm excited to get it started. At the moment, I am trying to save the Google fit data from the request I am making.

Here's what I'm doing:

let todayStart = "2017-02-23T00:00:17.971Z"
let dayEnd = "2017-02-23T23:59:17.971Z"
GoogleFit.getSteps(todayStart, dayEnd)

In my Android monitor, I see:

I/History: Number of buckets: 1
I/History: Data returned for Data type: com.google.step_count.delta
I/History: Data point:
I/History: 	Type: com.google.step_count.delta
I/History: 	Start: 23 Feb 2017 9:33:06 am
I/History: 	End: 23 Feb 2017 9:33:06 am
I/History: Day: Thu
I/History: 	Field: steps Value: 196

So it seems to be working. However, how do I store this info? If I save GoogleFit.getSteps(todayStart, dayEnd) to a variable, I just get undefined.

Hope you can help.

Thanks!

burned calories

Hi!
First of all let me thanks for your great work!

I am wondering if it possible to obtain burned calories info from google fit? If so - how? If not - would you consider adding it?

Observe History returns empty Array always

I am trying to get the history for steps count, but every time it returns an empty array, as i am using it since the morning, it should return the steps i walked till now.
Below is my code:
` const dayStart = '2017-01-01T00:00:17.971Z';
const dayEnd = (new Date()).toISOString();

GoogleFit.getSteps(dayStart, dayEnd);
GoogleFit.observeHistory((results) => {
  console.log(results);
});`

results is an empty array

getDailyStepCountSamples not works in release mode

hi guys, i have a problem and this is when i work with rn-google-fit in develop mode (node localserver) i have no problem and every thing is working. but when i release my app and generate signedApk, google auth modal is open but nothing occur and app crashes.
why?
please help me,
sorry for my bad english :(

onAuthorizeFailure always triggered when authorizing google fit

Hi,

It seems like the event onAuthorizeFailure is always triggered.

I'm using the README code:

GoogleFit.onAuthorize(() => {
  console.log('success');
});

GoogleFit.onAuthorizeFailure(() => {
  console.log('failure');
});

GoogleFit.authorize();

When I am authorizing Google fit, either on simulator or real device, the failure event is always triggered, right after calling authorize (while there is still the account selection modal).

Note that onAuthorize is triggered when I select my account, so the success case is handled. I was wondering if I am doing something wrong, or if the error handling has an issue.

Compile error

After updating the package to 0.7.0 in my project I see the error when ./gradlew assembleRelease:

> Task :react-native-google-fit:compileDebugJavaWithJavac FAILED
/Users/dmitriisalenko/projects/xendera-enterprise/node_modules/react-native-google-fit/android/src/main/java/com/reactnative/googlefit/GoogleFitManager.java:173: error: cannot find symbol
        GoogleSignInAccount gsa = GoogleSignIn.getAccountForScopes(mReactContext, new Scope(Scopes.FITNESS_ACTIVITY_READ));
                                              ^
  symbol:   method getAccountForScopes(ReactContext,Scope)
  location: class GoogleSignIn
1 error


FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':react-native-google-fit:compileDebugJavaWithJavac'.
> Compilation failed; see the compiler error output for details.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.