Android 步进计数器GoogleFitAPI

Android 步进计数器GoogleFitAPI,android,google-fit,Android,Google Fit,我目前正在尝试使用GoogleFitAPI。这是我第一个使用该API的应用程序,我主要是遵循Google的文档 下面是我的代码,它似乎有问题 我的问题是,它似乎没有更新步进计数器 public class MainActivity extends Activity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener { private

我目前正在尝试使用GoogleFitAPI。这是我第一个使用该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;
        }

    }
公共类MainActivity扩展活动
实现GoogleAppClient.ConnectionCallbacks、GoogleAppClient.OnConnectionFailedListener{
私有静态最终字符串标记=“FitActivity”;
//[开始验证变量引用]
私有静态最终int请求_OAUTH=1;
//[结束验证变量引用]
private GoogleAppClient mClient=null;
int mInitialNumberOfSteps=0;
私有文本视图mStepsTextView;
私有布尔值mFirstCount=true;
//创建生成器视图
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mStepsTextView=(TextView)findViewById(R.id.TextView\u步骤数);
}
私人健身(){
Log.i(标记“连接…”);
//创建GoogleAPI客户端
mClient=new GoogleApiClient.Builder(此)
//选择健身API
.addApi(Fitness.API)
//指定访问范围
.addScope(新范围(范围.适应度\活动\读取))
.addScope(新范围(范围.适合度\位置\读取))
.addScope(新范围(Scopes.FITNESS\u BODY\u READ\u WRITE))
//提供回调
.addConnectionCallbacks(此)
.addOnConnectionFailedListener(此)
.build();
//连接谷歌API客户端
mClient.connect();
}
//管理OAuth身份验证
@凌驾
连接失败的公共void(连接结果){
//连接时出错。请尝试使用返回的挂起意图进行解决。
if(result.getErrorCode()==ConnectionResult.SIGN\u需要||
result.getErrorCode()==FitnessStatusCodes.需要\u OAUTH\u权限){
试一试{
//请求身份验证
result.startResolutionForResult(这是请求);
}catch(IntentSender.sendtintentexe){
Log.e(标签“连接到健身服务的异常”,e);
}
}否则{
Log.e(标记“未知连接问题.代码=“+result.getErrorCode()”);
}
}
@凌驾
ActivityResult上的公共void(int请求代码、int结果代码、意图数据){
if(requestCode==REQUEST\u OAUTH){
if(resultCode==RESULT\u OK){
//如果用户已通过身份验证,请尝试再次连接
mClient.connect();
}
}
}
@凌驾
公共空间连接暂停(int i){
//如果您的连接在某个点丢失,
//你可以在这里确定原因并作出反应。
if(i==GoogleApiClient.ConnectionCallbacks.CAUSE\u NETWORK\u LOST){
Log.i(标记“连接丢失。原因:网络丢失”);
}else if(i==GoogleAppClient.ConnectionCallbacks.CAUSE\u服务\u已断开连接){
Log.i(标记“连接丢失。原因:服务断开”);
}
}
@凌驾
未连接的公共空间(捆绑包){
Log.i(标记“已连接!”);
//现在,您可以调用健身API。
invokeFitnessAPIs();
}
私有void invokeFitnessAPIs(){
//创建新数据可用时要调用的侦听器对象
OnDataPointListener=新的OnDataPointListener(){
@凌驾
公共无效数据点(数据点数据点){
for(字段:dataPoint.getDataType().getFields()){
Value val=dataPoint.getValue(字段);
updateTextViewWithStepCounter(val.asInt());
}
}
};
//指定要返回的数据源
DataSourcesRequest req=新建DataSourcesRequest.Builder()
.setDataSourceTypes(DataSource.TYPE_派生)
.setDataTypes(数据类型.TYPE\u步骤\u计数\u增量)
.build();
//使用以下命令调用传感器API:
//-谷歌API客户端对象
//-数据源请求对象
潘丁格勒潘丁格勒=
Fitness.SensorsApi.findDataSources(mClient,req);
//构建传感器注册请求对象
SensorRequest SensorRequest=新建SensorRequest.Builder()
.setDataType(数据类型.类型\步骤\计数\累积)
.设置采样率(1,时间单位。秒)
.build();
//使用以下命令调用传感器API:
//-谷歌API客户端对象
//-传感器注册请求对象
//-侦听器对象
Pendingressult=
Fitness.SensorsApi.add(mClient,
新建SensorRequest.Builder()
.setDataType(数据类型.TYPE\u步骤\u计数\u增量)
.build(),
听众);
//4.异步检查结果
regResult.setResultCallback(新的ResultCallback()
{
@凌驾
公共void onResult(状态){
if(status.issucess()){
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();
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)
                    }
                });
        }

    }
}
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);
}
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.");
                }
            }
        });

    }
}
**Don't forget to add this permission**

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />