每次调用connect时,如何强制GoogleApiClient提示帐户选择器UI?

时间:2016-01-10 02:30:25

标签: android google-play-services google-drive-android-api

每当我在第一个应用程序启动周期中第一次运行代码时

GoogleApiClient mGoogleApiClient = new GoogleApiClient.Builder(context)
    .addApi(Drive.API)
    .addScope(Drive.SCOPE_APPFOLDER) // required for App Folder sample
    .addConnectionCallbacks(this)
    .addOnConnectionFailedListener(this)
    .build();

mGoogleApiClient.connect();

我可以看到以下帐号选择器。

enter image description here

但是,如果以前的连接成功,并且我第二次在第二次应用启动周期时再次运行相同的代码

帐户选择器不会再次弹出。 GoogleApiClient将使用帐户名称,我在之前的应用启动周期中选择。

我希望每次都能弹出我的帐号选择器。

我遇到了How to Clear GoogleApiClient Default Account and Credentials

建议的解决方案对我的案例不起作用。

mGoogleApiClient.clearDefaultAccountAndReconnect()

如果我已连接上一个应用周期,并且我在当前应用周期中第一次调用上述代码,则会出现以下异常。

java.lang.IllegalStateException: GoogleApiClient is not connected yet.
    at com.google.android.gms.common.internal.zzx.zza(Unknown Source)
    at com.google.android.gms.common.api.internal.zzj.clearDefaultAccountAndReconnect(Unknown Source)

以下代码也无法使用。

if (mGoogleApiClient.isConnected()) {
    // No chance to execute this code, if you run this code during app launch.
    mGoogleApiClient.clearDefaultAccountAndReconnect();
} else {
    // No account chooser will pop up if you had been connected in previous app life cycle
    mGoogleApiClient.connect();
}

我可以知道,每次调用connect时,如何强制GoogleApiClient提示帐户选择器UI?

8 个答案:

答案 0 :(得分:12)

GDAAREST Api中,您有两种选择:
1 /您没有指定帐户,底层系统将对其进行管理 2 /您自己管理帐户。

如果您使用第一种方法,则永远不会知道您的应用用户是谁。你只能清理'该帐户通过clearDefaultAccountAndReconnect。选择对话框再次弹出,用户可以选择(添加)另一个帐户。

如果您需要知道当前所选的用户帐户(即缓存/持久性),您必须自己管理帐户选择,因为您可以看到here (for REST)here (for GDAA) - 只需按照{{1跟踪和REQ_ACCPICK类。这样你就可以完全掌控了。

所以,对你的问题的简短回答是你弹出

UT.AM

自己活动并提供结果

startActivityForResult(AccountPicker.newChooseAccountIntent(null,
        null, new String[]{GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE}, true, null, null, null, null),
        REQ_ACCPICK);

email = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME) ,如下:

setAccountName(email)

祝你好运

答案 1 :(得分:4)

我想我迟到了,但这就是我解决它的方法。

在我开始显示构建器的Google SignIn Intent之前。 Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient); startActivityForResult(signInIntent, RC_SIGN_IN);

这样做:

if (mGoogleApiClient.hasConnectedApi(Auth.GOOGLE_SIGN_IN_API)) { mGoogleApiClient.clearDefaultAccountAndReconnect(); }

由于mGoogleApiClient由于某种原因存储登录用户。因此,即使您正在重新创建mGoogleApiClient.isConnected()的实例,如果执行mGoogleApiClient它也可能无法正常工作。但是,这将强制它清除已选择的用户。

经过测试,确实有效。

答案 2 :(得分:2)

看起来目前无法清除默认帐户,除非已连接GoogleApiClient。我们可以通过引入一个布尔标志来解决这个问题,告诉我们是否需要清除默认帐户。

private boolean mClearDefaultAccount;

@Override
public void onConnectionFailed(ConnectionResult result) {
    if (!mIntentInProgress && result.hasResolution()) {
        try {
            mIntentInProgress = true;
            mClearDefaultAccount = false;
            startIntentSenderForResult(result.getResolution().getIntentSender(),
                    GOOGLE_PLUS, null, 0, 0, 0);
        } catch (IntentSender.SendIntentException e) {
            mIntentInProgress = false;
            // report error
        }
    } else if (!mIntentInProgress) {
       // report error
    }
}

@Override
public void onConnected(Bundle bundle) {
    if (mClearDefaultAccount) {
        mClearDefaultAccount = false;
        mGoogleApiClient.clearDefaultAccountAndReconnect();
        return;
    }
    // connected...
}

在调用mGoogleApiClient.connect()之前,相应地设置布尔状态标志,以提示帐户根据需要使用当前默认帐户。 请注意,如果用户在设备上只有一个帐户,则可能会发生冗余connect()来电。

protected void connectToGoogleApi(final boolean clearDefaultAccount) {
    if (clearDefaultAccount && mGoogleApiClient.isConnected()) {
        mClearDefaultAccount = false;
        mGoogleApiClient.clearDefaultAccountAndReconnect();
    } else {
        mGoogleApiClient.connect();
    }
}

答案 3 :(得分:1)

如果API客户端未连接或连接,我发现重新创建API客户端更容易,然后再次提示输入帐户。

答案 4 :(得分:1)

