Firebase存储下载多张照片网址

时间:2017-03-03 18:21:49

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

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

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

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

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来获取所有存储空间。

感谢您的帮助!

2 个答案:

答案 0 :(得分:3)

好的,所以经过很多尝试后我可以使用wait()和notify()方法。

现在,我可以使用FirebaseStorage中所有照片的下载网址来获取 ArrayList ,其中可能包含未知数量的照片。 注意到这只是因为在我进入我的storge之前我必须重命名它们(1,2,3 ......等)。

为此,您需要:

  1. 设置FirebaseStorage。
    1. 创建一个文件夹(我的名为test)并填充图片。
  2. 我能够得到这个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();}
    
    
            }
        }
    
    }
    

答案 1 :(得分:0)

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

所以我的建议是你应该将你的URL存储在firebase RealtimeDatabase中并获取这些URL然后用滑动加载它们。

如果您想了解有关处理网址列表的信息,可以查看文档 https://firebase.google.com/docs/database/android/lists-of-data