使用 Google Fit api 时的 Google Oauth 2.0 RESULT_CANCELED

Posted

技术标签:

【中文标题】使用 Google Fit api 时的 Google Oauth 2.0 RESULT_CANCELED【英文标题】:Google Oauth 2.0 RESULT_CANCELED while using Google Fit api 【发布时间】:2016-09-14 07:34:11 【问题描述】:

我正在尝试在我的 android 应用程序中使用 google fit api。我遵循this 指南并在我的 jdk 1.8 bin 文件夹中使用 keytool.exe 创建了 SHA-1 证书。我现在已经创建了 Oauth 客户端 ID。

在我的应用中,我在这里得到 RESULT_CANCELED:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) 
    super.onActivityResult(requestCode, resultCode, data);
    if( requestCode == REQUEST_OAUTH ) 
        authInProgress = false;
        if( resultCode == RESULT_OK ) 
            if( !mClient.isConnecting() && !mClient.isConnected() ) 
                mClient.connect();
            
         else if( resultCode == RESULT_CANCELED ) /// HERE
            Toast.makeText(MainActivity.this,"RESULT_CANCELED",Toast.LENGTH_SHORT).show();
            Log.e("GoogleFit", "RESULT_CANCELED");
            Log.e("GoogleFit", data.getExtras().toString());
        
    else if(requestCode == CALL_END)
        if (resultCode == Activity.RESULT_OK)
            //pass
        else

        
     else 
        Log.e("GoogleFit", "requestCode NOT request_oauth");
    

试图找出过去两天的问题。我在 android studio 中添加了正确的播放服务库:compile 'com.google.android.gms:play-services-fitness:8.4.0'

建筑客户端:

private void buildFitnessClient() 

    if (mClient == null && checkPermissions()) 
        Log.i(TAG, "Building Fitness Client");
        mClient = new GoogleApiClient.Builder(this)
                .addApi(Fitness.SENSORS_API)
                .addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE))
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();
        mClient.connect();
    

回调:

/**
 * GOOGLE FIT METHODS
 */
@Override
public void onConnected(@Nullable 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(mClient, dataSourceRequest)
            .setResultCallback(dataSourcesResultCallback);

@Override
public void onConnectionSuspended(int i) 


@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) 
    if( !authInProgress ) 
        try 
            authInProgress = true;
            connectionResult.startResolutionForResult( MainActivity.this, REQUEST_OAUTH );
         catch(IntentSender.SendIntentException e ) 

        
     else 
        Log.e( "GoogleFit", "authInProgress" );
    

@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();
                HealthRecordFragment.mStepsWalking.setText(value.toString());
            
        );
    

在 Gradle 中:

apply plugin: 'com.android.application'

android 
    compileSdkVersion 23
    buildToolsVersion "23.0.1"

    defaultConfig 
        applicationId "com.xxxx.xxxx"
        minSdkVersion 15
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    
    signingConfigs 
        release 
            storeFile file("C:\\Users\\xxxxx\\AndroidStudioProjects\\HBEAT2\\app\\hbeat_android")
            storePassword "password"
            keyAlias "hbeat_android"
            keyPassword "password"
        
    
    buildTypes 
        release 
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        
    


dependencies 
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.google.android.gms:play-services-fitness:8.4.0'
    compile 'com.android.support:appcompat-v7:23.1.1'
    compile "com.android.support:design:23.2.1"
    compile 'com.github.rahatarmanahmed:circularprogressview:2.4.0'
    compile 'de.timroes.android:EnhancedListView:0.3.0'

【问题讨论】:

您使用什么意图来获取请求?如果您没有发送正确的数据,可能就是这种情况。 请看上面的代码。这就是我构建客户端的方式 还有Oauth Client ID有什么用。我已经创建了它,但我没有在任何地方使用它 Oauth ID 是自动的。您能否包含您的回调代码以查看那里是否可能发生某些事情 您找到解决方案了吗? 【参考方案1】:

我刚刚遇到了这个问题。花了我几个小时才弄明白,所以我想指出那些犯同样错误的人。

我的 Google API 客户端无法仅在生产环境中连接,在开发环境中一切正常。

