我正在研究步骤计数的实现,为此我正在使用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/

10-12 02:47