- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在尝试使用 google fit 获取步行步数的数据。我正在执行此 tutorial 中的代码.我被要求提供我想要连接 google fit 的帐户。选择帐户后,它无法连接。选择帐户后,将调用 onActivityResult 但 mApiClient.isConnecting()
&& mApiClient.isConnected()
都是 false
和 resultCode == RESULT_CANCELED
。因此,不会调用下一个请求访问拟合数据权限的警告对话框。我不明白为什么 mApiClient 没有连接。我已按照教程中所示的有关创建 oauth2、启用 Fitness Api 和提供 keyStore 的步骤进行操作。
public class MainActivity extends AppCompatActivity implements OnDataPointListener,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
private static final int REQUEST_OAUTH = 1;
private static final String AUTH_PENDING = "auth_state_pending";
private boolean authInProgress = false;
private GoogleApiClient mApiClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState != null) {
authInProgress = savedInstanceState.getBoolean(AUTH_PENDING);
}
mApiClient = new GoogleApiClient.Builder(this)
.addApi(Fitness.SENSORS_API)
.addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE))
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
@Override
protected void onStart() {
super.onStart();
mApiClient.connect();
}
@Override
protected void onStop() {
super.onStop();
Fitness.SensorsApi.remove( mApiClient, this )
.setResultCallback(new ResultCallback<Status>() {
@Override
public void onResult(Status status) {
if (status.isSuccess()) {
mApiClient.disconnect();
}
}
});
}
private void registerFitnessDataListener(DataSource dataSource, DataType dataType) {
SensorRequest request = new SensorRequest.Builder()
.setDataSource( dataSource )
.setDataType( dataType )
.setSamplingRate( 3, TimeUnit.SECONDS )
.build();
Fitness.SensorsApi.add(mApiClient, request, this)
.setResultCallback(new ResultCallback<Status>() {
@Override
public void onResult(Status status) {
if (status.isSuccess()) {
Log.e("GoogleFit", "SensorApi successfully added");
} else {
Log.e("GoogleFit", "adding status: " + status.getStatusMessage());
}
}
});
}
@Override
public void onConnected(Bundle bundle) {
DataSourcesRequest dataSourceRequest = new DataSourcesRequest.Builder()
.setDataTypes( DataType.TYPE_STEP_COUNT_CUMULATIVE )
.setDataSourceTypes( DataSource.TYPE_RAW )
.build();
ResultCallback<DataSourcesResult> dataSourcesResultCallback = new ResultCallback<DataSourcesResult>() {
@Override
public void onResult(DataSourcesResult dataSourcesResult) {
for( DataSource dataSource : dataSourcesResult.getDataSources() ) {
if( DataType.TYPE_STEP_COUNT_CUMULATIVE.equals( dataSource.getDataType() ) ) {
registerFitnessDataListener(dataSource, DataType.TYPE_STEP_COUNT_CUMULATIVE);
}
}
}
};
Fitness.SensorsApi.findDataSources(mApiClient, dataSourceRequest)
.setResultCallback(dataSourcesResultCallback);
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
if( !authInProgress ) {
try {
authInProgress = true;
connectionResult.startResolutionForResult( MainActivity.this, REQUEST_OAUTH );
} catch(IntentSender.SendIntentException e ) {
Log.e( "GoogleFit", "sendingIntentException " + e.getMessage() );
}
} else {
Log.e( "GoogleFit", "authInProgress" );
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if( requestCode == REQUEST_OAUTH ) {
authInProgress = false;
if( resultCode == RESULT_OK ) {
if( !mApiClient.isConnecting() && !mApiClient.isConnected() ) {
mApiClient.connect();
}
} else if( resultCode == RESULT_CANCELED ) {
Log.e( "GoogleFit", "RESULT_CANCELED" );
}
} else {
Log.e("GoogleFit", "requestCode NOT request_oauth");
}
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onDataPoint(DataPoint dataPoint) {
for( final Field field : dataPoint.getDataType().getFields() ) {
final Value value = dataPoint.getValue( field );
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "Field: " + field.getName() + " Value: " + value, Toast.LENGTH_SHORT).show();
}
});
}
}
}
最佳答案
This答案帮助我弄清楚了如何解决。将这些依赖项添加到 gradle 文件中。 Google 已更新 ApiClient 库,他们需要 google 登录身份验证才能访问 api
compile 'com.google.android.gms:play-services-fitness:9.0.1'
compile 'com.google.android.gms:play-services-auth:9.0.1'
我添加了整个代码,因为不同的错误可能会给出 RESULT_CANCELED 作为输出。
public class MainActivity extends Activity implements GoogleApiClient.OnConnectionFailedListener,
GoogleApiClient.ConnectionCallbacks, OnDataPointListener {
private static final String TAG = "CCC";
private static final String AUTH_PENDING = "isAuthPending";
GoogleApiClient googleApiClient;
private boolean authInProgress = false;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//authInProgress code is useful because the onStop may be called while authentication is not complete.
//In such case this tells it to complete it
if (savedInstanceState != null) {
authInProgress = savedInstanceState.getBoolean(AUTH_PENDING);
}
}
@Override
protected void onStart() {
super.onStart();
//very important that the following lines are called in onStart
//when they are called in onCreate, when the permission fragment opens up, onStop gets called which disconnects the api client.
//after which it needs to be reConnected which does not happen as the apiClient is built in onCreate
//Hence these should be called in onStart or probably onResume.
googleApiClient = googleFitBuild(this, this, this);
googleFitConnect(this, googleApiClient);
}
public static GoogleApiClient googleFitBuild(Activity activity, GoogleApiClient.ConnectionCallbacks connectionCallbacks, GoogleApiClient.OnConnectionFailedListener failedListener){
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.requestScopes(new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE))
.build();
return new GoogleApiClient.Builder(activity)
//without GOOGLE_SIGN_IN_API, RESULT_CANCELED is always the output
//The new version of google Fit requires that the user authenticates with gmail account
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.addConnectionCallbacks(connectionCallbacks)
.addOnConnectionFailedListener(failedListener)
.addApi(Fitness.HISTORY_API)
.addApi(Fitness.SESSIONS_API)
.addApi(Fitness.RECORDING_API)
.addApi(Fitness.SENSORS_API)
.build();
}
//runs an automated Google Fit connect sequence
public static void googleFitConnect(final Activity activity, final GoogleApiClient mGoogleApiClient){
Log.d(TAG, "google fit connect called");
if(!mGoogleApiClient.isConnected() && !mGoogleApiClient.isConnecting()) {
mGoogleApiClient.registerConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
@Override
public void onConnected(Bundle bundle) {
Log.d(TAG, "Google API connected");
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
activity.startActivityForResult(signInIntent, 1);
}
@Override
public void onConnectionSuspended(int i) {
}
});
mGoogleApiClient.connect(GoogleApiClient.SIGN_IN_MODE_OPTIONAL);
}
}
@Override
public void onConnected(@Nullable Bundle bundle) {
Log.d(TAG, "onConnected called");
DataSourcesRequest dataSourceRequest = new DataSourcesRequest.Builder()
.setDataTypes(DataType.TYPE_STEP_COUNT_CUMULATIVE)
.setDataSourceTypes(DataSource.TYPE_RAW)
.build();
Log.d(TAG, "DataSourcetype: " + dataSourceRequest.getDataTypes().toString());
ResultCallback<DataSourcesResult> dataSourcesResultCallback = new ResultCallback<DataSourcesResult>() {
@Override
public void onResult(DataSourcesResult dataSourcesResult) {
Log.d(TAG, "onResult in Result Callback called");
for( DataSource dataSource : dataSourcesResult.getDataSources() ) {
if(DataType.TYPE_STEP_COUNT_CUMULATIVE.equals(dataSource.getDataType())) {
Log.d(TAG, "type step");
registerStepsDataListener(dataSource, DataType.TYPE_STEP_COUNT_CUMULATIVE);
}
}
}
};
Fitness.SensorsApi.findDataSources(googleApiClient, dataSourceRequest)
.setResultCallback(dataSourcesResultCallback);
}
@Override
public void onConnectionSuspended(int i) {
Log.d(TAG, "Connection suspended i= " + i);
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
if( !authInProgress ) {
Log.d(TAG, "!AUTHINPROG");
try {
authInProgress = true;
connectionResult.startResolutionForResult(this, 1);
} catch(IntentSender.SendIntentException e ) {
Log.d(TAG, "SendIntentExc: " + e.toString());
}
} else {
Log.d(TAG, "authInProgress" );
}
}
private void registerStepsDataListener(DataSource dataSource, DataType dataType) {
SensorRequest request = new SensorRequest.Builder()
.setDataSource(dataSource)
.setDataType(dataType)
.setSamplingRate(3, TimeUnit.SECONDS )
.build();
Fitness.SensorsApi.add(googleApiClient, request, this)
.setResultCallback(new ResultCallback<Status>() {
@Override
public void onResult(Status status) {
if (status.isSuccess()) {
Log.d(TAG, "SensorApi successfully added" );
}
}
});
}
@Override
public void onDataPoint(DataPoint dataPoint) {
for( final Field field : dataPoint.getDataType().getFields() ) {
final Value value = dataPoint.getValue( field );
Log.d(TAG, "Field Name: " + field.getName() + " Value: " + value.toString());
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "Field: " + field.getName() + " Value: " + value, Toast.LENGTH_SHORT).show();
}
});
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(TAG, "OnActivityResult called");
if( requestCode == 1) {
authInProgress = false;
if( resultCode == RESULT_OK ) {
Log.d(TAG, "Result_OK");
if( !googleApiClient.isConnecting() && !googleApiClient.isConnected() ) {
Log.d(TAG, "Calling googleApiClient.connect again");
googleApiClient.connect(GoogleApiClient.SIGN_IN_MODE_OPTIONAL);
} else {
onConnected(null);
}
} else if( resultCode == RESULT_CANCELED ) {
Log.d( TAG, "RESULT_CANCELED" );
}
} else {
Log.d(TAG, "requestCode NOT request_oauth");
}
}
@Override
protected void onStop() {
Log.d(TAG, "Onstop called");
super.onStop();
Fitness.SensorsApi.remove( googleApiClient, this )
.setResultCallback(new ResultCallback<Status>() {
@Override
public void onResult(Status status) {
if (status.isSuccess()) {
googleApiClient.disconnect();
}
}
});
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.d(TAG, "Onsaveinstance called");
outState.putBoolean(AUTH_PENDING, authInProgress);
}
}
关于android - 使用 google fit 时 GoogleApiClient 未连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37679476/
SQLite、Content provider 和 Shared Preference 之间的所有已知区别。 但我想知道什么时候需要根据情况使用 SQLite 或 Content Provider 或
警告:我正在使用一个我无法完全控制的后端,所以我正在努力解决 Backbone 中的一些注意事项,这些注意事项可能在其他地方更好地解决......不幸的是,我别无选择,只能在这里处理它们! 所以,我的
我一整天都在挣扎。我的预输入搜索表达式与远程 json 数据完美配合。但是当我尝试使用相同的 json 数据作为预取数据时,建议为空。点击第一个标志后,我收到预定义消息“无法找到任何内容...”,结果
我正在制作一个模拟 NHL 选秀彩票的程序,其中屏幕右侧应该有一个 JTextField,并且在左侧绘制弹跳的选秀球。我创建了一个名为 Ball 的类,它实现了 Runnable,并在我的主 Draf
这个问题已经有答案了: How can I calculate a time span in Java and format the output? (18 个回答) 已关闭 9 年前。 这是我的代码
我有一个 ASP.NET Web API 应用程序在我的本地 IIS 实例上运行。 Web 应用程序配置有 CORS。我调用的 Web API 方法类似于: [POST("/API/{foo}/{ba
我将用户输入的时间和日期作为: DatePicker dp = (DatePicker) findViewById(R.id.datePicker); TimePicker tp = (TimePic
放宽“邻居”的标准是否足够,或者是否有其他标准行动可以采取? 最佳答案 如果所有相邻解决方案都是 Tabu,则听起来您的 Tabu 列表的大小太长或您的释放策略太严格。一个好的 Tabu 列表长度是
我正在阅读来自 cppreference 的代码示例: #include #include #include #include template void print_queue(T& q)
我快疯了,我试图理解工具提示的行为,但没有成功。 1. 第一个问题是当我尝试通过插件(按钮 1)在点击事件中使用它时 -> 如果您转到 Fiddle,您会在“内容”内看到该函数' 每次点击都会调用该属
我在功能组件中有以下代码: const [ folder, setFolder ] = useState([]); const folderData = useContext(FolderContex
我在使用预签名网址和 AFNetworking 3.0 从 S3 获取图像时遇到问题。我可以使用 NSMutableURLRequest 和 NSURLSession 获取图像,但是当我使用 AFHT
我正在使用 Oracle ojdbc 12 和 Java 8 处理 Oracle UCP 管理器的问题。当 UCP 池启动失败时,我希望关闭它创建的连接。 当池初始化期间遇到 ORA-02391:超过
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 9 年前。 Improve
引用这个plunker: https://plnkr.co/edit/GWsbdDWVvBYNMqyxzlLY?p=preview 我在 styles.css 文件和 src/app.ts 文件中指定
为什么我的条形这么细?我尝试将宽度设置为 1,它们变得非常厚。我不知道还能尝试什么。默认厚度为 0.8,这是应该的样子吗? import matplotlib.pyplot as plt import
当我编写时,查询按预期执行: SELECT id, day2.count - day1.count AS diff FROM day1 NATURAL JOIN day2; 但我真正想要的是右连接。当
我有以下时间数据: 0 08/01/16 13:07:46,335437 1 18/02/16 08:40:40,565575 2 14/01/16 22:2
一些背景知识 -我的 NodeJS 服务器在端口 3001 上运行,我的 React 应用程序在端口 3000 上运行。我在 React 应用程序 package.json 中设置了一个代理来代理对端
我面临着一个愚蠢的问题。我试图在我的 Angular 应用程序中延迟加载我的图像,我已经尝试过这个2: 但是他们都设置了 src attr 而不是 data-src,我在这里遗漏了什么吗?保留 d
我是一名优秀的程序员,十分优秀!