代码之家  ›  专栏  ›  技术社区  ›  David

步骤计数器Google FIT API

  •  21
  • David  · 技术社区  · 10 年前

    我目前正在尝试使用Google Fit API。这是我第一个使用该API的应用程序,我主要是通过遵循Google的文档。

    下面是我的代码,似乎有问题

    我的问题是它似乎没有更新步数计数器。

    public class MainActivity extends Activity
            implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
    
            private static final String TAG = "FitActivity";
        //[START Auth_Variable_References]
            private static final int REQUEST_OAUTH = 1;
        // [END auth_variable_references]
            private GoogleApiClient mClient = null;
    
            int mInitialNumberOfSteps = 0;
            private TextView mStepsTextView;
            private boolean mFirstCount = true;
    
        // Create Builder View
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
                mStepsTextView = (TextView) findViewById(R.id.textview_number_of_steps);
            }
    
    
            private void connectFitness() {
                Log.i(TAG, "Connecting...");
    
                // Create the Google API Client
                mClient = new GoogleApiClient.Builder(this)
                        // select the Fitness API
                        .addApi(Fitness.API)
                                // specify the scopes of access
                        .addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ))
                         .addScope(new Scope(Scopes.FITNESS_LOCATION_READ))
                        .addScope(new Scope(Scopes.FITNESS_BODY_READ_WRITE))
                                        // provide callbacks
                                .addConnectionCallbacks(this)
                                .addOnConnectionFailedListener(this)
                                .build();
    
                // Connect the Google API client
                mClient.connect();
            }
    
            // Manage OAuth authentication
            @Override
            public void onConnectionFailed(ConnectionResult result) {
    
                // Error while connecting. Try to resolve using the pending intent returned.
                if (result.getErrorCode() == ConnectionResult.SIGN_IN_REQUIRED ||
                        result.getErrorCode() == FitnessStatusCodes.NEEDS_OAUTH_PERMISSIONS) {
                    try {
                        // Request authentication
                        result.startResolutionForResult(this, REQUEST_OAUTH);
                    } catch (IntentSender.SendIntentException e) {
                        Log.e(TAG, "Exception connecting to the fitness service", e);
                    }
                } else {
                    Log.e(TAG, "Unknown connection issue. Code = " + result.getErrorCode());
                }
            }
    
            @Override
            public void onActivityResult(int requestCode, int resultCode, Intent data) {
                if (requestCode == REQUEST_OAUTH) {
                    if (resultCode == RESULT_OK) {
                        // If the user authenticated, try to connect again
                        mClient.connect();
                    }
                }
            }
    
            @Override
            public void onConnectionSuspended(int i) {
                // If your connection 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");
                }
            }
    
            @Override
            public void onConnected(Bundle bundle) {
    
                Log.i(TAG, "Connected!");
    
                // Now you can make calls to the Fitness APIs.
                invokeFitnessAPIs();
    
            }
    
            private void invokeFitnessAPIs() {
    
                // Create a listener object to be called when new data is available
                OnDataPointListener listener = new OnDataPointListener() {
                    @Override
                    public void onDataPoint(DataPoint dataPoint) {
    
                        for (Field field : dataPoint.getDataType().getFields()) {
                            Value val = dataPoint.getValue(field);
                            updateTextViewWithStepCounter(val.asInt());
                        }
                    }
                };
    
                //Specify what data sources to return
                DataSourcesRequest req = new DataSourcesRequest.Builder()
                        .setDataSourceTypes(DataSource.TYPE_DERIVED)
                        .setDataTypes(DataType.TYPE_STEP_COUNT_DELTA)
                        .build();
    
                //  Invoke the Sensors API with:
                // - The Google API client object
                // - The data sources request object
                PendingResult<DataSourcesResult> pendingResult =
                        Fitness.SensorsApi.findDataSources(mClient, req);
    
                //  Build a sensor registration request object
                SensorRequest sensorRequest = new SensorRequest.Builder()
                        .setDataType(DataType.TYPE_STEP_COUNT_CUMULATIVE)
                        .setSamplingRate(1, TimeUnit.SECONDS)
                        .build();
    
                //  Invoke the Sensors API with:
                // - The Google API client object
                // - The sensor registration request object
                // - The listener object
                PendingResult<Status> regResult =
                  Fitness.SensorsApi.add(mClient,
                          new SensorRequest.Builder()
                          .setDataType(DataType.TYPE_STEP_COUNT_DELTA)
                          .build(),
                          listener);
    
    
                // 4. Check the result asynchronously
                regResult.setResultCallback(new ResultCallback<Status>()
                {
                    @Override
                    public void onResult(Status status) {
                        if (status.isSuccess()) {
                            Log.d(TAG, "listener registered");
                            // listener registered
                        } else {
                            Log.d(TAG, "listener not registered");
                            // listener not registered
                        }
                    }
                });
            }
    
            // Update the Text Viewer with Counter of Steps..
            private void updateTextViewWithStepCounter(final int numberOfSteps) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(getBaseContext(), "On Datapoint!", Toast.LENGTH_SHORT);
    
                        if(mFirstCount && (numberOfSteps != 0)) {
                            mInitialNumberOfSteps = numberOfSteps;
                            mFirstCount = false;
                        }
                        if(mStepsTextView != null){
                            mStepsTextView.setText(String.valueOf(numberOfSteps - mInitialNumberOfSteps));
                        }
                    }
                });
            }
    
        //Start
        @Override
        protected void onStart() {
            super.onStart();
            mFirstCount = true;
            mInitialNumberOfSteps = 0;
            if (mClient == null || !mClient.isConnected()) {
                connectFitness();
            }
        }
        //Stop
            @Override
            protected void onStop() {
                super.onStop();
                if(mClient.isConnected() || mClient.isConnecting()) mClient.disconnect();
                mInitialNumberOfSteps = 0;
                mFirstCount = true;
            }
    
        }
    
    4 回复  |  直到 9 年前
        1
  •  5
  •   Rajesh Satvara    8 年前

    首先 按照以下步骤在Google API控制台中启用Fitness API并获取OAuth 2.0客户端ID。

    1. 转到 Google API Console.

    2. 选择项目或创建新项目。对应用程序的Android和REST版本使用相同的项目。

    3. 单击“继续”以启用健身API。

    4. 单击转到凭据。

    5. 单击新建凭据,然后选择OAuth客户端ID。

    6. 在应用程序类型下选择Android。

    7. 在结果对话框中,输入应用程序的SHA-1指纹和软件包名称。例如:

    BB:0D:AC:74:D3:21:E1:43:67:71:9B:62:91:AF:66:6E:44:5D:75

    com.example.android.fit-example

    8. 单击“创建”。新的Android OAuth 2.0客户端ID和密码将显示在项目的ID列表中。OAuth 2.0客户端ID是一个字符串,类似于:

    780816631155-gbvyo7r2pn95qc4ei9d61io4uh48ml.apps.googleusercontent.com

    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    
    import com.google.android.gms.common.ConnectionResult;
    import com.google.android.gms.common.Scopes;
    import com.google.android.gms.common.api.GoogleApiClient;
    import com.google.android.gms.common.api.ResultCallback;
    import com.google.android.gms.common.api.Scope;
    import com.google.android.gms.common.api.Status;
    import com.google.android.gms.fitness.Fitness;
    import com.google.android.gms.fitness.data.DataPoint;
    import com.google.android.gms.fitness.data.DataSource;
    import com.google.android.gms.fitness.data.DataType;
    import com.google.android.gms.fitness.data.Field;
    import com.google.android.gms.fitness.data.Value;
    import com.google.android.gms.fitness.request.DataSourcesRequest;
    import com.google.android.gms.fitness.request.OnDataPointListener;
    import com.google.android.gms.fitness.request.SensorRequest;
    import com.google.android.gms.fitness.result.DataSourcesResult;
    
    import java.util.concurrent.TimeUnit;
    
    /**
     * Created by Admin on Dec/8/2016.
     * <p/>
     * <p/>
     * http://stackoverflow.com/questions/28476809/step-counter-google-fit-api?rq=1
     */
    public class StackOverflowActivity extends AppCompatActivity
           {
    
        private static final String TAG = "FitActivity";
        private GoogleApiClient mClient = null;
        private OnDataPointListener mListener;
    
        // Create Builder View
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }
    
        @Override
        protected void onResume() {
            super.onResume();
            connectFitness();
        }
    
        private void connectFitness() {
            if (mClient == null){
                mClient = new GoogleApiClient.Builder(this)
                        .addApi(Fitness.SENSORS_API)
                        .addScope(new Scope(Scopes.FITNESS_LOCATION_READ)) // GET STEP VALUES
                        .addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
                                                    @Override
                                                    public void onConnected(Bundle bundle) {
                                                        Log.e(TAG, "Connected!!!");
                                                        // Now you can make calls to the Fitness APIs.
                                                        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) {
                                                            Log.i(TAG, "Connection lost.  Cause: Network Lost.");
                                                        } else if (i
                                                                == GoogleApiClient.ConnectionCallbacks.CAUSE_SERVICE_DISCONNECTED) {
                                                            Log.i(TAG,
                                                                    "Connection lost.  Reason: Service Disconnected");
                                                        }
                                                    }
                                                }
                        )
                        .enableAutoManage(this, 0, new GoogleApiClient.OnConnectionFailedListener() {
                            @Override
                            public void onConnectionFailed(ConnectionResult result) {
                                Log.e(TAG, "!_@@ERROR :: Google Play services connection failed. Cause: " + result.toString());
                            }
                        })
                        .build();
            }
    
        }
    
        private void findFitnessDataSources() {
            Fitness.SensorsApi.findDataSources(
                    mClient,
                    new DataSourcesRequest.Builder()
                            .setDataTypes(DataType.TYPE_STEP_COUNT_DELTA)
                            .setDataSourceTypes(DataSource.TYPE_DERIVED)
                            .build())
                    .setResultCallback(new ResultCallback<DataSourcesResult>() {
                        @Override
                        public void onResult(DataSourcesResult dataSourcesResult) {
                            Log.e(TAG, "Result: " + dataSourcesResult.getStatus().toString());
                            for (DataSource dataSource : dataSourcesResult.getDataSources()) {
                                Log.e(TAG, "Data source found: " + dataSource.toString());
                                Log.e(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 TYPE_STEP_COUNT_DELTA found!  Registering.");
    
                                    registerFitnessDataListener(dataSource, DataType.TYPE_STEP_COUNT_DELTA);
                                }
                            }
                        }
                    });
        }
    
        private void registerFitnessDataListener(final 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.e(TAG, "Detected DataPoint field: " + field.getName());
                        Log.e(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.");
                    }
                }
            });
    
        }
    }
    

    注: ::有时在某些设备中,它无法检测Step值,因此无论何时开发和使用此代码 始终卸载应用程序,然后重新安装应用程序。那么这很好。

    **Don't forget to add this permission**
    
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    
        2
  •  1
  •   Machado    9 年前

    您可以尝试 StepSensor 来自的库 OrangeGangster的 .

    它包含一个自定义 Service 允许从 Sensor.TYPE_STEP_COUNTER Android 4.4(仅适用于支持此硬件功能的设备)。

        3
  •  1
  •   Armin    9 年前

    这个代码对我有用!

    构建客户端:

    mClient = new GoogleApiClient.Builder(this)
                .addApi(Fitness.SENSORS_API)
                .addScope(new Scope(Scopes.FITNESS_BODY_READ_WRITE))
                .addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE))
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();
    

    调用传感器API:

    private void invokeSensorsAPI() {
        Fitness.SensorsApi.add(
                mClient,
                new SensorRequest.Builder()
                        .setDataType(DataType.TYPE_STEP_COUNT_DELTA) 
                        .setSamplingRate(1, TimeUnit.SECONDS)
                        .build(),
                this)
                .setResultCallback(new ResultCallback<Status>() {
                    @Override
                    public void onResult(Status status) {
                        if (status.isSuccess()) {
                            Log.i(TAG, "Sensor Listener registered!");
                        } else {
                            Log.i(TAG, "Sensor Listener not registered.");
                        }
                    }
                });
    }
    

    接收数据:

    @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);
            final int value = val.asInt();
    
            if (field.getName().compareToIgnoreCase("steps") == 0) {
    
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            tv.setText("Value" + value)
                        }
                    });
            }
    
        }
    }
    

    我希望这有帮助

        4
  •  0
  •   suku    8 年前

    我认为你在这里犯了一个错误

    if (resultCode == RESULT_OK) {
        // If the user authenticated, try to connect again
        mClient.connect()
    }
    

    相反,它应该是

    if (resultCode != RESULT_OK) {
        // If the user is not authenticated, try to connect again/ resultcode = RESULT_CANCEL
        mClient.connect()
    } else {
        onConnected(null);
    }
    

    通过您的代码invokeFitnessApis将永远不会被调用,因为您在成功连接后将重新连接到googleapiclient。