安卓调用手机摄像头和相册

这篇具有很好参考价值的文章主要介绍了安卓调用手机摄像头和相册。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

调用摄像头和相册

调用摄像头进行拍照

  • 新建一个CameraAlbumTest项目,修改activity_main.xml中的代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/takePhotoBtn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="take photo" />

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal" />

</LinearLayout>
  • 可以看到在布局文件当中,有一个Button和一个ImageView.Button是用于打开摄像头进行拍照的,而ImageView则是用于将拍到图片显示出来.
  • 在MainActivity中编写调用摄像头的代码逻辑
package com.zb.cameraalbumtest

import 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.util.Log
import androidx.core.content.FileProvider
import kotlinx.android.synthetic.main.activity_main.*
import java.io.File

/**
* @Description: 
* @author zb~
* @date 2022/12/21
*/
class MainActivity : AppCompatActivity() {
    val takePhoto = 1
    lateinit var imageUri: Uri
    lateinit var outputImage: File
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        takePhotoBtn.setOnClickListener {
            //创建File对象,用于存储拍照后的图片
            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.zb.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) {
                    //将拍摄的照片显示出来
                    Log.d("MainActivity", "进入")
                    val bitmap = BitmapFactory.decodeStream(
                        contentResolver.openInputStream(imageUri)
                    )
                    imageView.setImageBitmap(rotateIfRequire(bitmap))
                }
            }
        }
    }

    private fun rotateIfRequire(bitmap: Bitmap): Bitmap {
        val exif = ExifInterface(outputImage.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 rotateBitmap = Bitmap.createBitmap(
            bitmap, 0, 0, bitmap.width, bitmap.height,
            matrix, true
        )
        bitmap.recycle() //将不需要的Bitmap对象进行回收
        return rotateBitmap
    }
}
  • 首先创建了一个File对象,用于存储摄像头拍下的图片,这里将图片命名为output_image.jpg
  • 并且存放在手机SD卡的应用关联缓存目录下,所谓关联缓存目录就是SD卡中专门用于存放当前缓存数据的位置,调用getExternalCacheDir()方法可以得到这个目录.其具体的路径是:/sdcard/Android/data//cache
  • 至于为什么要使用这个关联缓存来存放图片是因为,从Android6.0系统开始,读写SD卡别列为了危险权限,如果将如片放在SD卡任何目录,都要进行运行时权限处理才行,而使用应用关联目录则可以跳过这一步
  • 另外,从Android10.0系统开始,公有的SD目录已经不再允许被应用程序直接访问了,而是要使用作用域存储才可以.
  • 接着会进行一个判断,如果运行设备的系统版本低于Android7.0就调用Uri的fromFile()方法将File对象转换成为Uri对象.
  • 这个Uri对象标识着output_image.jpg这张图片的本地真是路径
  • 否者就调用FileProvider的getUriForFile()方法将File对象转换成为一个封装过的Uri对象.
  • getUriForFile()方法接受三个参数:第一个参数要求传入Context对象,第二个参数可以是任意唯一的字符串,第三个参数则是我们刚刚创建的File对象
  • 之所以要进行这样一层转换是因为从Android7.0开始,直接使用本地真实的Uri被认为是不安全的,会抛出一个FileUriExposedException异常,而FileProvider则是一种特殊的ContentProvider,它使用了和ContentProvider类似的机制来对数据进行保护,可以选择性地将封装过的Uri共享给外部,从而提高应用的安全性.
  • 接下来构建了一个Intent对象,并将这个Intent得action指定为android.media.action.IMAGE_GAPTURE,在调用Intent.putExtra()方法来指定图片输出得地址,这里填入刚刚得到得Uri对象系统会找出能够响应这个Intent的Activity去启动.
  • 这样相机程序就会被打开,拍下的照片会被存放到output_image.jpg当中
  • 由于刚才使用的是startActivityForResult()启动Activity的,因此拍照完之后会有结果返回到onActivityResult()方法当中,如果发现拍照成功,就可以调用BitmapFactory的decodeStream()方法将output_image.jpg这张照片解析成为Bitmap对象,然后把它设置到ImageView中显示出来.
  • 需要注意的是,调用照相机程序去拍照可能会在一些手机上发生照片旋转的情况,这是因为这些手机认为打开摄像头进行拍摄是手机就应该是横屏的,因此回到竖屏的情况下就会发生90°旋转
  • 为此在代码当中加上了判断图片方向的代码,如果发现图片需要进行翻转,那么就先将图片旋转相应的角度,然后再显示到界面上.
  • 还没有完,因为FileProvider是一种特殊的ContentProvider,所以需要在AndroidManifest.xml当中对他进行注册才行.
