如何在Android One Tap登录中使用Google Activity Result API
Android One Tap登录适配Activity Result API问题记录
我在自己的Android应用中接入One Tap登录认证功能时,发现startActivityForResult方法已被官方标记废弃,官方建议传入对应ActivityResultContract调用registerForActivityResult方法替代。最开始我参照示例写出的代码如下:
public class MainActivity extends AppCompatActivity { private SignInClient oneTapClient; private BeginSignInRequest signInRequest; private ActivityResultLauncher<Intent> loginResultHandler = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> { // 此处处理返回结果 if (result.getResultCode() == RESULT_OK) { SignInCredential credential = null; try { credential = oneTapClient.getSignInCredentialFromIntent(result.getData()); String idToken = credential.getGoogleIdToken(); String username = credential.getId(); String password = credential.getPassword(); if (idToken != null) { // 从Google获取到ID token,可用于后端身份校验 Log.d(TAG, "Got ID token."); } else if (password != null) { // 获取到保存的账号密码,可用于后端身份校验 Log.d(TAG, "Got password."); } } catch (ApiException e) { e.printStackTrace(); } } else { //... } }); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //... oneTapClient.beginSignIn(signInRequest) .addOnSuccessListener(this, new OnSuccessListener<BeginSignInResult>() { @Override public void onSuccess(BeginSignInResult result) { /*try { android.app.Activity.startIntentSenderForResult(result.getPendingIntent().getIntentSender(), REQ_ONE_TAP, null, 0, 0, 0); } catch (IntentSender.SendIntentException e) { Log.e(TAG, "Couldn't start One Tap UI: " + e.getLocalizedMessage()); }*/ loginResultHandler.launch(result.getPendingIntent().getIntentSender()); } }) .addOnFailureListener(this, new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { // 未找到保存的凭据,可拉起One Tap注册流程,或者不处理保持未登录状态 Log.d(TAG, e.getLocalizedMessage()); } }); } }
此时遇到的问题是:getIntentSender()返回的是IntentSender类型,但我声明的loginResultHandler.launch()要求传入Intent类型参数,不知道如何按照Activity Result API规范调整这部分逻辑。
最终可运行实现方案
最终我按如下方式重写了代码,经过测试,账户选择界面及后续流程均可正常运行:
public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; private SignInClient oneTapClient; private BeginSignInRequest signInRequest; private boolean showOneTapUI = true; private ActivityResultLauncher<IntentSenderRequest> loginResultHandler = registerForActivityResult(new ActivityResultContracts.StartIntentSenderForResult(), result -> { // 处理返回结果 if (result.getResultCode() == RESULT_OK) Log.d(TAG, "RESULT_OK."); if (result.getResultCode() == RESULT_CANCELED) Log.d(TAG, "RESULT_CANCELED."); if (result.getResultCode() == RESULT_FIRST_USER) Log.d(TAG, "RESULT_FIRST_USER."); try { SignInCredential credential = oneTapClient.getSignInCredentialFromIntent(result.getData()); String idToken = credential.getGoogleIdToken(); String username = credential.getId(); String password = credential.getPassword(); if (idToken != null) { // 从Google获取到ID token,可用于后端身份校验 Log.d(TAG, "Got ID token."); } else if (password != null) { // 获取到保存的账号密码,可用于后端身份校验 Log.d(TAG, "Got password."); } } catch (ApiException e) { switch (e.getStatusCode()) { case CommonStatusCodes.CANCELED: Log.d(TAG, "One-tap dialog was closed."); // 用户主动关闭弹窗,不要重复拉起避免打扰用户 showOneTapUI = false; break; case CommonStatusCodes.NETWORK_ERROR: Log.d(TAG, "One-tap encountered a network error."); // 可重试或者忽略 break; default: Log.d(TAG, "Couldn't get credential from result." + e.getLocalizedMessage()); break; } } }); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //... oneTapClient.beginSignIn(signInRequest) .addOnSuccessListener(this, new OnSuccessListener<BeginSignInResult>() { @Override public void onSuccess(BeginSignInResult result) { try { loginResultHandler.launch(new IntentSenderRequest.Builder(result.getPendingIntent().getIntentSender()).build()); } catch(android.content.ActivityNotFoundException e){ e.printStackTrace(); Log.e(TAG, "Couldn't start One Tap UI: " + e.getLocalizedMessage()); } } }) .addOnFailureListener(this, new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { // 未找到保存的凭据,可拉起One Tap注册流程,或者不处理保持未登录状态 Log.d(TAG, e.getLocalizedMessage()); } }); } }
核心修正点如下:
- 将原来使用的
ActivityResultContracts.StartActivityForResult替换为适配IntentSender的ActivityResultContracts.StartIntentSenderForResult - 对应的
ActivityResultLauncher泛型从Intent修改为IntentSenderRequest - 调用launch方法时,将获取到的
IntentSender通过IntentSenderRequest.Builder包装为IntentSenderRequest类型后传入即可
内容的提问来源于stack exchange,提问作者teb585
相关产品推荐
相关产品推荐

