android10图片保存,android10分区存储照片选择,拍照处理

前言

在前段时间,google正式发布了android10, Scoped storage(分区存储) 这个功能在android9上就跃跃欲试, 在android10上呼之欲出,某些app甚至在上架之后还会出现targetAPI降低的神奇操作,本文不针对于分区存储介绍etc ,不提及其它解决方案, 仅仅说明笔者在开发过程中遇到的关于图片处理问题以及解决方法, 先说下当前如何解决问题.

兼容模式

如果targetAPI == 29

常规的访问存储目录,或者做相关操作都会出现权限拒绝的异常

android:requestLegacyExternalStorage ="true"

在manifest文件application标签下加入这句话则会回到传统存储模式

如果targetAPI == 28

android:requestLegacyExternalStorage ="false"

在manifest文件application标签下加入此项配置为false , 则会强制开启分区存储, android10上需要适配的工作在android9上也需要

如果targetAPI > 29

配置会失效,google在说明此项配置只针对于临时问题

选取照片适配

先上代码 (笔者一直用kt , java同学应该也不难看懂,有疑问可以留言),这是常规的pick操作, 没什么好说的

private fun photoFromGallery() {

try {

val intent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {

Intent(Intent.ACTION_OPEN_DOCUMENT)

} else {

Intent(Intent.ACTION_PICK)

}

intent.type = "image/*"

startActivityForResult(intent, REQUEST_CODE_OPEN_PHOTO_ALBUM)

} catch (e: ActivityNotFoundException) {

e.printStackTrace()

showToast(R.string.open_photo_album_error)

}

}

然后来看看activityResult怎么处理,惯例先上代码

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {

when (requestCode) {

REQUEST_CODE_TAKE_PHOTOS -> if (resultCode == RESULT_OK)

mOutPutUri?.let { mPresenter.uploadFile(it) } //mOutPutUri为相机输出路径,后面会提及, ?.let句式为内联函数非空判断

REQUEST_CODE_OPEN_PHOTO_ALBUM -> if (resultCode == RESULT_OK && data != null) {

val resolver = applicationContext.contentResolver //在一般情况此处都用contentResolver来直接query文件的absPath然后进行上传操作

data.data?.let {

resolver.openInputStream(it).use { stream ->

stream?.readBytes()?.let { bytes -> mPresenter.uploadFile(bytes, System.currentTimeMillis().toString() + ".png") }

}

}

}

else -> super.onActivityResult(requestCode, resultCode, data)

}

}

注意看这一段

resolver.openInputStream(it).use { stream ->//此处的stream为自动回收流,不可引用

stream?.readBytes()?.let { bytes -> mPresenter.uploadFile(bytes, System.currentTimeMillis().toString() + ".png") }

}

resolver.openInputStream(it).use来获取文件流 -> 转化字节码上传 ,retrofit2也正好支持, 挺整好,旧版本也行

将resolver.openInputStream(it).use{}替换成如下这一段代码会更加简洁

val resolver = applicationContext.contentResolver

resolver.openFileDescriptor(uri, "r")?.let { pfd ->//获取ParcelFileDescriptor一样可以获取字节码

mPresenter.uploadFile(FileUtil.getScaledBitmapBytes(pfd))

}

附上FileUtil片段,缩放图片&转换为字节码

fun getScaledBitmapBytes(pfd: ParcelFileDescriptor, needRecycle: Boolean = true): ByteArray? {

val opt = BitmapFactory.Options()

opt.inJustDecodeBounds = true

BitmapFactory.decodeFileDescriptor(pfd.fileDescriptor, null, opt)

var inSampleSize = 1

val height = opt.outHeight

val width = opt.outWidth

if (width > 720 || height > 720) {//长或者宽>720则等比缩放

inSampleSize = if (width >= height) {

height / 720

} else {

width / 720

}

}

opt.inJustDecodeBounds = false

opt.inSampleSize = inSampleSize

val bitmap = BitmapFactory.decodeFileDescriptor(pfd.fileDescriptor, null, opt)

if (needRecycle)

pfd.close()

return bitmap?.let { bmpToByteArray(it, needRecycle) }

}

拍照处理

先上代码,看调起相机片段

private fun photoFromCamera() {

val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)//通过MediaStore访问

intent.resolveActivity(packageManager)?.let {

mOutPutUri = FileUtil.insertExternalStorageImage(this)

mOutPutUri?.also {

intent.putExtra(MediaStore.EXTRA_OUTPUT, it)

startActivityForResult(intent, REQUEST_CODE_TAKE_PHOTOS)

} ?: showToast("路径生成失败")

} ?: showToast("没有可用的拍照程序")

}

附上FileUtil片段 , MediaStore插入图片操作

fun insertExternalStorageImage(context: Context): Uri? {

return context.applicationContext.contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, ContentValues().apply {

val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA).format(Date())

put(MediaStore.Images.Media.DISPLAY_NAME, "${JPEG_FILE_PREFIX}${timeStamp}${JPEG_FILE_SUFFIX}")

put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")

})

}

通过上述片段可获取content Uri媒体路径, 然后可以照葫芦画瓢, 一样可以用流的方式或者ParcelFileDescriptor的方式 ,各位自行选取

上班摸鱼所写.时间紧迫没来得及整理文稿,都是现学现卖,请键下留情,不懂的可以留言,谢看

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值