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

Android原生应用Google一键登录触发空指针异常求助

Google一键登录(One Tap)空指针异常修复方案

问题描述

集成Google一键登录功能时,点击登录按钮执行activityResultLauncher.launch(intentSenderRequest)代码,触发如下空指针异常:

java.lang.NullPointerException: Attempt to invoke virtual method 'android.app.ActivityThread$ApplicationThread android.app.ActivityThread.getApplicationThread()' on a null object reference

问题根源

  1. ActivityResultLauncher注册时机错误:在login方法内临时注册Launcher,而非在Activity生命周期早期(如onCreate)完成注册,导致异步回调时Launcher与Activity生命周期绑定失效。
  2. 局部变量生命周期问题:Launcher作为login方法的局部变量,异步回调触发时可能已被GC回收,引发上下文空指针。
  3. 上下文强转风险:将传入的context强转为Activity,存在上下文类型不匹配的隐患。

修复代码示例

public class Googlelogin extends AppCompatActivity implements SocialLoginswwwwwwwwwwwwwwwwwwwwwwwwww, GoogleApiClient.OnConnectionFailedListener  {

    private SignInClient oneTapClient;
    private BeginSignInRequest signInRequest;
    private ActivityResultLauncher<IntentSenderRequest> activityResultLauncher;
    private static final String TAG = "GoogleLogin";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 必须在Activity生命周期早期注册ActivityResultLauncher
        activityResultLauncher = registerForActivityResult(
                new ActivityResultContracts.StartIntentSenderForResult(),
                result -> {
                    try {
                        SignInCredential credential = oneTapClient.getSignInCredentialFromIntent(result.getData());
                        String idToken = credential.getGoogleIdToken();
                        if (idToken != null) {
                            String email = credential.getId();
                            String username = credential.getDisplayName();
                            Toast.makeText(Googlelogin.this, "Email : " + email + " Name : " + username, Toast.LENGTH_SHORT).show();
                        }
                    } catch (ApiException e) {
                        e.printStackTrace();
                    }
                });
    }

    @RequiresApi(api = Build.VERSION_CODES.DONUT)
    @Override
    public void login(Context context) {
        // 使用当前Activity自身上下文,避免强转风险
        oneTapClient = Identity.getSignInClient(this);
        signInRequest = BeginSignInRequest.builder()
                .setPasswordRequestOptions(BeginSignInRequest.PasswordRequestOptions.builder()
                        .setSupported(true)
                        .build())
                .setGoogleIdTokenRequestOptions(BeginSignInRequest.GoogleIdTokenRequestOptions.builder()
                        .setSupported(true)
                        .setServerClientId("885176601647-qnk12j18ln08dhhhal4lgprmlrreor1q.apps.googleusercontent.com")
                        .setFilterByAuthorizedAccounts(true)
                        .build())
                .setAutoSelectEnabled(true)
                .build();

        oneTapClient.beginSignIn(signInRequest)
                .addOnSuccessListener(this, result -> {
                    IntentSenderRequest intentSenderRequest =
                            new IntentSenderRequest.Builder(result.getPendingIntent().getIntentSender()).build();
                    activityResultLauncher.launch(intentSenderRequest);
                })
                .addOnFailureListener(this, e -> {
                    Log.d(TAG, e.getLocalizedMessage());
                    Toast.makeText(this, e.getLocalizedMessage(), Toast.LENGTH_SHORT).show();
                });
    }
}

关键修复点

  • 提前注册Launcher:在onCreate方法中完成ActivityResultLauncher的注册,确保其与Activity生命周期绑定,避免回调时上下文失效。
  • 改用类成员变量:将Launcher、oneTapClient、signInRequest设为类成员变量,保证异步回调时变量仍处于有效生命周期内。
  • 直接使用Activity上下文:当前类继承自AppCompatActivity,直接用this替代传入的context,消除强转带来的风险。

内容的提问来源于stack exchange,提问作者sejn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 16:25:26