Google Drive API开发中onActivityResult未回调致空实例
核心根因
你遇到的现象不属于“回调不触发”的bug,本质是对Android startActivityForResult的异步执行逻辑认知错误:
startActivityForResult是非阻塞方法,调用后系统会立刻暂停当前页面的执行流程,跳转至Google账号授权界面,代码不会等待用户完成登录操作再继续向下运行。- 你在
onCreate中将uploadPdfFile()写在requestSignIn()的下一行,相当于登录流程刚发起、还未弹出账号选择界面时,上传逻辑就已经开始执行,此时driveServiceHelper根本没有完成初始化,取值自然为null。 onActivityResult的触发时机并不在startActivityForResult的代码块内,只有当用户在授权页完成账号选择、授权/取消操作,系统关闭登录页、将控制权交回MainActivity时,才会触发该回调。
代码存在的具体问题
- 执行逻辑顺序错误:将需要等待登录授权完成才能执行的上传操作,放在了登录流程的同步执行流中调用。
- 缺少空值判断:
uploadPdfFile()方法中直接调用driveServiceHelper的实例方法,未判空时遇到null会直接抛出空指针异常导致程序崩溃。 - 废弃API兼容风险:
startActivityForResult已在AndroidX中标记废弃,当targetSdk版本为30及以上时,存在回调无法正常触发的兼容问题。 - 异常处理缺失:登录失败、用户取消授权的回调逻辑为空,出现问题时没有任何用户可见的提示。
可直接落地的修改步骤
- 调整
onCreate的启动逻辑,删除页面启动时直接调用uploadPdfFile()的代码,增加登录状态前置检查:@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 保留原有Toolbar、悬浮按钮的初始化代码 GoogleSignInAccount lastSignedInAccount = GoogleSignIn.getLastSignedInAccount(this); if (lastSignedInAccount != null) { // 已有有效登录记录,直接初始化服务后执行上传 initDriveService(lastSignedInAccount); uploadPdfFile(); } else { // 无有效登录时再发起授权流程 requestSignIn(); } } - 将
handleSignalInIntent中的DriveServiceHelper初始化逻辑抽成公共方法,方便登录成功后复用:private void initDriveService(GoogleSignInAccount googleSignInAccount) { GoogleAccountCredential credential = GoogleAccountCredential .usingOAuth2(MainActivity.this, Collections.singleton(DriveScopes.DRIVE_FILE)); credential.setSelectedAccountName(googleSignInAccount.getAccount().name); Drive googleDriveService = new Drive.Builder( AndroidHttp.newCompatibleTransport(), new GsonFactory(), credential) .setApplicationName("My Drive Tutorial") .build(); driveServiceHelper = new DriveServiceHelper(googleDriveService); } - 修改
onActivityResult的回调逻辑,等初始化完成后再触发上传:@Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case 400: if (resultCode == RESULT_OK) { GoogleSignIn.getSignedInAccountFromIntent(data) .addOnSuccessListener(googleSignInAccount -> { initDriveService(googleSignInAccount); // 服务初始化完成后再执行上传操作 uploadPdfFile(); }) .addOnFailureListener(e -> Toast.makeText(this, "登录授权失败,请重试", Toast.LENGTH_SHORT).show()); } break; } } - 给
uploadPdfFile()增加空值判断,避免崩溃:private void uploadPdfFile() { if (driveServiceHelper == null) { Toast.makeText(this, "请先完成Google账号登录授权", Toast.LENGTH_SHORT).show(); return; } // 保留原有上传的进度弹窗、文件上传逻辑 }
补充说明
- 所有依赖异步流程结果的操作,都必须放到对应的异步回调中触发,不能和异步流程的调用放在同一同步执行流里顺序执行。
- 适配新版本Android时,建议将废弃的
startActivityForResult替换为官方推荐的Activity Result API,从根源上避免版本兼容导致的回调丢失问题。
内容的提问来源于stack exchange,提问作者Thomas Suditu
相关产品推荐
相关产品推荐

