Android上传bytearray图片至Firebase Storage时App崩溃排查
崩溃触发原因
核心错误是类型强转逻辑完全错误:
findViewById(R.id.edit_cover_picture)返回的是AppCompatImageView控件实例,属于View控件类层级;而BitmapDrawable是Drawable类的子类,是ImageView内部承载的绘制内容,二者属于完全独立的继承体系,直接把ImageView控件实例强转为BitmapDrawable必然触发ClassCastException。- 调试阶段未报错是因为测试场景没有覆盖到这段上传逻辑,属于测试遗漏,和代码本身的逻辑错误无关。
- 存在冗余无效逻辑:你定义的
imageUri变量全程没有在上传流程中使用,且写死指向APK内置的默认封面资源,即使后续改用putUri方法上传,也拿不到ImageView实际展示的、用户选择的图片。
修复方法
首先修正从ImageView提取Bitmap的逻辑:不要直接强转ImageView控件本身,先通过drawable属性获取控件绑定的Drawable对象,同时做类型校验,兼容非BitmapDrawable的场景(比如矢量图、shape资源、第三方图片库加载的包装Drawable等)。
修复后的可运行代码如下:
imagePicker = findViewById(R.id.edit_cover_picture) // 先获取ImageView绑定的Drawable内容,再做类型判断 val drawable = imagePicker.drawable var image: ByteArray? = null if (drawable is BitmapDrawable) { val bitmap = drawable.bitmap val stream = ByteArrayOutputStream() // 注意:PNG是无损压缩格式,第二个质量参数对PNG无效,要控制体积建议换JPEG/WEBP格式 bitmap.compress(Bitmap.CompressFormat.JPEG, 90, stream) image = stream.toByteArray() } else { // 兼容非BitmapDrawable场景:手动将Drawable绘制到Bitmap上 val bitmap = Bitmap.createBitmap( drawable.intrinsicWidth, drawable.intrinsicHeight, Bitmap.Config.ARGB_8888 ) val canvas = Canvas(bitmap) drawable.setBounds(0, 0, canvas.width, canvas.height) drawable.draw(canvas) val stream = ByteArrayOutputStream() bitmap.compress(Bitmap.CompressFormat.JPEG, 90, stream) image = stream.toByteArray() } // 加空安全校验避免空指针 image?.let { storageReference = FirebaseStorage.getInstance().getReference("coverPicture/${auth.currentUser?.uid}") storageReference.putBytes(it) .addOnSuccessListener { // 编写上传成功后的业务逻辑 } .addOnFailureListener { e -> // 编写上传失败的提示、重试逻辑 } }
额外注意事项
- 如果你的ImageView是用Glide、Coil等第三方图片加载库设置的图片,不建议从ImageView中反向提取Bitmap上传,优先使用图片选择/加载阶段拿到的原始Uri、Bitmap上传,避免拿到占位图、错误图或者被过度压缩失真的图片。
- PNG格式为无损压缩,
compress方法传入的质量参数对PNG无效,如果需要控制上传图片体积,建议改用JPEG或WEBP格式。
内容的提问来源于stack exchange,提问作者Tommy -
相关产品推荐
相关产品推荐