<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="com.zb.cameraalbumtest.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDES_PATHS"
        android:resource="@xml/file_paths" />
</provider>
  • android:name属性的值是固定
  • android:authorities属性的值,必须和刚才FileProvider.getUriFile()方法第二参数值是一致的
  • 另外还需要在标签当中使用标签来指定Uri的共享路径,并引用了一个@xml/file_paths资源
  • 在res目录下面创建这个资源
<?xml version="1.0" encoding="utf-8" ?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path
        name="my_images"
        path="/" />

</paths>
  • external-path就是用来指定Uri共享路径的,name属性的值可以随便填写

  • path属性的值就表示共享的具体路径,这里使用了一个单斜线便是将整个SD卡进行共享,当然也可以仅仅共享存放output_image.jpg这张图片的路径.

  • 这样代码就变写完了,运行项目,点击take photo就可以进行拍照了文章来源地址https://www.toymoban.com/news/detail-486952.html

从相册当中选取图片

  • 编辑activity_main.xml文件,在布局当中添加一个按钮用于,从相册当中选择图片
    <Button
        android:id="@+id/fromAlbumBtn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="from album"/>
  • 添加一个全局变量
    val takePhoto = 1
  • 编写该按钮的点击事件
        fromAlbumBtn.setOnClickListener {
            //打开文件选择器
            val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
            intent.addCategory(Intent.CATEGORY_OPENABLE)
            //指定只显示图片
            intent.type = "image/*"
            startActivityForResult(intent, fromAlbum)
        }
  • 在fromAlbum按钮的点击事件当中,先构建了一个Intent对象,并将它的action指定为Intent.ACTION_OPEN_DOCUMENT,表示打开系统的文件选择器,接着给这个Intent对象设置一些条件过滤,只允许可打开的图片显示出来,接着调用startActivityForResult()方法,我们给startActivityForResult()方法的第二个参数传入值为我们新定义的全局变量,这样当选择完图片之后会回到onActivityResult()方法是,就会进入fromAlbum的条件下处理图片
  • 编写onActivityResult()方法当中的逻辑
            fromAlbum -> {
                if (resultCode == Activity.RESULT_OK && data != null) {
                    data.data?.let { uri ->
                        //选择将图片进行显示
                        val bitmap = getBitmapFromUri(uri)
                        imageView.setImageBitmap(bitmap)
                    }
                }
            }
  • 调用了返回Intent的getData()方法来获取Uri,然后调用getBitmapFromUri()方法将Uri转换成为Bitmap对象,最终将图片显示到界面上
  • 编写getBitmapFromUri()方法
    private fun getBitmapFromUri(uri: Uri) = contentResolver.openFileDescriptor(uri, "r")?.use {
        BitmapFactory.decodeFileDescriptor(it.fileDescriptor)
    }