这是因为我的应用设置为使用“应用签名”。这样,如果您使用 Production Keystore 的 SHA1(或图片中上传证书的 SHA1)创建了 Oauth Client ID,它将不会被使用,因为 google 将删除此证书并更改为“App Signing”证书

所以我们需要做的是解决这个问题:只需使用这个新的 SHA1 创建一个新的 OAuth 客户端 ID,如下所示:

这个问题很容易遇到,因为大多数教程都会告诉您找到您的生产 SHA1 并在 API 控制台中使用它。但除非您使用“应用签名”,否则它将不再起作用。

【讨论】:

我被这个问题困扰了 3 天。非常感谢! 非常感谢!这对我有帮助!我坚持了大约 3 天,因为我使用 Firebase UI Auth,它返回 errorCode=4 (PROVIDER ERROR),我不知道原因。所以我尝试将 Firebase Auth SDK 与 Google 和 errorCode=16 (RESULT_CANCELED) 一起使用,这个主题对我有帮助。 谢谢 Nathan Do。当你说“大多数教程会告诉你......”时,你就明白了。 “适用于 Android 的 Google Cloud Client ID”部分似乎也具有误导性,因为它显示了获取指纹的命令行,而正确的 Google Play 控制台密钥证书上没有任何文字可供使用。【参考方案2】:

获得RESULT_CANCELED 的一个原因是,如果您的包名称与您在应用中定义的名称不同。

仔细检查您没有在 build.gradle 中设置另一个 applicationId,这可能与清单中定义的 package 不同。

【讨论】:

包名在所有地方都相同,即 manifest、gradle 和 google 开发者控制台【参考方案3】:

如果上述解决方案对您没有帮助,那么您绝对应该考虑一次此解决方案。我真的很努力才能弄清楚这一点。所以我认为,我的发现将帮助其他人避免同样的挣扎和挫折。

我已按照 google 指南 设置 GFi 身份验证。但完成后,我注意到当我的应用程序请求用户许可时,它会弹出身份验证屏幕。但是当用户选择一个帐户时,它只是在onActivityResult() 中返回RESULT_CANCELED 而不是RESULT_OK。其背后的原因是证书不匹配。我使用我的项目的 keystore 文件来生成 OAuth 令牌生成所需的SHA-1 指纹。但是我正在部署的构建是debug。当我尝试使用release 构建时,它运行良好。其背后的原因是,Android Studio 默认使用debug.keystore 文件来签署debug 构建,这与项目的keystore 文件不同。这就是为什么它在调试模式下不起作用的原因。当我将项目的 debug 配置更改为使用项目的 keystore 文件时,它就像一个魅力。所以,我建议先检查这个用例。大多数情况下,这是实际问题。你可以找到另一个 *** 问题 here 来解决这个问题。

要了解有关如何更改/修改构建的签名配置的更多信息,请参阅this。

【讨论】:

【参考方案4】:

我最近也遇到了这个问题。我不确定问题出在哪里,但它可能源于 Google 对 GoogleAPIClient 库和身份验证程序的更新。

我必须将自己的身份验证流程更新为 Google 登录 (Android) 的最新文档: https://developers.google.com/identity/sign-in/android/sign-in#before_you_begin

我也在用

    compile 'com.google.android.gms:play-services-auth:9.0.0'
    compile 'com.google.android.gms:play-services-fitness:9.0.0'

对于图书馆。这是我的代码的 sn-p:

//runs an automated Google Fit connect sequence
public static GoogleApiClient googleFitBuild(Activity activity, GoogleApiClient.ConnectionCallbacks connectionCallbacks, GoogleApiClient.OnConnectionFailedListener failedListener)
    GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            //.requestServerAuthCode(activity.getString(R.string.server_client_id), false)
            .requestEmail()
            .requestScopes(new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE), new Scope(Scopes.FITNESS_BODY_READ_WRITE),
                    new Scope(Scopes.FITNESS_NUTRITION_READ_WRITE), new Scope(Scopes.FITNESS_LOCATION_READ_WRITE))
            .build();
    return new GoogleApiClient.Builder(activity)
                .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
                .addConnectionCallbacks(connectionCallbacks)
                .addOnConnectionFailedListener(failedListener)
                //.addApi(Plus.API)
                .addApi(Fitness.CONFIG_API)
                .addApi(Fitness.HISTORY_API)
                .addApi(Fitness.SESSIONS_API)
                .addApi(Fitness.RECORDING_API)
                .addApi(Fitness.BLE_API)
                .addApi(Fitness.SENSORS_API)
                .build();


