我有一个函数(不在活动中),它将图像上传到firebase存储并返回url。 我的问题是,我需要等待 UploadTask 完成,否则它会返回一个空字符串。
public String pushRegisterImage(Bitmap image) {
StorageReference imagesRef = storage.getReferenceFromUrl(STORAGE_REF)
.child(FINDMYPET).child(IMAGES).child(String.valueOf(UUID.randomUUID()));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] data = baos.toByteArray();
UploadTask uploadTask = imagesRef.putBytes(data);
uploadTask.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
imageUrl = null;
Log.e(LOG_TAG, "Image upload error: " + e);
}
}).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
@Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
imageUrl = taskSnapshot.getDownloadUrl().toString();
Log.v(LOG_TAG, "Image uploade sucess, url: " + imageUrl);
}
});
return imageUrl;
}
答案 0 :(得分:1)
我遇到了同样的问题:最适合我的解决方案是使用WorkManager和CountDownLatch
下面是代码片段,对我来说很有效。此处的日志来自Timber。在任务完成之后但在工作人员返回成功之前,它将作为字符串从Firebase返回downloadUrl。
@NonNull
@Override
public Result doWork() {
mFirebaseStorage = mFirebaseStorage.getInstance();
mTriviaImageStorageReference = mFirebaseStorage.getReference().child("images");
CountDownLatch countDown = new CountDownLatch(2);
Uri imageUri = Uri.parse(getInputData().getString(KEY_IMAGE_URI));
try {
// get the image reference
final StorageReference imageRef = mTriviaImageStorageReference.child(imageUri.getLastPathSegment());
// upload the image to Firebase
imageRef.putFile(imageUri).continueWithTask(new Continuation<UploadTask.TaskSnapshot, Task<Uri>>() {
@Override
public Task<Uri> then(@NonNull Task<UploadTask.TaskSnapshot> task) throws Exception {
if (!task.isSuccessful()) {
throw task.getException();
}
countDown.countDown();
return imageRef.getDownloadUrl();
}
}).addOnCompleteListener(new OnCompleteListener<Uri>() {
@Override
public void onComplete(@NonNull Task<Uri> task) {
if (task.isSuccessful()) {
Timber.d("Image was successfully uploaded to Firebase");
Uri downloadUri = task.getResult();
String imageUrl = downloadUri.toString();
Timber.d(("URl of the image is: " + imageUrl));
mOutputData = new Data.Builder()
.putString(KEY_FIREBASE_IMAGE_URL, imageUrl)
.build();
countDown.countDown();
} else {
Toast.makeText(getApplicationContext(), "upload failed", Toast.LENGTH_SHORT).show();
countDown.countDown();
}
}
});
countDown.await();
return Result.success(mOutputData);
} catch (Throwable throwable) {
Timber.e(throwable, "Error uploading image");
return Result.failure();
}
}
答案 1 :(得分:0)
使用此处提到的com.google.android.gms.tasks.Tasks.await(uploadTask);
:Firebase Storage upload synchronously。这解决了我的问题(我需要上传更多文件一个接一个)。此外,这不是要在UIThread上运行,因此请创建异步任务或类似的东西。
final UploadTask uploadTask
=FirebaseStorage.getInstance().getReference("...").putFile(path);
try {
com.google.android.gms.tasks.Tasks.await(uploadTask);
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d("Upload", "upload took " + (System.currentTimeMillis() - start));
答案 2 :(得分:-2)
您正在尝试将数据同步放入Firebase(并等待结果),但Android SDK提供的与Firebase数据库的所有交互都是异步的(这是一个实时数据库,与“同步”事情不太一样)所以有无法解决您的退货问题。
因此,回答您的问题是重新考虑您的代码,并记住Firebase的所有内容都是异步。