通过上述解决方案的混合和匹配,我得到了它:

mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this, new GoogleApiClient.OnConnectionFailedListener() {
    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
    }
})
.addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
    @Override
    public void onConnected(@Nullable Bundle bundle) {
        mGoogleApiClient.clearDefaultAccountAndReconnect(); // To remove to previously selected user's account so that the choose account UI will show
    }

    @Override
    public void onConnectionSuspended(int i) {

    }
})
.addApi(Auth.GOOGLE_SIGN_IN_API, new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN).requestEmail().build())
.build();

希望能帮助他人节省一些时间。 =)

答案 5 :(得分:0)

每次调用connect 时,强制执行GoogleApiClient以提示帐户选择器UI的方法都非常糟糕。如果您有更好的方法,请告诉我们。

它围绕这个想法而建立。

  1. 如果显示了帐户选择器UI,则必须至少触发一次onConnectionFailed
  2. onConnected中,我们可以检查onConnectionFailed是否至少被触发一次。如果没有,我们会致电clearDefaultAccountAndReconnect
  3. 这是这个想法的完整代码。

    public class GoogleApiClientFragment extends Fragment implements
            GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
    
        public static GoogleApiClientFragment newInstance() {
            return new GoogleApiClientFragment();
        }
    
        /**
         * Handles resolution callbacks.
         */
        @Override
        public void onActivityResult(int requestCode, int resultCode,
                                        Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if (requestCode == RequestCode.REQUEST_GOOGLE_API_CLIENT_CONNECT && resultCode == Activity.RESULT_OK) {
                mGoogleApiClient.connect();
            }
        }
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setRetainInstance(true);
        }
    
        @Override
        public void onResume() {
            super.onResume();
            if (mGoogleApiClient == null) {
                mGoogleApiClient = new GoogleApiClient.Builder(this.getContext())
                    .addApi(Drive.API)
                    .addScope(Drive.SCOPE_APPFOLDER)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .build();
    
                accountPickerShown = false;
                mGoogleApiClient.connect();
            }
        }
    
        @Override
        public void onPause() {
            super.onPause();
            if (mGoogleApiClient != null) {
                mGoogleApiClient.disconnect();
            }
        }
    
        @Override
        public void onConnected(Bundle bundle) {
            Log.i(TAG, "GoogleApiClient connected");
    
            if (accountPickerShown == false && mGoogleApiClient.isConnected()) {
                mGoogleApiClient.clearDefaultAccountAndReconnect();
            }
        }
    
        @Override
        public void onConnectionSuspended(int i) {
            Log.i(TAG, "GoogleApiClient connection suspended");
        }
    
        @Override
        public void onConnectionFailed(ConnectionResult connectionResult) {
            Log.i(TAG, "GoogleApiClient connection failed: " + connectionResult.toString());
    
            if (!connectionResult.hasResolution()) {
                // show the localized error dialog.
                GoogleApiAvailability.getInstance().getErrorDialog(this.getActivity(), connectionResult.getErrorCode(), 0).show();
                return;
            }
            try {
                accountPickerShown = (connectionResult.getErrorCode() == ConnectionResult.SIGN_IN_REQUIRED);
                connectionResult.startResolutionForResult(this.getActivity(), RequestCode.REQUEST_GOOGLE_API_CLIENT_CONNECT);
            } catch (IntentSender.SendIntentException e) {
                Log.e(TAG, "Exception while starting resolution activity", e);
            }
        }
    
        private boolean accountPickerShown = false;
        private static final String TAG = "GoogleApiClientFragment";
        private GoogleApiClient mGoogleApiClient;
    }
    

答案 6 :(得分:0)

接受的解决方案确实有效(如果您想将更新版本的API导入您的应用程序,您还必须包含google-play-services-auth api),但帐户选择器将会以不同的风格出现,可能会使用户感到困惑或担忧。

如果您希望保持UI统一并且不想包含google-play-services-auth API,我提供了2个备用解决方案。

您可以拨打mGoogleApiClient.clearDefaultAccountAndReconnect(),然后只要您想强制用户选择帐户,就可以通过拨打mGoogleApiClient.disconnect()立即断开连接。通过这样做,您可以在下次用户连接时调用mGoogleApiClient.connect()连接(强制帐户选择器)。当您希望触发用户再次选择帐户的特定事件时,此功能非常有用。

另一种(更普遍有用的)解决方案是以相同的方式执行以下操作(在后台线程中,可能是AsyncTask)而不是最终的代码块:

mGoogleApiClient.blockingConnect();
if (mGoogleApiClient.isConnected()) {
    mGoogleApiClient.clearDefaultAccountAndReconnect();
}

这将避免您看到的空指针异常,并将显式强制帐户选择器。这是有点奇怪,因为你连接两次,但它的工作原理。

如果Google明确地在GoogleApiClient中提供此功能,那就太好了。

答案 7 :(得分:0)

问题是您退出了内部活动,而不是从 signIn 中退出,但是如果您每次都在登录前退出,则问题将得到解决。 简单的! ,只需添加

mGoogleSignInClient.signOut();

在您开始登录之前,即:

Intent signInIntent = mGoogleSignInClient.getSignInIntent(); 

这将在您登录之前注销任何用户。