【问题标题】:Firebase StorageReference.getFile is not working - FirebaseStorage AndroidFirebase StorageReference.getFile 不工作 - FirebaseStorage Android
【发布时间】:2020-06-05 05:57:10
【问题描述】:

我正在尝试从 Firebase Storage 下载我的 AsyncTask 中的文件,如下所示:

static class DownloadFileFromFireBase extends AsyncTask<String, Void, Boolean> {
    File file;
    String fileName;
    boolean downloadStatus = false;
    public DownloadFileFromFireBase(Context context,String fileName, File file){
        this.fileName = fileName;
        this.file = file;
    }
    protected Boolean doInBackground(String... urls) {
        FirebaseStorage storage = FirebaseStorage.getInstance();
        StorageReference storageRef = storage.getReference();
        StorageReference dataRef = storageRef.child(fileName);
        try {
            file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        dataRef.getFile(file).addOnSuccessListener(new OnSuccessListener<FileDownloadTask.TaskSnapshot>() {
            @Override
            public void onSuccess(FileDownloadTask.TaskSnapshot taskSnapshot) {
                Log.d(TAG,"File Downloaded");
                downloadStatus = true;
            }
        }).addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception exception) {
                Log.d(TAG,"File Download Failed");
                downloadStatus = false;
            }
        });
        return downloadStatus;
    }
    protected void onPostExecute(InputStream contentsInputStream) {
        //TODO:
    }
}

我的程序既没有进入 addOnSuccessListener 也没有进入 addOnFailureListener 监听器(Logcat 中没有打印日志)

我暂时将我的 Firebase 规则设置如下:

rules_version = '2';
service firebase.storage {
    match /b/{bucket}/o {
        match /{allPaths=**} {
            allow read: if request.auth == null;
        }   
    } 
}

我正在调用我的 AsyncTask,如下所示:

boolean status = new DownloadFileFromFireBase(getContext(), contentsJsonFile).execute("").get();

我存储在 Firebase 存储中的文件可以通过网络浏览器访问(我没有登录/隐身模式)。 我的模拟器和设备正在使用最新的 Google 服务。 甚至在我的项目中实现的 Firebase Storage API 也是最新的(19.1.1)。

我不确定这里出了什么问题。 任何帮助,将不胜感激!谢谢。

【问题讨论】:

    标签: java android firebase firebase-storage


    【解决方案1】:

    FirebaseStorage Android SDK getFile(file) 在 Android Q (SDK 29) 中似乎不再正常工作,这是一项重大更改。你可以像这样使用getBytes(file_size)

        //Member variable but depending on your scope
    private ByteArrayInputStream inputStream;
    private Uri downloadedFileUri;
    private OutputStream stream;
    
    //Creating a reference to the link
        StorageReference httpsReference = FirebaseStorage.getInstance().getReferenceFromUrl(downloadURL);
    
        Uri contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
        String type = "";
        String mime = "";
        String folderName = "";
    
        if (downloadURL.contains("jpg") || downloadURL.contains("jpeg")
                || downloadURL.contains("png") || downloadURL.contains("webp")
                || downloadURL.contains("tiff") || downloadURL.contains("tif")) {
            type = ".jpg";
            mime = "image/*";
            contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
            folderName = Environment.DIRECTORY_PICTURES;
        }
        if (downloadURL.contains(".gif")){
            type = ".gif";
            mime = "image/*";
            contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
            folderName = Environment.DIRECTORY_PICTURES;
        }
        if (downloadURL.contains(".mp4") || downloadURL.contains(".avi")){
            type = ".mp4";
            mime = "video/*";
            contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
            folderName = Environment.DIRECTORY_MOVIES;
        }
        if (downloadURL.contains(".mp3")){
            type = ".mp3";
            mime = "audio/*";
            contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
            folderName = Environment.DIRECTORY_MUSIC;
        }
    
                final String relativeLocation = folderName + "/" + getString(R.string.app_name);
    
            final ContentValues contentValues = new ContentValues();
            contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, UUID.randomUUID().toString() + type);
            contentValues.put(MediaStore.MediaColumns.MIME_TYPE, mime); //Cannot be */*
            contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, relativeLocation);
    
            ContentResolver resolver = getContentResolver();
            Uri uriResolve = resolver.insert(contentUri, contentValues);
    
            try {
    
                if (uriResolve == null || uriResolve.getPath() == null) {
                    throw new IOException("Failed to create new MediaStore record.");
                }
    
                stream = resolver.openOutputStream(uriResolve);
    
                //This is 1GB change this depending on you requirements
                httpsReference.getBytes(1024 * 1024 * 1024)
                .addOnSuccessListener(bytes -> {
                    try {
    
                        int bytesRead;
    
                        inputStream = new ByteArrayInputStream(bytes);
    
                        while ((bytesRead = inputStream.read(bytes)) > 0) {
                            stream.write(bytes, 0, bytesRead);
                        }
    
                        inputStream.close();
                        stream.flush();
                        stream.close();
    //FINISH
    
                    } catch (IOException e) {
                        closeSession(resolver, uriResolve, e);
                        e.printStackTrace();
                        Crashlytics.logException(e);
                    }
                });
    
            } catch (IOException e) {
                closeSession(resolver, uriResolve, e);
                e.printStackTrace();
                Crashlytics.logException(e);
    
            }
    

    如果您想监控下载进度,更好的替代方法是使用getStream(),这样您就可以根据要下载的总字节数计算下载的字节数。

    httpsReference.getStream((state, inputStream) -> {
    
                long totalBytes = state.getTotalByteCount();
                long bytesDownloaded = 0;
    
                byte[] buffer = new byte[1024];
                int size;
    
                while ((size = inputStream.read(buffer)) != -1) {
                    stream.write(buffer, 0, size);
                    bytesDownloaded += size;
                    showProgressNotification(bytesDownloaded, totalBytes, requestCode);
                }
    
                // Close the stream at the end of the Task
                inputStream.close();
                stream.flush();
                stream.close();
    
            }).addOnSuccessListener(taskSnapshot -> {
                showDownloadFinishedNotification(downloadedFileUri, downloadURL, true, requestCode);
                //Mark task as complete so the progress download notification whether success of fail will become removable
                taskCompleted();
                contentValues.put(MediaStore.Files.FileColumns.IS_PENDING, false);
                resolver.update(uriResolve, contentValues, null, null);
            }).addOnFailureListener(e -> {
                Log.w(TAG, "download:FAILURE", e);
    
                try {
                    stream.flush();
                    stream.close();
                } catch (IOException ioException) {
                    ioException.printStackTrace();
                    FirebaseCrashlytics.getInstance().recordException(ioException);
                }
    
                FirebaseCrashlytics.getInstance().recordException(e);
    
                //Send failure
                showDownloadFinishedNotification(null, downloadURL, false, requestCode);
    
                //Mark task as complete
                taskCompleted();
            });
    

    查看示例项目以了解更多信息:https://github.com/firebase/quickstart-android/tree/master/storage

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-29
      • 2017-02-11
      • 2019-03-25
      • 2020-07-14
      • 2021-11-21
      • 2016-03-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多