【问题标题】:Firebase Storage download multiple photos UrlsFirebase 存储下载多张照片网址
【发布时间】:2017-03-03 18:21:49
【问题描述】:

我有一个包含照片的 Firebase 存储。 我正在按名称1、2、3等组织照片...... 我正在尝试获取所有照片的下载 URL,因此将来我会将它们输入到 URL 的 Arraylist 中并使用 Glide 将它们呈现在照片库中(这就是我只寻找 URL 的原因)

我正在寻找一种方法,该方法仅在调用 onSucsess 时才会继续给我 Urls,当调用 onFailure 时(因为没有更多照片)我希望循环结束。

我正在尝试使用 Firebase 的 getDownloadUrl 方法并添加了一个布尔值,当调用 onFailure 时将触发 false。 并增加我从 1 开始的 photoOrder int,这样会改变所选照片的​​路径。

public class Photopackges extends AppCompatActivity {

public static boolean shouldRun = true;
public static final String TAG = "debug";
public static int photoOrder = 1;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_photopackges);

    //just normal firebase setup
    FirebaseStorage storage = FirebaseStorage.getInstance();


     // while shouldRun boolean is true keep going , until it will be defined false
    while (shouldRun == true) {

          // define my Firebase storage path,which contain one folder called "test" and three photos 1.jpg,2.jpg,3.jpg
         // the number of the photo is represented in the photoOrder int.
        String storagePath = "test/" + String.valueOf(photoOrder) + ".jpg";
        StorageReference ref = storage.getReference().child(storagePath);

        try {

            ref.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
                @Override
                public void onSuccess(Uri uri) {

                    // trying to define that if the action was successful , keep on going.
                    shouldRun = true;
                    Log.e(TAG, "sucsess! " + uri);


                }
            }).addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {

                    // trying to define that if the action has failed , stop.
                    shouldRun = false;
                    Log.e(TAG, "Fail! " + e);
                }
            });


        } catch (Exception e) {
            Log.e(TAG, "Error! " + e);
            break;


        }

        //increment the photoOrder so it will go to the next path.
        photoOrder++;
        Log.e(TAG,"value of photoOrder "+photoOrder);
    }
}
}

日志 -

Loginfo

我不认为他在得到答案之前发送了更多请求。 我只需要他在事情发生时停下来

StorageException:该位置不存在对象。

我猜一定有一种更简单的方法可以使用 firebase 获取所有存储空间。

感谢您的帮助!

