Google Sign In for Android:无法解决RC_SIGN_IN

6
我正在尝试使用手机应用程序对后端服务器进行身份验证。 我正在遵循这个文档。 https://developers.google.com/identity/sign-in/android/sign-in 然而,出现了一些错误。 RC_SIGN_INupdateUI() 无法解决。
我的代码如下:
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {

    ...

       GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestEmail()
            .build();

       mGoogleSignInClient = GoogleSignIn.getClient(this, gso);

        mSignInButton = findViewById(R.id.sign_in_button);
        mSignInButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Toast.makeText(MainActivity.this, "Hello", Toast.LENGTH_LONG).show();
            Intent signIntent = mGoogleSignInClient.getSignInIntent();
            startActivityForResult(signIntent, RC_SIGN_IN);
        }
    });


   @Override
   protected void onStart() {
        GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(this);
        updateUI(account);
        super.onStart();
    }


    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    // Result returned from launching the Intent from GoogleSignInClient.getSignInIntent(...);
    if (requestCode == RC_SIGN_IN) {
        // The Task returned from this call is always completed, no need to attach
        // a listener.
        Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
        handleSignInResult(task);
    }
}


   private void handleSignInResult(Task<GoogleSignInAccount> completedTask) {
       try {
           GoogleSignInAccount account = completedTask.getResult(ApiException.class);
           String idToken = account.getIdToken();

           // Send Id Token to the backend and validate here

           // Signed in successfully, show authenticated UI.
           updateUI(account);
       } catch (ApiException e) {
           // The ApiException status code indicates the detailed failure reason.
           // Please refer to the GoogleSignInStatusCodes class reference for more information.
           Log.w(TAG, "signInResult:failed code=" + e.getStatusCode());
           updateUI(null);
       }
   }

更新

现在按钮本身不起作用。

xml

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">

<!-- Include the main content -->
<FrameLayout
    android:id="@+id/content_frame"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <com.google.android.gms.common.SignInButton
        android:id="@+id/sign_in_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/text_view_result"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#000"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </android.support.v4.widget.NestedScrollView>

</FrameLayout>

<!-- Navigation bar -->
<android.support.design.widget.NavigationView
    android:id="@+id/nav_view"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:fitsSystemWindows="true"
    app:menu="@menu/navigation_menu"/>

</android.support.v4.widget.DrawerLayout>

我该怎么修复这个问题?


mSignInButton 是 SignInButton 类型吗? - Gourav
你是在模拟器上进行检查吗?如果是的话,你首先需要在模拟器中添加一个Google账户。前往Gmail应用程序并在那里添加一个Google账户。 - Gourav
我已经移除了 switch 语句,并且我的 Google 帐户已经添加到模拟器上,但仍然无法工作。 - user11016692
@MartinZeitler 我的模拟器启用了Play服务。即使在真实设备上仍然无法工作... - user11016692
@Wineseller,可能存在Play Services插件的问题,这可能导致google_services.json无法解析-然后在字符串资源中没有clientId,那个按钮将无法工作...这是另一个前提条件。 - Martin Zeitler
显示剩余6条评论
3个回答

6
您无需做任何事情,只需将RC_SIGN_IN替换为一个整数值。它可以是任何数字,但使用1作为其值。按照以下步骤操作:
startActivityForResult(signIntent, 1);

将活动结果中的if代码更改为以下内容:

if (requestCode == 1)

同时将登录按钮的点击代码更改为以下内容(删除switch cases):

mSignInButton.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View view) {
                      signIn();
               }
           }
       });

这是因为您在调用按钮的点击方法,然后再次检查是否单击了同一按钮,这就是我认为它不起作用的原因。
现在对于updateUI方法,此方法应由您定义。基本上,这是为了让您的应用程序在用户登录应用程序时更改向其显示的内容。如果您想要在signedIn()时打开新活动,则可以通过将updateUI(account)更改为意图来使用Intent
startActivity(new Intent(MainActivity.this, SecondActivity.class));

SecondActivity中获取已登录的帐户:

GoogleSignInAccount account = GoogleSignIn.g etLastSignedInAccount(this); //use this in onCreate

