【问题标题】:Illegal state exception while calling signout through GoogleApiClient通过 GoogleApiClient 调用注销时出现非法状态异常
【发布时间】:2015-12-20 05:35:01
【问题描述】:

我想实现一个 Google 登录活动,成功后会打开我的下一个活动。如果用户从下一个活动中注销,我想返回 Google 登录活动并退出。但是,当我在 onActivityResult 中调用注销时,出现以下异常

Caused by: java.lang.IllegalStateException: GoogleApiClient is not connected yet.

这是相关代码

public class LoginActivity extends AppCompatActivity implements
    GoogleApiClient.OnConnectionFailedListener,
    View.OnClickListener {

private static final String TAG = "LoginActivity";
private static final int RC_SIGN_IN = 9001;

private GoogleApiClient mGoogleApiClient;
private GoogleSignInOptions gso;
private TextView mStatusTextView;
private ProgressDialog mProgressDialog;

@Override
protected void onCreate(Bundle savedInstanceState) {
    Log.d(TAG, "onCreate()");
    super.onCreate(savedInstanceState);
    setContentView(R.layout.signin_activity);

    // Views
    mStatusTextView = (TextView) findViewById(R.id.status);

    // Button listeners
    findViewById(R.id.sign_in_button).setOnClickListener(this);
    findViewById(R.id.sign_out_button).setOnClickListener(this);
    findViewById(R.id.disconnect_button).setOnClickListener(this);

    // [START configure_signin]
    // Configure sign-in to request the user's ID, email address, and basic
    // profile. ID and basic profile are included in DEFAULT_SIGN_IN.
    gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestEmail()
            .build();
    // [END configure_signin]

    // [START build_client]
    // Build a GoogleApiClient with access to the Google Sign-In API and the
    // options specified by gso.
    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
            .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
            .build();
    // [END build_client]

    SignInButton signInButton = (SignInButton) findViewById(R.id.sign_in_button);
    signInButton.setSize(SignInButton.SIZE_STANDARD);
    signInButton.setScopes(gso.getScopeArray());
    // [END customize_button]
}

@Override
public void onStart() {
    Log.d(TAG, "onStart()");
    super.onStart();
    OptionalPendingResult<GoogleSignInResult> opr = Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient);
        if (opr.isDone()) {
            // If the user's cached credentials are valid, the OptionalPendingResult will be "done"

            // and the GoogleSignInResult will be available instantly.
            Log.d(TAG, "Got cached sign-in");
            GoogleSignInResult result = opr.get();
            handleSignInResult(result);
        } else {
            // If the user has not previously signed in on this device or the sign-in has
            // expired,
            // this asynchronous branch will attempt to sign in the user silently.  Cross-device
            // single sign-on will occur in this branch.
            showProgressDialog();
            opr.setResultCallback(new ResultCallback<GoogleSignInResult>() {
                @Override
                public void onResult(GoogleSignInResult googleSignInResult) {
                    hideProgressDialog();
                    handleSignInResult(googleSignInResult);
                }
            });
        }
}

// [START onActivityResult]
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    Log.d(TAG, "onActivityResult()");
    super.onActivityResult(requestCode, resultCode, data);

    // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
    if (requestCode == RC_SIGN_IN) {
        GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
        handleSignInResult(result);
    }
    else if (requestCode == Constants.MAPS_ACTIVITY_FINISHED) {
        if (resultCode == Constants.SIGNOUT) {
            signOut();
        }
    }
}
// [END onActivityResult]


// [START handleSignInResult]
private void handleSignInResult(GoogleSignInResult result) {
    Log.d(TAG, "handleSignInResult:" + result.isSuccess());
    if (result.isSuccess()) {
        // Signed in successfully, show authenticated UI.
        GoogleSignInAccount acct = result.getSignInAccount();
        mStatusTextView.setText(getString(R.string.signed_in_fmt, acct.getDisplayName()));
        updateUI(true);
        Intent intent = new Intent(this, MapsActivity.class);
        startActivityForResult(intent, Constants.MAPS_ACTIVITY_FINISHED);
    } else {
        // Signed out, show unauthenticated UI.
        updateUI(false);
    }
}
// [END handleSignInResult]

// [START signIn]
private void signIn() {
    Log.d(TAG, "signin()");
    Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
    startActivityForResult(signInIntent, RC_SIGN_IN);
}
// [END signIn]

// [START signOut]
private void signOut() {
    Log.d(TAG, "signout()");
    Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
            new ResultCallback<Status>() {
                @Override
                public void onResult(Status status) {
                    // [START_EXCLUDE]
                    updateUI(false);
                    // [END_EXCLUDE]
                }
            });
}
// [END signOut]
}

【问题讨论】:

    标签: android google-api-client illegalstateexception


    【解决方案1】:

    根据Javadoc

    1) 退出:

    public abstract PendingResult<Status> signOut (GoogleApiClient client)
    Parameters
    client  The connected GoogleApiClient to service the call.
    

    2) 获取SignInIntent

    public abstract Intent getSignInIntent (GoogleApiClient client)
    Parameters
    client  The GoogleApiClient to service the call.
    

    signOut 调用需要已连接 GoogleApiClient;而 getSignInIntent() 没有。在谷歌的示例中,退出按钮只有在登录后才会启用,这样可以保证连接的 GoogleApiClient。但是,在您的情况下,您需要在调用 signOut 之前显式收听 onConnected。您可以使用 GoogleApiClient.Builder.addConnectionCallbacks 注册一个 onConnected 侦听器,并确保将 signOut 请求排队,直到回调 onConnected。

    (由于您使用了 autoManage,GoogleApiClient 内部将在 onStart() 中自动连接并在 onStop 中自动断开连接)

    【讨论】:

      【解决方案2】:

      您的异常告诉您问题所在:您的客户端未连接。首先,我建议您查看this guide 关于 Google API 客户端的信息。

      无论如何,您应该在应用程序的某处添加以下代码:

      mGoogleApiClient.connect();
      

      此代码将发送连接请求,如果一切正常,您的客户端将连接。之后,在使用之前,请检查客户端是否已连接,以避免以后出现此错误:

      if (mGoogleApiClient.isConnected()) {
          // do your stuff with Google Api Client
      }
      

      【讨论】:

        猜你喜欢
        • 2014-02-12
        • 1970-01-01
        • 1970-01-01
        • 2013-02-06
        • 1970-01-01
        • 2012-06-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多