Android 图片下载或上传时请求失败。

项目场景:

Android开发时使用OkHttp等相关网络框架与后端完成网络通信,完成上传或下载图片功能。



Bug1:

通过Intent获取图片,并使用OkHttp将其传输到后端,发现后端未收到Http请求(即请求丢失)。进而导致OkHttp中onResponse回调发生异常情况,发生返回数据丢失等情况。


原因分析:

发送的图片过大,导致OkHttp未能将请求发送出去。
(不知道是不是根本原因,但将图片发送前进行压缩确实能完成正常的请求发送)


解决方案:

发送前将图片等文件进行压缩,压缩完成后再将其加入到RequestsBody中进行数据发送。
并且使用Android传输大尺寸图片也是毫无意义的,因为Android本身也并不能显示出那些动辄上十兆的图片。
在此提供一个相对好用的文件压缩第三方库:Compressor



Bug2:

利用OkHttp请求图片,并将其加载到ImageView中时图片不能显示。
通常伴随相关错误或警告:

  • Failed to create image decoder with message 'unimplemented'
  • android.graphics.ImageDecoder$DecodeException: Failed to create image decoder with message 'unimplemented'Input contained an error.

实际上在开发时你很可能看不到第二个错误,而只会在网络请求回调执行中图片加载不出来时看到第一种形式的警告(这个警告极其不显眼,一般情况下你甚至不会注意到它)。两种形式对应的是同一种错误。


原因分析:

请求返回的数据流过大,直接使用该数据流生成Bitmap格式的图片生成失败。(可能原因)


解决方案:

不要直接调用BitmapFactory.decodeStream(stream),而是先将返回的数据流保存到本地文件 (若接收的是图片,则保存时最好对其进行压缩),并通过调用本地文件的Uri来使用其数据。

可在回调中尝试如下方案:

	val call = client.newCall(request)
    call.enqueue(object : Callback {
        // UI的更新需要在UI线程中更新, runOnUiThread
        override fun onFailure(call: Call?, e: IOException?) {
            e?.printStackTrace()
            activity?.runOnUiThread {
                Toast.makeText(context, "照片处理失败,请稍后重试", Toast.LENGTH_SHORT).show()
                loadingDialog.dismiss()
            }
        }

        override fun onResponse(call: Call?, response: Response) {
            val stream = response.body()!!.byteStream()
            val fType = context.contentResolver.getType(img.toUri()) ?: "jpg"
            // 将数据流保存到本地,最好同时对其进行压缩处理
            val bitmap: File = streamToFile(context, stream, fType)
            activity?.runOnUiThread {
                view?.findViewById<ImageView>(R.id.imageView)?.setImageURI(bitmap.toUri())
                Toast.makeText(context, "照片处理完成", Toast.LENGTH_SHORT).show()
                loadingDialog.dismiss()
            }
        }
    })

你可能感兴趣的:(android,kotlin)