Firebase存储等待侦听器

时间:2017-03-24 16:14:44

标签: android task firebase-storage

我有一个函数(不在活动中),它将图像上传到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;
}

3 个答案:

答案 0 :(得分:1)

我遇到了同样的问题:最适合我的解决方案是使用WorkManagerCountDownLatch

下面是代码片段,对我来说很有效。此处的日志来自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的所有内容都是异步