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

相关文章

IDEA如何切换数据库版本mysql5或mysql8

《IDEA如何切换数据库版本mysql5或mysql8》本文介绍了如何将IntelliJIDEA从MySQL5切换到MySQL8的详细步骤,包括下载MySQL8、安装、配置、停止旧服务、启动新服务以及... 目录问题描述解决方案第一步第二步第三步第四步第五步总结问题描述最近想开发一个新应用,想使用mysq

java脚本使用不同版本jdk的说明介绍

《java脚本使用不同版本jdk的说明介绍》本文介绍了在Java中执行JavaScript脚本的几种方式,包括使用ScriptEngine、Nashorn和GraalVM,ScriptEngine适用... 目录Java脚本使用不同版本jdk的说明1.使用ScriptEngine执行javascript2.

Debian如何查看系统版本? 7种轻松查看Debian版本信息的实用方法

《Debian如何查看系统版本?7种轻松查看Debian版本信息的实用方法》Debian是一个广泛使用的Linux发行版,用户有时需要查看其版本信息以进行系统管理、故障排除或兼容性检查,在Debia... 作为最受欢迎的 linux 发行版之一,Debian 的版本信息在日常使用和系统维护中起着至关重要的作

Idea调用WebService的关键步骤和注意事项

《Idea调用WebService的关键步骤和注意事项》:本文主要介绍如何在Idea中调用WebService,包括理解WebService的基本概念、获取WSDL文件、阅读和理解WSDL文件、选... 目录前言一、理解WebService的基本概念二、获取WSDL文件三、阅读和理解WSDL文件四、选择对接

Java调用Python代码的几种方法小结

《Java调用Python代码的几种方法小结》Python语言有丰富的系统管理、数据处理、统计类软件包,因此从java应用中调用Python代码的需求很常见、实用,本文介绍几种方法从java调用Pyt... 目录引言Java core使用ProcessBuilder使用Java脚本引擎总结引言python

你的华为手机升级了吗? 鸿蒙NEXT多连推5.0.123版本变化颇多

《你的华为手机升级了吗?鸿蒙NEXT多连推5.0.123版本变化颇多》现在的手机系统更新可不仅仅是修修补补那么简单了,华为手机的鸿蒙系统最近可是动作频频,给用户们带来了不少惊喜... 为了让用户的使用体验变得很好,华为手机不仅发布了一系列给力的新机,还在操作系统方面进行了疯狂的发力。尤其是近期,不仅鸿蒙O

什么是 Ubuntu LTS?Ubuntu LTS和普通版本区别对比

《什么是UbuntuLTS?UbuntuLTS和普通版本区别对比》UbuntuLTS是Ubuntu操作系统的一个特殊版本,旨在提供更长时间的支持和稳定性,与常规的Ubuntu版本相比,LTS版... 如果你正打算安装 Ubuntu 系统,可能会被「LTS 版本」和「普通版本」给搞得一头雾水吧?尤其是对于刚入

windows端python版本管理工具pyenv-win安装使用

《windows端python版本管理工具pyenv-win安装使用》:本文主要介绍如何通过git方式下载和配置pyenv-win,包括下载、克隆仓库、配置环境变量等步骤,同时还详细介绍了如何使用... 目录pyenv-win 下载配置环境变量使用 pyenv-win 管理 python 版本一、安装 和

java如何调用kettle设置变量和参数

《java如何调用kettle设置变量和参数》文章简要介绍了如何在Java中调用Kettle,并重点讨论了变量和参数的区别,以及在Java代码中如何正确设置和使用这些变量,避免覆盖Kettle中已设置... 目录Java调用kettle设置变量和参数java代码中变量会覆盖kettle里面设置的变量总结ja

如何在页面调用utility bar并传递参数至lwc组件

1.在app的utility item中添加lwc组件: 2.调用utility bar api的方式有两种: 方法一,通过lwc调用: import {LightningElement,api ,wire } from 'lwc';import { publish, MessageContext } from 'lightning/messageService';import Ca