简体   繁体   English

Android Firebase 无法下载图像并将它们添加到位图数组

[英]Android Firebase cannot download images and add them to a Bitmap Array

I am currently working on a matching card game where I need to store the images on Firebase.我目前正在开发一款匹配的纸牌游戏,我需要将图像存储在 Firebase 上。 I am uploading the images by a button click when I start the game(doing it automatically creates same problem but the button one is safer) I think the Image isn't getting downloaded fast enough to show on the card face or it might not be working in a sequence with the whole app so the bitmap array gets zero elements inside.当我开始游戏时,我通过单击按钮上传图像(这样做会自动产生同样的问题,但按钮更安全)我认为图像下载速度不够快,无法显示在卡面上,或者它可能不会与整个应用程序按顺序工作,以便位图数组在内部获得零元素。 My current code is:我当前的代码是:

class game2x2 : AppCompatActivity() {
    private lateinit var database: DatabaseReference
    private lateinit var buttons: List<ImageButton>
    //private lateinit var bitmapArray: ArrayList<Bitmap>
    private var bitmapArray = mutableListOf<Bitmap>()
    private lateinit var button1: ImageButton
    private lateinit var button2: ImageButton
    private lateinit var button3: ImageButton
    private lateinit var button4: ImageButton
    private lateinit var upload: Button
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_game2x2)

        val min = 1
        val max = 45
        val database = FirebaseDatabase.getInstance()
        val imageID1 = Random().nextInt(max - min + 1) + min
        val imageID2 = Random().nextInt(max - min + 1) + min
        val aDatabase = FirebaseStorage.getInstance().getReference("all/$imageID1.jpg")
        val sDatabase = FirebaseStorage.getInstance().getReference("all/$imageID2.jpg")

        upload = findViewById(R.id.uploadButton)
        button1 = findViewById(R.id.imageButton1)
        button2 = findViewById(R.id.imageButton2)
        button3 = findViewById(R.id.imageButton3)
        button4 = findViewById(R.id.imageButton4)
        buttons = listOf(button1, button2, button3, button4)

        upload.setOnClickListener(View.OnClickListener {
            try {
                val localfile = File.createTempFile("tempfile", ".jpg")
                aDatabase.getFile(localfile).addOnSuccessListener {
                    val bitmap = BitmapFactory.decodeFile(localfile.absolutePath)
                    bitmapArray.add(bitmap)
                }.addOnFailureListener {
                    Log.w("myapplication", "ERROR RETRIEVING IMAGE")
                    Toast.makeText(this, "ERROR RETRIEVING IMAGE", Toast.LENGTH_SHORT).show()
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }

            try {
                val localfile = File.createTempFile("tempfile1", ".jpg")
                sDatabase.getFile(localfile).addOnSuccessListener {
                    val bitmap = BitmapFactory.decodeFile(localfile.absolutePath)
                    bitmapArray.add(bitmap)
                }.addOnFailureListener {
                    Log.w("myapplication", "ERROR RETRIEVING IMAGE")
                    Toast.makeText(this, "ERROR RETRIEVING IMAGE", Toast.LENGTH_SHORT).show()
                }
            } catch (e: java.lang.Exception) {
                e.printStackTrace()
            }
            ///    DUPLICATE
            bitmapArray.addAll(bitmapArray)
            ///SHUFFLE
            bitmapArray.shuffle()
            Log.w("myapplication", bitmapArray.size.toString())
        })

        buttons.forEachIndexed { index, button ->
            button.setOnClickListener(View.OnClickListener {
                button.setImageBitmap(bitmapArray[index])
            })
        }
    }
}

Is there any other way to retrieve image from the Firebase Storage besides downloading and adding it to a temporary file and then decoding it to a bitmap?除了下载并将其添加到临时文件然后将其解码为位图之外,还有其他方法可以从 Firebase 存储中检索图像吗?

I tried anything that I could find.我尝试了我能找到的任何东西。 I even tried adding the access tokens of the images to a realtime database and then getting them from there but I failed terribly.我什至尝试将图像的访问令牌添加到实时数据库,然后从那里获取它们,但我失败了。 Thanks in advance for helping!在此先感谢您的帮助!

Since getFile() an asynchronous task I would imagine your log statement Log.w("myapplication", bitmapArray.size.toString()) is executing while the bitmapArray is still empty?由于getFile()是一个异步任务,我想你的日志语句Log.w("myapplication", bitmapArray.size.toString())正在执行,而 bitmapArray 仍然是空的? This would happen because the aDatabase.getFile().addOnSuccessListener {} and sDatabase.getFile().addOnSuccessListener {} won't execute until the download finishes, but allow the rest of your function to continue to execute.发生这种情况是因为aDatabase.getFile().addOnSuccessListener {}sDatabase.getFile().addOnSuccessListener {}在下载完成之前不会执行,但允许您的其余函数继续执行。

What you need to do is await the results of the downloads before continuing with the duplicate and shuffle portions.您需要做的是等待下载结果,然后再继续复制和随机播放部分。

getFile() returns a FileDownloadTask , which inherits from StorageTask . getFile()返回一个FileDownloadTask ,它继承自StorageTask StorageTask has an isComplete() method -- and a few others the may be useful for errors cases. StorageTask有一个isComplete()方法——以及其他一些可能对错误情况有用的方法。 One option would be to capture the FileDownloadTask in a variable and not continue executing until your downloads are finished.一种选择是在变量中捕获FileDownloadTask ,并且在下载完成之前不继续执行。 However, be warned this might freeze up your main thread.但是,请注意这可能会冻结您的主线程。

