学习日记12.1——Android kotlin 图形验证码的转换

在写到注册功能时,需要从后台获取图形验证码图片并进行展示,但这个很简单的问题却难了我一周。

从后台拿到的是二进制图片流。因为不懂原理,所以去网上虾78百度了很多二进制转图片的方法。

像这个:

    fun image2byte(path: String?, inStream: InputStream?): ByteArray? {
        var data: ByteArray? = null
        try {
            val imageFile = path?.let { File(it) }
            val output = ByteArrayOutputStream()
            val buf = ByteArray(1024)
            var numBytesRead = 0
            while (inStream?.read(buf).also {
                    if (it != null) {
                        numBytesRead = it
                    }
                } != -1) {
                output.write(buf, 0, numBytesRead)
            }
            data = output.toByteArray()
            output.close()
            inStream?.close()
        } catch (ex1: FileNotFoundException) {
            ex1.printStackTrace()
        } catch (ex1: IOException) {
            ex1.printStackTrace()
        }
        return data
    }

这个:

    //根据指定的二进制流字符串保存文件并返回保存路径
    fun saveFileByBinary(str: String?, attName: String, context: Context?): String? {
        /***加载附件*/  //获取存储卡路径、构成保存文件的目标路径
        var dirName = "" //SD卡具有读写权限、指定附件存储路径为SD卡上指定的文件夹
        dirName = Environment.getExternalStorageDirectory().toString() + "/MyDownload/"
        val f = File(dirName)
        if (!f.exists()) {      //判断文件夹是否存在
            f.mkdir() //如果不存在、则创建一个新的文件夹
        } //准备拼接新的文件名
        var fileName = ""
        fileName = attName
        fileName = dirName + fileName
        val file = File(fileName)
        if (file.exists()) {    //如果目标文件已经存在
            file.delete() //则删除旧文件
        }
        val byteFile: ByteArray? = null
        try {
            val `is`: InputStream = ByteArrayInputStream(byteFile)
            val os = FileOutputStream(file)
            val b = ByteArray(1024)
            var len = 0 //开始读取
            while (`is`.read(b).also { len = it } != -1) {
                os.write(b, 0, len)
            } //完毕关闭所有连接
            `is`.close()
            os.close()
        } catch (e: FileNotFoundException) {
            e.printStackTrace()
        } catch (e: IOException) {
            e.printStackTrace()
        }
        return fileName
    }

还有这个:

/**
     * @param args
     * 二进制数据流反编译示例
     */
    @Throws(Exception::class)
    @JvmStatic
    fun main(args: Array<String>) {
        // new一个URL对象
        val url = URL(
            "http://www.cxhke.com:88/upload/20123200000074522010/1509697245327.jpg"
        )
        // 打开链接
        val conn = url.openConnection() as HttpURLConnection
        // 设置请求方式为"GET"
        conn.requestMethod = "GET"
        // 超时响应时间为5秒
        conn.connectTimeout = 5 * 1000
        // 通过输入流获取图片数据
        val inStream = conn.inputStream
        // 得到图片的二进制数据,以二进制封装得到数据,具有通用性
        val data = readInputStream(inStream)
        // new一个文件对象用来保存图片,默认保存当前工程根目录
        val imageFile = File("D:\\BeautyGirl123.png")
        // 创建输出流
        val outStream = FileOutputStream(imageFile)
        // 写入数据
        outStream.write(data)
        // 关闭输出流
        outStream.close()
    }

    @Throws(Exception::class)
    fun readInputStream(inStream: InputStream): ByteArray {
        val outStream = ByteArrayOutputStream()
        // 创建一个Buffer字符串
        val buffer = ByteArray(1024)
        // 每次读取的字符串长度,如果为-1,代表全部读取完毕
        var len = 0
        // 使用一个输入流从buffer里把数据读取出来
        while (inStream.read(buffer).also { len = it } != -1) {
            // 用输出流往buffer里写入数据,中间参数代表从哪个位置开始读,len代表读取的长度
            outStream.write(buffer, 0, len)
        }
        // 关闭输入流
        inStream.close()
        // 把outStream里的数据写入内存
        return outStream.toByteArray()
    }

但是这些都不是我需要的。

基于图片有多种格式,所以我们需要弄清楚我们要通过何种方式转换成图片。在这里用得是bitmap格式。bitmap和byte[]之间有一个转化方法。我的了解方式源自:这里

在过往我们都会在界面中展示图片,常用的方法要么是App内的图片直接读取,要么是图片的字符串地址、用loadImage方法读取(Glide工具我也就放在这里算通过地址加载图片)。但这里应该用bitmap方法,先将字节流转化为字节数组byte[],再将字节数组转换为bitmap格式。这个时候就可以直接将bitmap格式的图片直接展示在控件上了。

这是我的最终实现:

        val ivImage = dialog!!.findViewById<ImageView>(R.id.iv_image)
        val tvAgain = dialog!!.findViewById<TextView>(R.id.tv_again)
        tvAgain.clickWithTrigger {
            val params = CaptchaParams("")
            ApiManger.getApiService().getcaptcha(params).compose(RxUtil.normalSchedulers())
                .subscribe(object : Observer<ResponseBody> {

                    override fun onCompleted() {
                        ToastUtils.showShort("获取成功")
                    }

                    override fun onError(e: Throwable?) {
                        ToastUtils.showShort("onError")
                    }

                    override fun onNext(t: ResponseBody?) {
                        val source= t?.bytes()
                        LogX.i(TAG, "二进制数组为${source}")
                        val bitmap: Bitmap = BitmapFactory.decodeByteArray(source, 0, source!!.size)
                        ivImage.setImageBitmap(bitmap)
                    }
                })
        }

仅仅三行代码,就解决了这个为难了我一周的问题。

o(╥﹏╥)o

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值