[英]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.