![](/img/trans.png)
[英]How to get Data source for step count using Google Fit Android API?
[英]Unable to get the step count using google fit android
我正在研究步数实现,为此我正在使用 android 的 google fit api。
下面是我的代码。
public class GoogleFitDemoActivity extends AppCompatActivity {
public static final String TAG = "BasicSensorsApi";
private GoogleApiClient mClient = null;
private static final int REQUEST_PERMISSIONS_REQUEST_CODE = 34;
private OnDataPointListener mListener;
private TextView stepsCountTextView;
ProgressDialog progressDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.google_fit_main);
progressDialog = new ProgressDialog(this);
if (!checkPermissions()) {
requestPermissions();
Debug.displayToast(this, "Requesting for permisstion ");
}
stepsCountTextView = (TextView) findViewById(R.id.sample_logview);
}
/**
* Return the current state of the permissions needed.
*/
private boolean checkPermissions() {
int permissionState = ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION);
return permissionState == PackageManager.PERMISSION_GRANTED;
}
/**
* Unregister the listener with the Sensors API.
*/
private void unregisterFitnessDataListener() {
if (mListener == null) {
return;
}
Fitness.SensorsApi.remove(
mClient,
mListener)
.setResultCallback(new ResultCallback<Status>() {
@Override
public void onResult(Status status) {
if (status.isSuccess()) {
Debug.print(TAG, "Listener was removed!");
} else {
Debug.print(TAG, "Listener was not removed.");
}
}
});
}
private void buildFitnessClient() {
if (progressDialog == null) {
return;
}
progressDialog.setMessage("Wait.....");
progressDialog.show();
if (mClient == null && checkPermissions()) {
mClient = new GoogleApiClient.Builder(this)
.addApi(Fitness.SENSORS_API)
.addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE))
.addConnectionCallbacks(
new GoogleApiClient.ConnectionCallbacks() {
@Override
public void onConnected(Bundle bundle) {
runOnUiThread(new Runnable() {
@Override
public void run() {
progressDialog.setMessage("Client Connected waiting for fit register");
}
});
Debug.print(TAG, "Connected!!!");
findFitnessDataSources();
}
@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) {
Debug.print(TAG, "Connection lost. Cause: Network Lost.");
} else if (i
== GoogleApiClient.ConnectionCallbacks.CAUSE_SERVICE_DISCONNECTED) {
Debug.print(TAG,
"Connection lost. Reason: Service Disconnected");
}
}
}
)
.enableAutoManage(this, 0, new GoogleApiClient.OnConnectionFailedListener() {
@Override
public void onConnectionFailed(ConnectionResult result) {
Debug.print(TAG, "Google Play services connection failed. Cause: " +
result.toString());
Snackbar.make(
GoogleFitDemoActivity.this.findViewById(R.id.main_activity_view),
"Exception while connecting to Google Play services: " +
result.getErrorMessage(),
Snackbar.LENGTH_INDEFINITE).show();
}
})
.build();
}
}
private void findFitnessDataSources() {
Fitness.SensorsApi.findDataSources(mClient, new DataSourcesRequest.Builder()
.setDataTypes(DataType.TYPE_STEP_COUNT_CUMULATIVE)
.setDataSourceTypes(DataSource.TYPE_DERIVED)
.build())
.setResultCallback(new ResultCallback<DataSourcesResult>() {
@Override
public void onResult(DataSourcesResult dataSourcesResult) {
progressDialog.dismiss();
Debug.print(TAG, "Result: " + dataSourcesResult.getStatus().toString());
for (DataSource dataSource : dataSourcesResult.getDataSources()) {
Debug.print(TAG, "Data source found: " + dataSource.toString());
Debug.print(TAG, DataType.TYPE_STEP_COUNT_CUMULATIVE + " Data Source type: " + dataSource.getDataType().getName());
//Let's register a listener to receive Activity data!
if (dataSource.getDataType().equals(DataType.TYPE_STEP_COUNT_CUMULATIVE)
&& mListener == null) {
Debug.print(TAG, "Data source for LOCATION_SAMPLE found! Registering.");
registerFitnessDataListener(dataSource,
DataType.TYPE_STEP_COUNT_CUMULATIVE);
}
}
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
}
@Override
protected void onResume() {
super.onResume();
buildFitnessClient();
}
private void registerFitnessDataListener(DataSource dataSource, DataType dataType) {
mListener = new OnDataPointListener() {
@Override
public void onDataPoint(DataPoint dataPoint) {
for (Field field : dataPoint.getDataType().getFields()) {
final Value val = dataPoint.getValue(field);
runOnUiThread(new Runnable() {
@Override
public void run() {
stepsCountTextView.setText("Steps count is " + val);
}
});
Debug.print(TAG, "Detected DataPoint field: " + field.getName());
Debug.print(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()) {
Debug.print(TAG, "Listener registered!");
} else {
Debug.print(TAG, "Listener not registered.");
}
}
});
}
private void requestPermissions() {
boolean shouldProvideRationale =
ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACCESS_FINE_LOCATION);
if (shouldProvideRationale) {
Debug.print(TAG, "Displaying permission rationale to provide additional context.");
Snackbar.make(
findViewById(R.id.main_activity_view),
R.string.permission_rationale,
Snackbar.LENGTH_INDEFINITE)
.setAction(R.string.ok, new View.OnClickListener() {
@Override
public void onClick(View view) {
// Request permission
ActivityCompat.requestPermissions(GoogleFitDemoActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_PERMISSIONS_REQUEST_CODE);
}
})
.show();
} else {
Debug.print(TAG, "Requesting permission");
ActivityCompat.requestPermissions(GoogleFitDemoActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_PERMISSIONS_REQUEST_CODE);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
Debug.print(TAG, "onRequestPermissionResult");
if (requestCode == REQUEST_PERMISSIONS_REQUEST_CODE) {
if (grantResults.length <= 0) {
Debug.print(TAG, "User interaction was cancelled.");
} else if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
buildFitnessClient();
} else {
Snackbar.make(
findViewById(R.id.main_activity_view),
R.string.permission_denied_explanation,
Snackbar.LENGTH_INDEFINITE)
.setAction(R.string.settings, new View.OnClickListener() {
@Override
public void onClick(View view) {
// Build intent that displays the App settings screen.
Intent intent = new Intent();
intent.setAction(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package",
BuildConfig.APPLICATION_ID, null);
intent.setData(uri);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
})
.show();
}
}
}
}
以下是我面临的这段代码中的问题。
(假设我已经开始步行,步数为 10,一旦调用 onConnected(),我将全部杀死并再次启动应用程序我注册获取数据点并获得数据点值 10,而它应该从第一个开始给出 0
1 步长值不会重置为 0 并继续递增。
2 每次运行代码时,steps 值都不会重置为 0,因此它会采用一些过去的值。
3 没有经常更新步数更新需要时间。(当我步行 5 分钟时,它给出了第一步计数)
4 即使在杀死应用程序并再次重新启动应用程序后,仍会获得先前的步数计数,步数计数不会从 0 开始从旧开始。(因为我没有在首选项或数据库中存储任何值。我如何获得上一步计数,例如 10)
请查看结果日志
检测到的 DataPoint 值:1 >>>>>>>>>> 此时它应该从 0 开始
检测到的数据点字段:步骤检测到的数据点值:1
检测到的数据点字段:步骤检测到的数据点值:6
检测到的数据点字段:步骤检测到的数据点值:6
检测到的数据点字段:步骤检测到的数据点值:7
检测到的数据点字段:步骤检测到的数据点值:7
检测到的数据点字段:步骤检测到的数据点值:2
请帮助我犯错的地方。
我认为有两种方法可以通过他们的 API 从 Google Fit 获取步长值:
1)历史API:我们只需要向GG Fit订阅我们想要获得什么样的价值,GG Fit会自己保存信息(不知何故它可以通过利用传感器,机器学习,......(而不是通过GPS -你可以很容易地在谷歌上找到它))。 然后,如果我们想获取 GG Fit 保存的值,只需撤销具有时间范围的 History API。
2) Sensor API:我们将使用带有一些奇妙算法的 Sensor API 与设备中我们自己的传感器通信以直接获取步长值(不是由 GG Fit 在他们的服务器上保存并稍后获取)。 但是,此方法将使用您设备中传感器的临时内存来保存步长值; 并且这个值不断增加,只有当你的设备重新启动时,它才会被重置:( => 所以,你可以做一些小技巧来获得真正的值。(例如,保存第一个值,然后继续减去后面的值。假设起初我们得到1990,然后保存它,然后得到1995,然后减去它1995 - 1190 = 5步)但是,我不知道如果传感器内存中保存的值变得太大并且溢出。:(
** 我的经验:不应该使用 DELTA 类型。 由于时间范围,它可能会带来错误的值; 例如,从 17:30:00 到 17:31:00 它有第 15 步的值,但是如果我们撤销从 17:30:00 到 17:30:10 的时间范围,它就没有值,时间范围从 17:30 :10 到 17:31:00,它有第 10 步的值。有时,当你的屏幕设备处于睡眠状态时,它会丢失值,GG Fit 会在地下调用他们的 API 但不记录时间。 更重要的是,有时我会得到负值@@。 天知道他们在做什么!
最后,我认为 GG Fit 应用程序以某种方式使用了一些技巧来实时显示步长值(可能是传感器 API,而且大多数情况下,我使用带有步长累加(而不是增量)的传感器 API,这提供了类似于 GG Fit 应用程序的最佳结果) )。 然后,当我响应应用程序时,唤醒设备的屏幕(如果您在 Android 中开发,这意味着您的活动调用 onResume() 方法),我撤销历史 API,时间范围从开始到当前时间我唤醒我的应用程序并获取最新信息价值。
https://developers.google.com/fit/android --> 此链接向您展示了对 Android 的哪种 API GG Fit 支持。
https://developer.android.com/reference/android/hardware/Sensor.html#TYPE_STEP_COUNTER --> 这个链接是传感器对TYPE_STEP的描述,据说它会一直增加直到设备重启。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.