【问题讨论】:

    标签: android multithreading firebase while-loop firebase-storage


    【解决方案1】:

    好的,经过大量尝试,我能够使用 wait() 和 notify() 方法。

    现在我可以获取 ArrayList 以及我的 FirebaseStorage 中所有照片的 下载 URLS,其中可能包含未知数量的照片。 请注意,这只是因为我必须在将它们输入到我的存储中之前将它们重命名为 (1,2,3...etc)。

    为此,您需要:

    1. 设置 FirebaseStorage。
      1. 创建一个文件夹(我的称为 test)并填充图像。

    我能够得到这个 Logcat,这正是我想要的 See Log

    public static final String TAG = "eyaldebug";
    public static PathGenerator pathGenerator;
    public static ArrayList<String>photoURLs;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_photopackges);
    
        //Initialize the whole process
    
        photoURLs = new ArrayList<>();
    
        pathGenerator = new PathGenerator();
    
        new UrlProducer(pathGenerator);
    
    
    }
    
    
    /**
     * This class contains the GeneratePaths method,which responsible
     * of making new paths.
     * Also we have a simple set - get methods of the booleans.
     */
    
    class PathGenerator {
        //start photo number
        int photoNumber = 0;
        //boolean that indicates if the path has been used already or not.
        boolean pathIsTaken = false;
        //our storage path.
        String path;
    
        /**
         * This method will generate a new path.
         * while path is taken , wait because we didn't use it yet.
         *
         * @param photoNumber
         */
    
        public synchronized String generatePath(int photoNumber) {
    
            while (pathIsTaken)
            {
                try {wait();} catch (Exception e) {}
            }
            this.photoNumber = photoNumber;
            path = "test/" + String.valueOf(photoNumber) + ".jpg";
            pathIsTaken = true;
            Log.e("eyaldebug", "path is :  " + path);
            return path;
        }
    
        /**
         * Simple set method.
         * @param value
         */
    
        public synchronized void setPathisSet(boolean value)
        {
            this.pathIsTaken = value;
        }
    
        /**
         * Unfreeze the thread, we call this method after onSucsess.
         */
    
        public synchronized void unfreeze( )
        {
            notifyAll();
        }
    
    }
    
    
    /**
     * Our URLProducer calls will take the paths,and will
     * send HTTP request to the storage that we'll get a
     * download URL returned.
     * later we'll be using Glide\Picasso to display those images.
     */
    
    class UrlProducer implements Runnable {
    
        PathGenerator mPathGenerator;
    
        //initialize a String type ArrayList which will contain our URLS.
        public  ArrayList<String>photoURLs = new ArrayList<>();
    
        //constructor that will be called in the activity
        public UrlProducer(PathGenerator mPathGenerator) {
            this.mPathGenerator = mPathGenerator;
    
            Thread b = new Thread(this, "UrlProducer");
            b.start();
        }
    
        /**
         * Here we a simple download URL method using FirebaseStorage.
         * for the documentation for FirebaseStoarge download go to :
         *
         * https://firebase.google.com/docs/storage/android/download-files
         *
         * IF the task was successful we UNfreeze the threads so it will
         * keep sending us new URLS.
         * IF the onFailure was called the stroage is must likely empty and
         * we should stop trying to get new photos.
         */
    
        @Override
        public void run() {
    
    
            int photoNumber =0 ;
    
            while (true) {
    
    
                photoNumber ++;
    
                try {
                    FirebaseStorage storage = FirebaseStorage.getInstance();
                    StorageReference ref = storage.getReference();
    
    
                    ref.child(pathGenerator.generatePath(photoNumber)).getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
                        @Override
                        public void onSuccess(Uri uri) {
    
                            Log.e(TAG, "Success! " + uri);
    
                            //add the URL into the ArrayList
                            photoURLs.add(String.valueOf(uri));
    
                           //tell the generate method that the path has been used.
                            pathGenerator.setPathisSet(false);
    
                            //Unfreeze the thread so it will continue generate new paths.
                            pathGenerator.unfreeze();
    
                        }
                    }).addOnFailureListener(new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e) {
    
                            //When onFailure is called shutdown,and output the given ArrayList.
    
                            Log.e(TAG,"onFailure was called , storage is empty!");
                            Log.e(TAG,"----------------------------------------");
                            for(String singleUrl :photoURLs)
                            {
                                Log.e(TAG,""+singleUrl)   ;
                            }
                        }
                    });
    
    
                }catch (Exception e){e.printStackTrace();}
    
    
            }
        }
    
    }
    

    【讨论】:

      【解决方案2】:

      嗯,问题是由于调用 ref.getDownloadUrl() 是异步的。因此,当您的第一个 onFailure 方法被调用时,已经有许多其他对异步方法的调用,因为您的循环运行得更快并且不等待前一个调用的响应。

      所以我的建议是,您应该将 URL 存储在 Firebase RealtimeDatabase 中并获取这些 URL,然后使用 glide 加载它们。

      如果您想了解如何处理 URL 列表,可以查看文档 https://firebase.google.com/docs/database/android/lists-of-data

      【讨论】:

      • 好的,感谢您的帮助!我将尝试使用 RealtimeDatabase 并将在此处发布。
      猜你喜欢
      • 1970-01-01
      • 2020-02-08
      • 2020-06-24
      • 2016-10-16
      • 1970-01-01
      • 2019-05-24
      • 2018-05-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多