到了这里,关于安卓调用手机摄像头和相册的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 记录--h5调用手机摄像头踩坑

    一般业务也很少接触摄像头,有也是现成的工具库扫个二维码。难得用一次,记录下踩坑。 这个就不用多说了,缺点就是没办法自定义界面,它是调用的系统原生相机界面。 由于我需要自定义界面,就像下面这样: 所以我选择了这个方案,这个 api 使用起来其实很简单: 可

    2024年02月08日
    浏览(33)
  • h5调用手机摄像头获取图片用于人脸识别

    1、安卓手机获取前置摄像头,并在video标签显示 注:navigator.mediaDevices.getUserMedia文档说明兼容Safari11,实测不好用 2、苹果手机获取前置摄像头拍照上传,用于人脸识别 注:该方法在安卓手机也可使用 3、附件 //exif.js exif.js //rotate-photo.js rotate-photo.js

    2024年02月11日
    浏览(35)
  • Python+OpenCV 调用手机摄像头并实现人脸识别

    文章内容 : 1、windows 环境下安装 OpenCV 机器视觉环境搭建; 2、基于通过 Python+OpenCV 调用 手机摄像头 并实现人脸检测识别。 操作环境:Windows 10 64位 开发 IDE:Spyder 4.2.5 Python:3.8 OpenCV:OpenCv-Python 4.5.3 硬件需要:PC(win10)、手机 主要介绍使用 pip 安装 OpenCV(使用.whl文件安装

    2024年02月09日
    浏览(35)
  • h5端调用手机摄像头实现扫一扫功能

     一、前言         最近有遇到一个需求,在h5浏览器中实现扫码功能,其本质便是打开手机摄像头定时拍照,特此做一个记录。主要技术栈采用的是vue2,使用的开发工具是hbuilderX。         经过测试发现部分浏览器并不支持打开摄像头,测试了果子,华子和米,发现

    2024年03月14日
    浏览(76)
  • 【计算机视觉 · OpenCV】使用 OpenCV 调用手机摄像头

    Droidcam 是一款可以将手机变成网络摄像头的工具,我们可以利用 Droidcam 让 OpenCV 拥有调用手机摄像头的能力。 2.1 安装 DroidCam 在手机和电脑上分别安装 DroidCam 的客户端和服务端 下载地址:https://pan.baidu.com/s/1DrBn3P1Bx-SXa4d6oziifA?pwd=gr1o 提取码:gr1o 2.2 测试连接状态 手机和电脑需

    2024年02月09日
    浏览(33)
  • 安卓手机做电脑摄像头(USB连接1080P 60FPS低延迟非常稳定)

            在网上找了非常久的方案,有Droidcam的还有一些别的软件,经过我测试基本不是分辨率不够就是比较延迟卡顿,无线网是没那么稳定,那些软件也比较久,经过我的搜索终于找到个方法能达到1080P60低延迟0卡顿。 第一步,下载IP摄像头专业版 ,界面如下图所示,别

    2024年02月03日
    浏览(36)
  • 移动端利用 input 标签调用手机摄像头拍照,实现人脸验证的功能

    近期在做项目时,有一个需求需要实现人脸识别功能,该功能的底层原理就是利用手机的拍照功能,获取用户的人脸图片,然后调用公安部的图像库进行逐一比对。实现这个功能只需要两步,第一步就是获取用户人脸图片;第二步就是将图片传给后端进行人脸比对。由于现在

    2024年02月16日
    浏览(30)
  • H5 页面通过navigator.mediaDevices.getUserMedia调用手机摄像头拍照上传

    需求: 某知名化妆品牌,要做个在线问卷调查。需要试用着自拍上传 注:使用navigator.mediaDevices.getUserMedia 需要使用https请求协议否者视为不安全,无法访问,开发阶段需要将启动改为https 在package.json中 前端开发环境启动项目将http协议改为https协议    授权,默认前置,切换

    2024年02月11日
    浏览(41)
  • 【学习笔记】Yolov5调用手机摄像头实时检测(环境配置+实现步骤)

    我们需要首先从GitHub获取到yolov5的源码,直达链接如下: https://github.com/ultralytics/yolov5 打开后按照如下步骤下载源码压缩包即可 权重文件下载地址:https://download.csdn.net/download/liujiahao123987/87400892 注:我用的iOS,安卓版本没有\\\"Lite\\\" 需要的就是这个局域网,每个人的都不一样 需

    2023年04月25日
    浏览(37)
  • vue&h5获取手机前置摄像头(安卓&ios),input capture属性和navigator.mediaDevices

    调用前置摄像头 capture=\\\"user\\\" 调用后置摄像头capture=\\\"environment\\\"或其他只适用于ios 根据官网解释 iOS最遵守遵守HTML5规范,其次是X5内核,安卓的webview基本忽略了capture。 官方文档:www.w3.org/TR/2018/REC-html-media-capture-20180201/ 对于安卓,亲测capture=\\\"user\\\"效果是,第一次打开前置摄像无效

    2024年02月10日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包