感谢您的回答。但是sign_in_button本身根本无法工作。我尝试在OnClickListener中设置Toast,但它并没有显示出来。 - user11016692
你是否遇到了任何空指针引用的问题,或者如果应用程序崩溃了,请在问题中添加堆栈跟踪信息? - Gourav
请在代码中定义按钮的 ID 并对其进行初始化。 - Gourav
应用程序没有崩溃。按钮本身只是不起作用。 - user11016692
无论如何,非常感谢您的耐心帮助。我已经为您的答案点赞了。 - user11016692

3

RC_SIGN_IN 基本上是一个整数编码,用于标识您的 onActivityResult 被调用以进行 Google 登录。

 private static final int RC_SIGN_IN = 007;

updateUi()是一个方法,用于告知用户Google登录是否成功。以下是该方法:

private void updateUI(GoogleSignInAccount signedIn) {
  if (signedIn != null) {
      // sigin is successfull
      signInButton.setVisibility(View.GONE);
      signOutButton.setVisibility(View.VISIBLE);
  } else {
      // sigin is cancelled
      signInButton.setVisibility(View.VISIBLE);
      signOutButton.setVisibility(View.GONE);
  }
}

谢谢,错误已经修复了。但是 sign_in_button 没有起作用。当我点击它时什么也没有发生。 - user11016692

3

试试这个。

在MainActivity中,实现View.OnClickListener和GoogleApiClient.OnConnectionFailedListener。

private static final String TAG = MainActivity.class.getSimpleName();
private static final int RC_SIGN_IN = 007;
private GoogleApiClient mGoogleApiClient;

GoogleSignInOptions gso = new 
GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestEmail()
            .build();

GoogleApiClient = new GoogleApiClient.Builder(this)
            .enableAutoManage(this, this)
            .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
            .build();

btnSignIn.setSize(SignInButton.SIZE_STANDARD);
btnSignIn.setScopes(gso.getScopeArray());


private void handleSignInResult(GoogleSignInResult result) {
    Log.d(TAG, "handleSignInResult:" + result.isSuccess());
    if (result.isSuccess()) {
        // Signed in successfully, show authenticated UI.
        GoogleSignInAccount acct = result.getSignInAccount();

        Log.e(TAG, "display name: " + acct.getDisplayName());

        String personName = acct.getDisplayName();
        String personPhotoUrl = acct.getPhotoUrl().toString();
        String email = acct.getEmail();

        Log.e(TAG, "Name: " + personName + ", email: " + email
                + ", Image: " + personPhotoUrl);

        txtName.setText(personName);
        txtEmail.setText(email);
        Glide.with(getApplicationContext()).load(personPhotoUrl)
                .thumbnail(0.5f)
                .into(imgProfilePic);

        updateUI(true);
    } else {
        // Signed out, show unauthenticated UI.
        updateUI(false);
    }
}


private void signIn() {
    Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
    startActivityForResult(signInIntent, RC_SIGN_IN);
}

private void signOut() {
    Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
            new ResultCallback<Status>() {
                @Override
                public void onResult(Status status) {
                    updateUI(false);
                }
            });
}


private void revokeAccess() {
    Auth.GoogleSignInApi.revokeAccess(mGoogleApiClient).setResultCallback(
            new ResultCallback<Status>() {
                @Override
                public void onResult(Status status) {
                    updateUI(false);
                }
            });
}
@Override
public void onClick(View v) {
    int id = v.getId();

    switch (id) {
        case R.id.btn_sign_in:
            signIn();
            break;

        case R.id.btn_sign_out:
            signOut();
            break;

        case R.id.btn_revoke_access:
            revokeAccess();
            break;
    }

}


@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    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);
    }
}

@Override
public void 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);
            }
        });
    }
}

@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
    Log.d(TAG, "onConnectionFailed:" + connectionResult);
}

private void updateUI(boolean isSignedIn) {
    if (isSignedIn) {
        btnSignIn.setVisibility(View.GONE);
        btnSignOut.setVisibility(View.VISIBLE);
        btnRevokeAccess.setVisibility(View.GONE);
        llProfileLayout.setVisibility(View.VISIBLE);
    } else {
        btnSignIn.setVisibility(View.VISIBLE);
        btnSignOut.setVisibility(View.GONE);
        btnRevokeAccess.setVisibility(View.GONE);
        llProfileLayout.setVisibility(View.GONE);
    }
}

实际上,我已经尝试过实现ViewOnClickListner并覆盖OnClick方法,但仍然没有任何反应。 - user11016692
我注意到一个问题。只有 SignButton 不起作用。我尝试了登录按钮,它可以工作。 - user11016692

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接