我正在研究步骤计数的实现,为此我正在使用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()时杀死了所有并再次启动应用程序,我注册了获取数据点的权限,并获得了dataPoint值10,而应该从第一开始为0
1步长值不会重置为0,而是继续递增。
2每次我运行代码时,steps值都不会重置为0,因此它会吸收一些过去的值。
3没有经常更新步数,这需要花费时间来更新。(当我步行5分钟时,它会给出第一步数)
4即使在杀死应用程序并再次重新启动应用程序之后,也获得了先前的步骤计数,但步骤计数仍不从旧的0开始计数(因为我没有在首选项或数据库中存储任何值。我如何获得上一个步骤的计数,例如10)
请查看结果日志
检测到的DataPoint值:1 >>>>>>>>>>此处应从0开始
检测到的DataPoint字段:步骤
检测到的DataPoint值:1
检测到的DataPoint字段:步骤
检测到的DataPoint值:6
检测到的DataPoint字段:步骤
检测到的DataPoint值:6
检测到的DataPoint字段:步骤
检测到的DataPoint值:7
检测到的DataPoint字段:步骤
检测到的DataPoint值:7
检测到的DataPoint字段:步骤
检测到的DataPoint值:2
请帮助我犯错的地方。
最佳答案
我认为,有两种方法可以通过其API从Google Fit中获取步进值:
1)历史记录API:我们只需要向GG Fit订阅我们想要获得的那种价值,GG Fit便会自行保存信息(以某种方式它可以通过利用传感器,机器学习等来检测您的脚步...(而不是通过GPS-您可以在Google上轻松找到它))。然后,如果我们想获取GG Fit保存的值,只需在一定时间范围内撤消History API。
2)传感器API:我们将使用传感器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()方法),我撤消了从开始到当前重新启动应用程序的时间范围内的History 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的描述,据说它将一直增加直到设备重新启动。
关于android - 无法使用Google Fit Android获取步数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39977241/