//runs an automated Google Fit connect sequence
public static void googleFitConnect(final Activity activity, final GoogleApiClient mGoogleApiClient)
    if(!mGoogleApiClient.isConnected() && !mGoogleApiClient.isConnecting()) 
        mGoogleApiClient.registerConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() 
            @Override
            public void onConnected(Bundle bundle) 
                Log.i(TAG, "Google API connected");
                Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
                activity.startActivityForResult(signInIntent, FragmentLogin.REQUEST_OAUTH);
            
            @Override
            public void onConnectionSuspended(int i) 

            
        );
        mGoogleApiClient.connect(GoogleApiClient.SIGN_IN_MODE_OPTIONAL);
    


GoogleApiClient googleApiClient = googleFitBuild(activity, (MainActivity)activity, (MainActivity)activity);
googleFitConnect(activity, googleApiClient);

我之前也有一些接近 OP 代码的东西,但它突然决定停止工作……至少可以说令人沮丧。

【讨论】:

GoogleApiClient googleApiClient = googleFitBuild(activity, (MainActivity)activity, (MainActivity)activity); 此行给出错误,因为它的参数与函数参数不匹配 最后 2 个参数必须是实现 GoogleApiClient.ConnectionCallbacks 和 GoogleApiClient.OnConnectionFailedListener 的类(可能是 Activity 或 Fragment) googleFitBuild 和 googleFitConnect 应在 onStart 中调用。在 onCreate 中调用它们时,输出仍然是 RESULT_CANCELED。【参考方案5】:

就我而言,我更改了 apk 名称,但未能在 OAuth 凭据控制台中更新它。然后我的 onActivityResult 代码给了我 RESULT_CANCELLED。一旦我更正了 apk 名称,一切就又开始工作了。

【讨论】:

我遇到了同样的问题。在我的情况下,我更改了我的工作站并且 debug.keystore 的签名发生了更改,因此必须更新凭据。感谢您为我指明了正确的方向!【参考方案6】:

我遇到了类似的问题,并通过在 build.gradle 文件中统一 fitnessauth 依赖项的版本号来解决它。

implementation "com.google.android.gms:play-services-fitness:18.0.0"
implementation "com.google.android.gms:play-services-auth:18.0.0"

以前我使用auth:17.0.0,这导致该功能在随机基础上失败(是的,它有时有效,但在其他基础上失败)。

因此,如果上述解决方案没有帮助,我认为值得检查您的依赖关系。

【讨论】:

【参考方案7】:

我遇到了同样的问题,错误是我正在使用构建风格(完整、模拟),最终更改了包名称。 因此,在控制台中,我必须输入包的风味,而不是清单的风味。 希望这会有所帮助:)

【讨论】:

【参考方案8】:

就我而言,我尝试重用 Firebase 生成的 OAuth 客户端,但没有创建新客户端。这样做通常似乎没问题,但是,我从未在 Firebase 中启用 Google 身份验证(事实上,甚至没有 Firebase 身份验证)

我从没想过您还必须这样做,但事实证明,这对我有用!

要在 Firebase 中启用 Google 身份验证,请执行以下操作:

    在 Firebase 中展开左侧边栏并点击“身份验证”。 如果尚未启用,请启用身份验证。 在“登录方法”选项卡中,点击“Google”并启用它。

【讨论】:

以上是关于使用 Google Fit api 时的 Google Oauth 2.0 RESULT_CANCELED的主要内容,如果未能解决你的问题,请参考以下文章

如何在 php 中使用 Google Fit api 获取步数?

Google Fit API 登录卡在加载时

Google Fit REST API - 带有空格的 dataStreamId 导致错误

无法获得 Google fit 应用上显示的确切步骤

如何在Android模拟器中安装Google Fit应用?

谷歌钱包应用内付款:未捕获的 ReferenceError:未定义 goog。 google.payments 与 goog.payments