Edit: Instead of checking status on the main thread, you might want to try something like disabling the buttons until the images are ready.编辑:您可能不想在主线程上检查状态,而是想尝试禁用按钮,直到图像准备就绪。 See edit comments:见编辑评论:

class game2x2 : AppCompatActivity() {
    private lateinit var database: DatabaseReference
    private lateinit var buttons: List<ImageButton>
    //private lateinit var bitmapArray: ArrayList<Bitmap>
    private var bitmapArray = mutableListOf<Bitmap>()
    private lateinit var button1: ImageButton
    private lateinit var button2: ImageButton
    private lateinit var button3: ImageButton
    private lateinit var button4: ImageButton

    private val numImages = 2 // EDIT total number of images we need to download
    private val numImagesReady = AtomicInteger(0) // EDIT count of how many images are currently ready

    private lateinit var upload: Button
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_game2x2)

        val min = 1
        val max = 45
        val database = FirebaseDatabase.getInstance()
        val imageID1 = Random().nextInt(max - min + 1) + min
        val imageID2 = Random().nextInt(max - min + 1) + min
        val aDatabase = FirebaseStorage.getInstance().getReference("all/$imageID1.jpg")
        val sDatabase = FirebaseStorage.getInstance().getReference("all/$imageID2.jpg")

        upload = findViewById(R.id.uploadButton)
        button1 = findViewById(R.id.imageButton1)
        button2 = findViewById(R.id.imageButton2)
        button3 = findViewById(R.id.imageButton3)
        button4 = findViewById(R.id.imageButton4)
        buttons = listOf(button1, button2, button3, button4)

        // EDIT disable buttons until all images are ready
        buttons.forEach {
            it.setEnabled(false)
        }

        upload.setOnClickListener(View.OnClickListener {
            try {
                val localfile = File.createTempFile("tempfile", ".jpg")
                aDatabase.getFile(localfile).addOnSuccessListener {
                    val bitmap = BitmapFactory.decodeFile(localfile.absolutePath)
                    bitmapArray.add(bitmap)


                    // EDIT add the image twice here instead of duplicating later
                    bitmapArray.add(bitmap)

                    // EDIT count this image as ready
                    val totalImagesReady = numImagesReady.incrementAndGet()
                    
                    // EDIT once all images are ready, shuffle and enable the buttons
                    if (totalImagesReady == numImages) {
                        bitmapArray.shuffle()
                        buttons.forEach { it.setEnabled(true) }
                    }


                }.addOnFailureListener {
                    Log.w("myapplication", "ERROR RETRIEVING IMAGE")
                    Toast.makeText(this, "ERROR RETRIEVING IMAGE", Toast.LENGTH_SHORT).show()
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }

            try {
                // SUGGESTION especially if this will be implemented 8x8, you might want to try implementing this in a loop instead of duplicating code
                val localfile = File.createTempFile("tempfile1", ".jpg")
                sDatabase.getFile(localfile).addOnSuccessListener {
                    val bitmap = BitmapFactory.decodeFile(localfile.absolutePath)
                    bitmapArray.add(bitmap)

                    // EDIT add the image twice here instead of duplicating later
                    bitmapArray.add(bitmap)

                    // EDIT count this image as ready
                    val totalImagesReady = numImagesReady.incrementAndGet()
                    
                    // EDIT once all images are ready, shuffle and enable the buttons
                    if (totalImagesReady == numImages) {
                        bitmapArray.shuffle()
                        buttons.forEach { it.setEnabled(true) }
                    }


                }.addOnFailureListener {
                    Log.w("myapplication", "ERROR RETRIEVING IMAGE")
                    Toast.makeText(this, "ERROR RETRIEVING IMAGE", Toast.LENGTH_SHORT).show()
                }
            } catch (e: java.lang.Exception) {
                e.printStackTrace()
            }
// EDIT moved            ///    DUPLICATE
// EDIT refactor         bitmapArray.addAll(bitmapArray)
// EDIT moved            ///SHUFFLE
// EDIT moved            bitmapArray.shuffle()
// EDIT remove           Log.w("myapplication", bitmapArray.size.toString())
        })

        buttons.forEachIndexed { index, button ->
            button.setOnClickListener(View.OnClickListener {
                button.setImageBitmap(bitmapArray[index])
            })
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Android Kotlin Firebase 如何同时检索两个图像并将它们添加到位图数组中? - Android Kotlin Firebase How to retrieve two image at the same time and add them into a bitmap array? 压缩多张图片上传到 firebase android - Compressing multiple images before uploading them to firebase android 如何从 firebase 存储下载和显示图像 - How to download and display images from firebase storage 上传文件到firebase存储Flutter后无法获取下载链接 - Cannot get the download link after uploading files to firebase storage Flutter 如何将嵌套数组添加到 Firebase Firestore? - How to add nested array into Firebase Firestore? 如何将 firebase crashlytics 添加到 android 项目中 - How to add firebase crashlytics into android projects 从图库中选择多张图片,然后将它们上传到 Firebase Storgae - 但出现 ENOENT(没有此类文件或目录)错误 - Select multiple images from gallery and then upload them to Firebase Storgae - but get an ENOENT (No such file or directory) error 如何从 android 中 firebase 的图像列表中获取单个图像 - how to get single image from list of images from firebase in android android firebase crashlytics 无法在 null ZA8CFDE6331BD59EB2AC966F8911Z4B6 上调用方法 all() - android firebase crashlytics Cannot invoke method all() on null object 下载托管在 Firebase 中的图像 - Download an image hosted in Firebase
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM