Android10以上版本调用相机拍照

2024-04-06 18:20

本文主要是介绍Android10以上版本调用相机拍照,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1、拍照功能

界面

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent" ><Buttonandroid:id="@+id/takePhotoBtn"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="Take Photo" /><ImageViewandroid:id="@+id/imageView"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:contentDescription="图片" />
</LinearLayout>

逻辑处理

package com.jpc.cameraalbumtestimport android.app.Activity
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Matrix
import android.media.ExifInterface
import android.net.Uri
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.provider.MediaStore
import android.widget.Button
import android.widget.ImageView
import androidx.core.content.FileProvider
import java.io.File/*** 首先这里创建了一个File对象,用于存放摄像头拍下的图片,这里我们把图片命名为* output_image.jpg,并存放在手机SD卡的应用关联缓存目录下。什么叫作应用关联缓存目录* 呢?就是指SD卡中专门用于存放当前应用缓存数据的位置,调用getExternalCacheDir()* 方法可以得到这个目录,具体的路径是/sdcard/Android/data/<package name>/cache。* 那么为什么要使用应用关联缓存目录来存放图片呢?因为从Android 6.0系统开始,读写SD卡* 被列为了危险权限,如果将图片存放在SD卡的任何其他目录,都要进行运行时权限处理才行,* 而使用应用关联目录则可以跳过这一步。另外,从Android 10.0系统开始,公有的SD卡目录已* 经不再允许被应用程序直接访问了,而是要使用作用域存储才行*/
class MainActivity : AppCompatActivity() {private val takePhoto = 1private lateinit var imageUri: Uri//private lateinit var outputImage: File// 为了解决outputImage为空的问题,这里将outputImage声明为可空类型private var outputImage: File ?= nullprivate lateinit var imageView: ImageViewoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)val btnTakePhoto = findViewById<Button>(R.id.takePhotoBtn)imageView = findViewById(R.id.imageView)btnTakePhoto.setOnClickListener{// 创建File对象,用于存储拍照后的图片val outputImage = File(externalCacheDir, "output_image.jpg")if(outputImage.exists()){outputImage.delete()}outputImage.createNewFile()// 一般要检查一下版本imageUri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {FileProvider.getUriForFile(this, "com.jpc.cameraalbumtest.fileprovider", outputImage)}else{Uri.fromFile(outputImage)}// 启动相机程序val intent = Intent("android.media.action.IMAGE_CAPTURE")intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri)startActivityForResult(intent, takePhoto)}}override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {super.onActivityResult(requestCode, resultCode, data)when(requestCode) {takePhoto -> {if(resultCode == Activity.RESULT_OK){// 将拍摄的照片显示出来val bitmap =BitmapFactory.decodeStream(contentResolver.openInputStream(imageUri))imageView.setImageBitmap(rotateIfRequired(bitmap))}}}}/*** 调用照相机程序去拍照有可能会在一些手机上发生照片旋转的情况。这是因为* 这些手机认为打开摄像头进行拍摄时手机就应该是横屏的,因此回到竖屏的情况下就会发生90* 度的旋转。为此,这里我们又加上了判断图片方向的代码,如果发现图片需要进行旋转,那么* 就先将图片旋转相应的角度,然后再显示到界面上*/private fun rotateIfRequired(bitmap: Bitmap): Bitmap {// 这里使用let函数,如果outputImage不为空,就执行let函数中的代码val exif = outputImage?.let { ExifInterface(it.path) }val orientation = exif?.getAttributeInt(ExifInterface.TAG_ORIENTATION,ExifInterface.ORIENTATION_NORMAL)return when (orientation) {ExifInterface.ORIENTATION_ROTATE_90 -> rotateBitmap(bitmap, 90)ExifInterface.ORIENTATION_ROTATE_180 -> rotateBitmap(bitmap, 180)ExifInterface.ORIENTATION_ROTATE_270 -> rotateBitmap(bitmap, 270)else -> bitmap}}private fun rotateBitmap(bitmap: Bitmap, degree: Int): Bitmap {val matrix = Matrix()matrix.postRotate(degree.toFloat())val rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height,matrix, true)bitmap.recycle() // 将不再需要的Bitmap对象回收return rotatedBitmap}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"><!-- 声明权限--><uses-featureandroid:name="android.hardware.camera"android:required="false" /><uses-permission android:name="android.permission.CAMERA" /><applicationandroid:allowBackup="true"android:dataExtractionRules="@xml/data_extraction_rules"android:fullBackupContent="@xml/backup_rules"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.CameraAlbumTest"tools:targetApi="31"><activityandroid:name=".MainActivity"android:exported="true"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><providerandroid:name="androidx.core.content.FileProvider"android:authorities="com.jpc.cameraalbumtest.fileprovider"android:exported="false"android:grantUriPermissions="true"><meta-dataandroid:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/file_paths" /></provider></application></manifest>

存放路径

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android"><external-path name="my_images" path="/" />
</paths>
2、从相册中选择图片的功能

在上面基本代码的基础之上添加

val fromAlbumBtn = findViewById<Button>(R.id.fromAlbumBtn)fromAlbumBtn.setOnClickListener{// 打开文件选择器val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)intent.addCategory(Intent.CATEGORY_OPENABLE)// 指定只显示图片intent.type = "image/*"startActivityForResult(intent, fromAlbum)}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {super.onActivityResult(requestCode, resultCode, data)when(requestCode) {takePhoto -> {if(resultCode == Activity.RESULT_OK){// 将拍摄的照片显示出来val bitmap =BitmapFactory.decodeStream(contentResolver.openInputStream(imageUri))imageView.setImageBitmap(rotateIfRequired(bitmap))}}fromAlbum -> {if(resultCode == Activity.RESULT_OK && data != null){data.data?.let { uri ->// 将选择的图片显示val bitmap = getBitmapFromUri(uri)imageView.setImageBitmap(bitmap)}}}}}

这篇关于Android10以上版本调用相机拍照的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/880515

相关文章

Python一次性将指定版本所有包上传PyPI镜像解决方案

《Python一次性将指定版本所有包上传PyPI镜像解决方案》本文主要介绍了一个安全、完整、可离线部署的解决方案,用于一次性准备指定Python版本的所有包,然后导出到内网环境,感兴趣的小伙伴可以跟随... 目录为什么需要这个方案完整解决方案1. 项目目录结构2. 创建智能下载脚本3. 创建包清单生成脚本4

Ubuntu如何升级Python版本

《Ubuntu如何升级Python版本》Ubuntu22.04Docker中,安装Python3.11后,使用update-alternatives设置为默认版本,最后用python3-V验证... 目China编程录问题描述前提环境解决方法总结问题描述Ubuntu22.04系统自带python3.10,想升级

Java调用Python脚本实现HelloWorld的示例详解

《Java调用Python脚本实现HelloWorld的示例详解》作为程序员,我们经常会遇到需要在Java项目中调用Python脚本的场景,下面我们来看看如何从基础到进阶,一步步实现Java与Pyth... 目录一、环境准备二、基础调用:使用 Runtime.exec()2.1 实现步骤2.2 代码解析三、

Python如何调用另一个类的方法和属性

《Python如何调用另一个类的方法和属性》在Python面向对象编程中,类与类之间的交互是非常常见的场景,本文将详细介绍在Python中一个类如何调用另一个类的方法和属性,大家可以根据需要进行选择... 目录一、前言二、基本调用方式通过实例化调用通过类继承调用三、高级调用方式通过组合方式调用通过类方法/静

C#控制台程序同步调用WebApi实现方式

《C#控制台程序同步调用WebApi实现方式》控制台程序作为Job时,需同步调用WebApi以确保获取返回结果后执行后续操作,否则会引发TaskCanceledException异常,同步处理可避免异... 目录同步调用WebApi方法Cls001类里面的写法总结控制台程序一般当作Job使用,有时候需要控制

Python用Flask封装API及调用详解

《Python用Flask封装API及调用详解》本文介绍Flask的优势(轻量、灵活、易扩展),对比GET/POST表单/JSON请求方式,涵盖错误处理、开发建议及生产环境部署注意事项... 目录一、Flask的优势一、基础设置二、GET请求方式服务端代码客户端调用三、POST表单方式服务端代码客户端调用四

更改linux系统的默认Python版本方式

《更改linux系统的默认Python版本方式》通过删除原Python软链接并创建指向python3.6的新链接,可切换系统默认Python版本,需注意版本冲突、环境混乱及维护问题,建议使用pyenv... 目录更改系统的默认python版本软链接软链接的特点创建软链接的命令使用场景注意事项总结更改系统的默

Linux升级或者切换python版本实现方式

《Linux升级或者切换python版本实现方式》本文介绍在Ubuntu/Debian系统升级Python至3.11或更高版本的方法,通过查看版本列表并选择新版本进行全局修改,需注意自动与手动模式的选... 目录升级系统python版本 (适用于全局修改)对于Ubuntu/Debian系统安装后,验证Pyt

MySQL 升级到8.4版本的完整流程及操作方法

《MySQL升级到8.4版本的完整流程及操作方法》本文详细说明了MySQL升级至8.4的完整流程,涵盖升级前准备(备份、兼容性检查)、支持路径(原地、逻辑导出、复制)、关键变更(空间索引、保留关键字... 目录一、升级前准备 (3.1 Before You Begin)二、升级路径 (3.2 Upgrade

Python跨文件实例化、跨文件调用及导入库示例代码

《Python跨文件实例化、跨文件调用及导入库示例代码》在Python开发过程中,经常会遇到需要在一个工程中调用另一个工程的Python文件的情况,:本文主要介绍Python跨文件实例化、跨文件调... 目录1. 核心对比表格(完整汇总)1.1 自定义模块跨文件调用汇总表1.2 第三方库使用汇总表1.3 导