You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 23:36:04