android 拍照得到大图,Android拍照及图片获取使用及原理剖析

文档说明

在日常开发过程中,我们经常需要用到调用相册和相机拍照功能,由于系统版本混乱,使用方式杂乱不一,在此进行整理说明以及简单的原理分析。

注意权限声明:

简单使用

通过调用相机

private fun openCamera() {

val takePhotoIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)

if (takePhotoIntent.resolveActivity(packageManager) != null) { // 解析是否存在可以处理当前意图的Activity

startActivityForResult(

takePhotoIntent,

PERSONAL_INFO_I_TAKEPHOTO

);//启动相机

}

}

通过相册

private fun openAlbum() {

val openAlbumIntent = Intent(Intent.ACTION_GET_CONTENT)

openAlbumIntent.type = "image/*"

startActivityForResult(openAlbumIntent, PERSONAL_INFO_I_GALLEY) //打开相册

}

处理返回结果

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

super.onActivityResult(requestCode, resultCode, data)

when (requestCode) {

PERSONAL_INFO_I_TAKEPHOTO -> {

if (resultCode == RESULT_OK) {

val bitmap: Bitmap = data?.getParcelableExtra("data")!! // intent中data字段就是保存的是bitmap缩略图

val tempUri :Uri = getImageUri(bitmap)

}

}

PERSONAL_INFO_I_GALLEY -> {

if (resultCode == RESULT_OK) {

val tempUri :Uri = data!!.data // intent中data字段就是保存的uri

}

}

}

// 内存图片保存为uri

fun getImageUri(inImage: Bitmap): Uri {

val bytes = ByteArrayOutputStream()

inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes)

val path = MediaStore.Images.Media.insertImage(this.contentResolver, inImage, "Title", null)

return Uri.parse(path)

}

拍照获取原图

原理说明

通过以上的实现方式,相机实现的是拍照的缩略图,如何取到实际拍摄的原图呢?

在这里需要用到 Android provider 实现方式。

首先在清单文件添加以下逻辑:

...

android:name="android.support.v4.content.FileProvider"

android:authorities="com.example.android.fileprovider" // 建议更新为 `包名.fileprovider`

android:exported="false"

android:grantUriPermissions="true">

android:name="android.support.FILE_PROVIDER_PATHS"

android:resource="@xml/file_paths">

// 记得新建xml文件

...

file_paths.xml 文件内容:

name="my_images"

path="." />

字段名表示需要创建uri的文件夹,常用的有 external-path,files-path 和 cache-path。external-path表示的含义是通过Environment.getExternalStorageDirectory() 获取的文件存储位置,files-path表示通过 Context.getFilesDir() 获取的文件存储位置,cache-path表示通过Context.getCacheDir()获取的文件存储位置。

name属性表示这个文件的昵称,会包含在生成的uri中,path表示指定的子文件夹。

配置结束生成的 uri 类似 content://com.example.testad.fileprovider/my_images/xxx

使用方式

lateinit var currentPhotoPath: String // 保存文件路径

lateinit var photeUri: Uri // 保存照片的uri

private fun createImageFile(): File {

val storageDir: File? = this.filesDir // 目标存储在 files 文件夹内

return File.createTempFile(

"JPEG_${System.currentTimeMillis()}_", // 文件名

".jpg", // 后缀

storageDir // 存储文件夹

).apply {

currentPhotoPath = absolutePath

}

}

private fun takePhote() {

Intent(MediaStore.ACTION_IMAGE_CAPTURE).also { takePictureIntent ->

takePictureIntent.resolveActivity(packageManager)?.also {

val photoFile: File = createImageFile()

photoFile.also {

photeUri = FileProvider.getUriForFile( // 根据文件创建uri

this,

"com.example.testad.fileprovider", // 在清单文件声明的权限全称

it

)

takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photeUri) // 传入目标uri

startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO)

}

}

}

}

处理结果:

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

super.onActivityResult(requestCode, resultCode, data)

when (requestCode) {

REQUEST_TAKE_PHOTO -> {

if (resultCode == RESULT_OK) {

photeUri // 直接使用上面生成的uri

}

}

}

}

在官方文档中说明了 MediaStore.ACTION_IMAGE_CAPTURE 的使用方式,如果没有传入 MediaStore.EXTRA_OUTPUT 则默认返回一个小尺寸的 Bitmap 对象,反之则将图片全尺寸进行写入传递的位置。具体说明参考:ACTION _ IMAGE _ CAPTURE

到此为止就已完成我们的需求,如果需要拍照插入图库,下面步骤即可实现:

private fun galleryAddPic() {

Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE).also { mediaScanIntent ->

val f = File(currentPhotoPath) // 需要传递文件真实位置,系统会生成标准的uri

mediaScanIntent.data = Uri.fromFile(f)

sendBroadcast(mediaScanIntent)

}

}

以上便是 Android 拍照的简单使用。

如有疑问,欢迎交流讨论。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值