Как получить источник данных для подсчета шагов с помощью Google Fit Android API?
Я пытаюсь использовать Google Fit API для подсчета шагов в моем приложении. Но я не получаю никаких источников данных, кроме Location. Как получить источник данных для подсчета шагов? Прошло уже более 4 дней, я застрял в этом. Пожалуйста, помогите мне с этим. Благодарю. Ниже приведен код, который я использую
public class Home extends BaseActivity {
private static String TAG = "HOME Activity";
private static final int REQUEST_OAUTH = 1;
/**
* Track whether an authorization activity is stacking over the current activity, i.e. when
* a known auth error is being resolved, such as showing the account chooser or presenting a
* consent dialog. This avoids common duplications as might happen on screen rotations, etc.
*/
private static final String AUTH_PENDING = "auth_state_pending";
private boolean authInProgress = false;
private GoogleApiClient mClient = null;
private OnDataPointListener mListener;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
if (savedInstanceState != null) {
authInProgress = savedInstanceState.getBoolean(AUTH_PENDING);
}
buildFitnessClient();
}
private void findFitnessDataSources() {
// [START find_data_sources]
Fitness.SensorsApi.findDataSources(mClient, new DataSourcesRequest.Builder()
// At least one datatype must be specified.
.setDataTypes(DataType.TYPE_STEP_COUNT_DELTA).setDataTypes(DataType.TYPE_STEP_COUNT_CADENCE).setDataTypes(DataType.TYPE_LOCATION_SAMPLE)
// Can specify whether data type is raw or derived.
.setDataSourceTypes(DataSource.TYPE_RAW)
.build())
.setResultCallback(new ResultCallback<DataSourcesResult>() {
@Override
public void onResult(DataSourcesResult dataSourcesResult) {
Log.v("Inside", "Callback");
Log.i(TAG, "Result: " + dataSourcesResult.getStatus().toString());
Log.v("Len", dataSourcesResult.getDataSources().size() + "");
for (DataSource dataSource : dataSourcesResult.getDataSources()) {
Log.i(TAG, "Data source found: " + dataSource.toString());
Log.i(TAG, "Data Source type: " + dataSource.getDataType().getName());
//Let's register a listener to receive Activity data!
if (dataSource.getDataType().equals(DataType.TYPE_STEP_COUNT_CADENCE)
&& mListener == null) {
Log.i(TAG, "Data source for STEP found! Registering.");
registerFitnessDataListener(dataSource,
DataType.TYPE_STEP_COUNT_CADENCE);
}
}
}
});
// [END find_data_sources]
}
private void registerFitnessDataListener(DataSource dataSource, DataType dataType) {
// [START register_data_listener]
mListener = new OnDataPointListener() {
@Override
public void onDataPoint(DataPoint dataPoint) {
for (Field field : dataPoint.getDataType().getFields()) {
Value val = dataPoint.getValue(field);
Log.i(TAG, "Detected DataPoint field: " + field.getName());
Log.i(TAG, "Detected DataPoint value: " + val);
}
}
};
Fitness.SensorsApi.add(
mClient,
new SensorRequest.Builder()
.setDataSource(dataSource) // Optional but recommended for custom data sets.
.setDataType(dataType) // Can't be omitted.
.setSamplingRate(1, TimeUnit.SECONDS)
.build(),
mListener)
.setResultCallback(new ResultCallback<Status>() {
@Override
public void onResult(Status status) {
if (status.isSuccess()) {
Log.i(TAG, "Listener registered!");
} else {
Log.i(TAG, "Listener not registered.");
}
}
});
// [END register_data_listener]
}
private void buildFitnessClient() {
// Create the Google API Client
mClient = new GoogleApiClient.Builder(this)
.addApi(Fitness.SENSORS_API).addApi(Fitness.RECORDING_API).addApi(Fitness.SESSIONS_API)
.addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE)).addScope(Fitness.SCOPE_ACTIVITY_READ_WRITE).addScope(Fitness.SCOPE_BODY_READ_WRITE)
.addConnectionCallbacks(
new GoogleApiClient.ConnectionCallbacks() {
@Override
public void onConnected(Bundle bundle) {
Log.i(TAG, "Connected!!!");
// Now you can make calls to the Fitness APIs.
// Put application specific code here.
findFitnessDataSources();
// makeFitnessAPIRequest();
}
@Override
public void onConnectionSuspended(int i) {
// If your connection to the sensor gets lost at some point,
// you'll be able to determine the reason and react to it here.
if (i == GoogleApiClient.ConnectionCallbacks.CAUSE_NETWORK_LOST) {
Log.i(TAG, "Connection lost. Cause: Network Lost.");
} else if (i == GoogleApiClient.ConnectionCallbacks.CAUSE_SERVICE_DISCONNECTED) {
Log.i(TAG, "Connection lost. Reason: Service Disconnected");
}
}
}
)
.addOnConnectionFailedListener(
new GoogleApiClient.OnConnectionFailedListener() {
// Called whenever the API client fails to connect.
@Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "Connection failed. Cause: " + result.toString());
if (!result.hasResolution()) {
// Show the localized error dialog
GooglePlayServicesUtil.getErrorDialog(result.getErrorCode(),
Home.this, 0).show();
return;
}
// The failure has a resolution. Resolve it.
// Called typically when the app is not yet authorized, and an
// authorization dialog is displayed to the user.
if (!authInProgress) {
try {
Log.i(TAG, "Attempting to resolve failed connection");
authInProgress = true;
result.startResolutionForResult(Home.this,
REQUEST_OAUTH);
} catch (IntentSender.SendIntentException e) {
Log.e(TAG,
"Exception while starting resolution activity", e);
}
}
}
}
)
.build();
}
private void makeFitnessAPIRequest() {
SensorRequest request = new SensorRequest.Builder().setDataType(DataType.TYPE_STEP_COUNT_DELTA)
.setSamplingRate(1, TimeUnit.SECONDS).build();
PendingResult<Status> reqResult = Fitness.SensorsApi.add(mClient, request, mListener);
}
@Override
protected void onStart() {
super.onStart();
// Connect to the Fitness API
Log.i(TAG, "Connecting...");
mClient.connect();
}
@Override
protected void onStop() {
super.onStop();
if (mClient.isConnected()) {
mClient.disconnect();
}
Log.v("Inside", "Stop");
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_OAUTH) {
authInProgress = false;
if (resultCode == RESULT_OK) {
// Make sure the app is not already connected or attempting to connect
if (!mClient.isConnecting() && !mClient.isConnected()) {
mClient.connect();
Log.v("Inside", "connect");
}
}
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(AUTH_PENDING, authInProgress);
}
/**
* Unregister the listener with the Sensors API.
*/
private void unregisterFitnessDataListener() {
if (mListener == null) {
// This code only activates one listener at a time. If there's no listener, there's
// nothing to unregister.
return;
}
// [START unregister_data_listener]
// Waiting isn't actually necessary as the unregister call will complete regardless,
// even if called from within onStop, but a callback can still be added in order to
// inspect the results.
Fitness.SensorsApi.remove(
mClient,
mListener)
.setResultCallback(new ResultCallback<Status>() {
@Override
public void onResult(Status status) {
if (status.isSuccess()) {
Log.i(TAG, "Listener was removed!");
} else {
Log.i(TAG, "Listener was not removed.");
}
}
});
// [END unregister_data_listener]
}
}
4 ответа
Это работает для меня, если кто-то застрял, используйте это ----
Инициализируйте объект FitnessClient следующим образом:
private void buildFitnessClient() {
if (mClient == null && checkPermissions()) {
mClient = new GoogleApiClient.Builder(this)
.addApi(Fitness.SENSORS_API)
.addScope(new Scope(Scopes.FITNESS_LOCATION_READ))
.addConnectionCallbacks(
new GoogleApiClient.ConnectionCallbacks() {
@Override
public void onConnected(Bundle bundle) {
Log.i(TAG, "Connected!!!");
// Now you can make calls to the Fitness APIs.
findFitnessDataSources();
}
Теперь определите тип данных, который вы хотите получить как обратный вызов, который мы должны установить как DataType.TYPE_STEP_COUNT_DELTA, следующим образом:
private void findFitnessDataSources() {
// [START find_data_sources]
// Note: Fitness.SensorsApi.findDataSources() requires the ACCESS_FINE_LOCATION permission.
Fitness.SensorsApi.findDataSources(mClient, new DataSourcesRequest.Builder()
// At least one datatype must be specified.
.setDataTypes(DataType.TYPE_STEP_COUNT_DELTA)
// Can specify whether data type is raw or derived.
.build())
.setResultCallback(new ResultCallback<DataSourcesResult>() {
@Override
public void onResult(DataSourcesResult dataSourcesResult) {
Log.i(TAG, "Result: " + dataSourcesResult.getStatus().toString());
for (DataSource dataSource : dataSourcesResult.getDataSources()) {
Log.i(TAG, "Data source found: " + dataSource.toString());
Log.i(TAG, "Data Source type: " + dataSource.getDataType().getName());
//Let's register a listener to receive Activity data!
if (dataSource.getDataType().equals(DataType.TYPE_STEP_COUNT_DELTA)
&& mListener == null) {
Log.i(TAG, "Data source for LOCATION_SAMPLE found! Registering.");
registerFitnessDataListener(dataSource,
DataType.TYPE_STEP_COUNT_DELTA);
}
}
}
});
// [END find_data_sources]
}
Теперь зарегистрируйте прослушиватель с помощью API Sensors для предоставленных DataSource и DataType следующим образом:
private void registerFitnessDataListener(DataSource dataSource, DataType dataType) {
// [START register_data_listener]
mListener = new OnDataPointListener() {
@Override
public void onDataPoint(DataPoint dataPoint) {
for (Field field : dataPoint.getDataType().getFields()) {
Value val = dataPoint.getValue(field);
// Value(TotalSteps);
// TotalSteps=val+TotalSteps;
Log.i(TAG, "Detected DataPoint field: " + field.getName());
Log.i(TAG, "Detected DataPoint value: " + val);
}
}
};
Fitness.SensorsApi.add(
mClient,
new SensorRequest.Builder()
.setDataSource(dataSource) // Optional but recommended for custom data sets.
.setDataType(dataType) // Can't be omitted.
.setSamplingRate(1, TimeUnit.SECONDS)
.build(),
mListener)
.setResultCallback(new ResultCallback<Status>() {
@Override
public void onResult(Status status) {
if (status.isSuccess()) {
Log.i(TAG, "Listener registered!");
} else {
Log.i(TAG, "Listener not registered.");
}
}
});
// [END register_data_listener]
}
Также не забудьте отменить регистрацию вашего слушателя:
private void unregisterFitnessDataListener() {
if (mListener == null) {
// This code only activates one listener at a time. If there's no listener, there's
// nothing to unregister.
return;
}
// [START unregister_data_listener]
// Waiting isn't actually necessary as the unregister call will complete regardless,
// even if called from within onStop, but a callback can still be added in order to
// inspect the results.
Fitness.SensorsApi.remove(
mClient,
mListener)
.setResultCallback(new ResultCallback<Status>() {
@Override
public void onResult(Status status) {
if (status.isSuccess()) {
Log.i(TAG, "Listener was removed!");
} else {
Log.i(TAG, "Listener was not removed.");
}
}
});
// [END unregister_data_listener]
}
Хорошо, мой друг. Пожалуйста, попробуйте это. Он еще не считает шаги, но может прочитать тип данных вашего счетчика шагов. Когда я пробовал ваш, у меня была проблема с OAuth с экраном настроек. Я сделал некоторые изменения с вещами addApi.
public class MainActivity extends ActionBarActivity {
public static final String TAG = "BasicSensorsApi";
// [START auth_variable_references]
private static final int REQUEST_OAUTH = 1;
private static final String AUTH_PENDING = "auth_state_pending";
private boolean authInProgress = false;
private GoogleApiClient mClient = null;
// [END auth_variable_references]
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Put application specific code here.
// [END auth_oncreate_setup_beginning]
setContentView(R.layout.activity_main);
// This method sets up our custom logger, which will print all log messages to the device
// screen, as well as to adb logcat.
// [START auth_oncreate_setup_ending]
if (savedInstanceState != null) {
authInProgress = savedInstanceState.getBoolean(AUTH_PENDING);
}
buildFitnessClient();
}
private void buildFitnessClient() {
// Create the Google API Client
mClient = new GoogleApiClient.Builder(this)
.addApi(Fitness.SENSORS_API)
.addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ))
.addScope(new Scope(Scopes.FITNESS_BODY_READ))
.addConnectionCallbacks(
new GoogleApiClient.ConnectionCallbacks() {
@Override
public void onConnected(Bundle bundle) {
Log.i(TAG, "Connected!!!");
// Now you can make calls to the Fitness APIs.
// Put application specific code here.
// [END auth_build_googleapiclient_beginning]
// What to do? Find some data sources!
findFitnessDataSources();
// [START auth_build_googleapiclient_ending]
}
@Override
public void onConnectionSuspended(int i) {
if (i == ConnectionCallbacks.CAUSE_NETWORK_LOST)
{
Log.i(TAG, "Connection lost. Cause: Network
Lost.");
} else if (i ==
ConnectionCallbacks.CAUSE_SERVICE_DISCONNECTED) {
Log.i(TAG, "Connection lost. Reason:
Service Disconnected");
}
}
}
)
.addOnConnectionFailedListener(
new GoogleApiClient.OnConnectionFailedListener() {
// Called whenever the API client fails to connect.
@Override
public void onConnectionFailed(ConnectionResult
result) {
Log.i(TAG, "Connection failed. Cause: " +
result.toString());
if (!result.hasResolution()) {
// Show the localized error dialog
GooglePlayServicesUtil.getErrorDialog(result.getErrorCode(),
MainActivity.this, 0).show();
return;
}
if (!authInProgress) {
try {
Log.i(TAG, "Attempting to resolve failed
connection");
authInProgress = true;
result.startResolutionForResult(MainActivity.this,
REQUEST_OAUTH);
} catch (IntentSender.SendIntentException e)
{
Log.e(TAG,
"Exception while starting
resolution activity", e);
}
}
}
}
)
.build();
}
@Override
protected void onStart() {
super.onStart();
// Connect to the Fitness API
Log.i(TAG, "Connecting...");
mClient.connect();
}
@Override
protected void onStop() {
super.onStop();
if (mClient.isConnected()) {
mClient.disconnect();
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent
data) {
if (requestCode == REQUEST_OAUTH) {
authInProgress = false;
if (resultCode == RESULT_OK) {
if (!mClient.isConnecting() && !mClient.isConnected()) {
mClient.connect();
}
}
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(AUTH_PENDING, authInProgress);
}
private void findFitnessDataSources() {
// [START find_data_sources]
Fitness.SensorsApi.findDataSources(mClient, new
DataSourcesRequest.Builder()
// At least one datatype must be specified.
.setDataTypes(DataType.TYPE_STEP_COUNT_DELTA)
// Can specify whether data type is raw or derived.
.setDataSourceTypes(DataSource.TYPE_DERIVED)
.build())
.setResultCallback(new ResultCallback<DataSourcesResult>() {
@Override
public void onResult(DataSourcesResult dataSourcesResult) {
Log.i(TAG, "Result: " +
dataSourcesResult.getStatus().toString());
for (DataSource dataSource :
dataSourcesResult.getDataSources()) {
Log.i(TAG, "Data source found: " +
dataSource.toString());
Log.i(TAG, "Data Source type: " +
dataSource.getDataType().getName());
if
(dataSource.getDataType().equals(DataType.TYPE_STEP_COUNT_DELTA)
&& mListener == null) {
Log.i(TAG, "Data source for STEP_COUNT_DELTA
found! Registering.");
registerFitnessDataListener(dataSource,
DataType.TYPE_STEP_COUNT_DELTA);
}
}
}
});
// [END find_data_sources]
}
private void registerFitnessDataListener(DataSource dataSource, DataType
dataType) {
// [START register_data_listener]
mListener = new OnDataPointListener() {
@Override
public void onDataPoint(DataPoint dataPoint) {
for (Field field : dataPoint.getDataType().getFields()) {
Value val = dataPoint.getValue(field);
Log.i(TAG, "Detected DataPoint field: " + field.getName());
Log.i(TAG, "Detected DataPoint value: " + val);
}
}
};
Fitness.SensorsApi.add(
mClient,
new SensorRequest.Builder()
.setDataSource(dataSource)
.setDataType(dataType) // Can't be omitted.
.setSamplingRate(10, TimeUnit.SECONDS)
.build(),
mListener)
.setResultCallback(new ResultCallback<Status>() {
@Override
public void onResult(Status status) {
if (status.isSuccess()) {
Log.i(TAG, "Listener registered!");
} else {
Log.i(TAG, "Listener not registered.");
}
}
});
// [END register_data_listener]
}
}
Я столкнулся с той же проблемой
Я решил это, просто изменив
.setDataSourceTypes(DataSource.TYPE_RAW)
в
.setDataSourceTypes(DataSource.TYPE_DERIVED)
Попробуйте изменить это.
Также измените эту строку внутри onDataPointListener
Log.i(TAG, "Detected DataPoint value: " + val);
в
Log.i(TAG, "Detected DataPoint value: " + val.asInt());
Вы получите счетчик шагов, но со мной это смешно. Например, он достигает 25 шагов, но затем падает вместо подсчета. По крайней мере, я получил бит счетчика шагов, который что-то делал.