[英]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.