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

创建用户时调用setPhotoUri报错:对象不存在于指定位置

问题根源:异步操作顺序错误

你遇到的com.google.firebase.storage.StorageException: Object does not exist at location错误,核心原因是Firebase的Storage操作是异步执行的,你的代码没有等待图片上传完成就去获取下载URL,而且更新用户资料的逻辑也跑在了URL获取完成之前。

具体来说:

  • 调用uploadImage()后立刻执行getImageUrl(),但ref.putFile(filePath)还在后台上传,这时候Storage里还没有这个文件,自然会提示"对象不存在"。
  • 就算上传侥幸完成了,downloadUri的赋值也是在getImageUrl()的异步回调里,你在回调外部直接调用user.updateProfile(profileUpdates)时,downloadUri大概率还是null,根本没拿到正确的URL。
解决方案:按异步流程链式调用

我们需要把操作按顺序串起来:用户创建成功 → 上传图片(等待完成)→ 获取下载URL(等待完成)→ 更新用户资料 → 后续逻辑。

下面是修改后的完整代码:

1. 调整创建用户的逻辑

auth.createUserWithEmailAndPassword(email, password)
    .addOnCompleteListener(SignupActivity.this, new OnCompleteListener<AuthResult>() {
        @Override
        public void onComplete(@NonNull Task<AuthResult> task) {
            Toast.makeText(SignupActivity.this, "createUserWithEmail:onComplete:" + task.isSuccessful(), Toast.LENGTH_SHORT).show();
            progressBar.setVisibility(View.GONE);

            if (!task.isSuccessful()) {
                Toast.makeText(SignupActivity.this, "Authentication failed." + task.getException(), Toast.LENGTH_SHORT).show();
            } else {
                user = auth.getCurrentUser();
                if(user != null){
                    // 调用带回调的上传方法,确保上传完成后再执行后续操作
                    uploadImageAndProceed();
                }
            }
        }
    });

2. 重构上传和获取URL的方法

private void uploadImageAndProceed() {
    if(filePath != null && user != null) {
        ref = storageReference.child("UserProfileImages/" + user.getEmail());
        // 等待上传完成后再执行下一步
        ref.putFile(filePath)
            .addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                @Override
                public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                    // 上传成功后,获取下载URL
                    getImageUrlAndUpdateProfile();
                }
            })
            .addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {
                    Toast.makeText(SignupActivity.this, "图片上传失败:" + e.getMessage(), Toast.LENGTH_SHORT).show();
                }
            });
    } else {
        Toast.makeText(SignupActivity.this, "请选择要上传的图片", Toast.LENGTH_SHORT).show();
    }
}

private void getImageUrlAndUpdateProfile() {
    ref.getDownloadUrl()
        .addOnSuccessListener(new OnSuccessListener<Uri>() {
            @Override
            public void onSuccess(Uri uri) {
                downloadUri = uri;
                Log.i("Class","Photo URL: " + downloadUri);

                // 拿到URL后,再更新用户资料
                UserProfileChangeRequest profileUpdates = new UserProfileChangeRequest.Builder()
                        .setPhotoUri(downloadUri)
                        .setDisplayName(displayNameString)
                        .build();

                user.updateProfile(profileUpdates)
                    .addOnSuccessListener(new OnSuccessListener<Void>() {
                        @Override
                        public void onSuccess(Void unused) {
                            // 资料更新成功后,再执行退出登录和跳转逻辑
                            FirebaseAuth.getInstance().signOut();
                            Intent intent = new Intent(SignupActivity.this, LoginActivity.class);
                            intent.putExtra("Email", user.getEmail());
                            if (downloadUri != null){
                                intent.putExtra("Image", downloadUri.toString());
                            }
                            startActivity(intent);
                            Toast.makeText(SignupActivity.this, "Verifique su contraseña", Toast.LENGTH_SHORT).show();
                        }
                    })
                    .addOnFailureListener(new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e) {
                            Toast.makeText(SignupActivity.this, "更新用户资料失败:" + e.getMessage(), Toast.LENGTH_SHORT).show();
                        }
                    });
            }
        })
        .addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception exception) {
                Log.i("Class","获取图片URL出错:" + exception.toString());
                Toast.makeText(SignupActivity.this, "获取图片URL失败:" + exception.getMessage(), Toast.LENGTH_SHORT).show();
            }
        });
}
关键修改点说明
  • 将上传和URL获取的逻辑链式绑定,确保每一步都等待前一步异步操作完成。
  • 把用户资料更新的代码移到getDownloadUrl()的成功回调里,保证downloadUri已经被正确赋值。
  • 给每个异步操作都添加了OnFailureListener,方便排查错误。
  • 跳转逻辑放在updateProfile()的成功回调里,确保用户资料已经更新完成。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:01:18