Android---打开相机拍照

news2024/12/23 6:06:53

简单实现打开系统系统相机拍一张图片并显示在UI上,适用与个人主页头像的切换。

1. 添加权限。AndroidManifest.xml里添加使用相机的权限。

<uses-permission android:name="android.permission.CAMERA"/>

2. 布局。布局内容比较交单,一个Button用来打开相机;一个ImageView用来接收拍摄的图片。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btn_open_gallery"
        android:layout_width="150dp"
        android:layout_height="75dp"
        android:layout_centerHorizontal="true"
        android:text="拍照"
        android:textSize="20sp"/>

    <ImageView
        android:id="@+id/img"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="10dp"
        android:layout_below="@+id/btn_open_gallery"/>

</RelativeLayout>

3. 动态申请权限。Google 在 Android 6.0 开始引入了权限申请机制,除了在AndroidManifest.xml里申请静态权限,还需要在代码里动态申请。这里需要申请系统相机的权限。

    /**
     * 申请动态权限
     */
    private void requestPermission() {
        if (ContextCompat.checkSelfPermission(this,Manifest.permission.CAMERA)
                != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.CAMERA}, PERMISSION_REQUEST_CODE);
        }else {
            takePhoto();
        }
    }

4. 申请权限的回调。

    /**
     * 用户选择是否开启权限操作后的回调;TODO 同意/拒绝
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == PERMISSION_REQUEST_CODE) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // TODO 用户同意开启权限,打开相机
                takePhoto();
            }else{
                Log.d("HL", "权限申请拒绝!");
            }
        }
    }

5. 创建一个存放拍的照片的文件

    /**
     * 创建一个存放拍的照片的文件
     */
    private File createImageFile() throws IOException {
        // Create an image file name
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault())
                .format(new Date());
        String imageFileName = "JPEG_" + timeStamp + "_";
        Log.d("HL", imageFileName);
        File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
        return File.createTempFile(
                imageFileName,  /* prefix */
                ".bmp",         /* suffix */
                storageDir      /* directory */
        );
    }

6. 打开相机。

    /**
     * 打开相机,选择头像
     */
    private void takePhoto() {
        Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

        // 确保有一个活动来处理意图
        if (takePhotoIntent.resolveActivity(getPackageManager()) != null) {
            // 创建保存图片的文件夹
            File imageFile = null;
            try {
                imageFile = createImageFile();
            }catch (Exception e){
                e.printStackTrace();
            }
            if (imageFile != null) {
                //TODO imageUri 用来接收拍摄的这张照片的真实路径
                imageUri = FileProvider.getUriForFile(this, "com.example.takePhoto.fileprovider", imageFile);
            }

            takePhotoIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
            startActivityForResult(takePhotoIntent, TAKE_PHOTO_REQUEST_CODE);
        }
    }

7. 结果回调。用户拍了一张图片,接收返回的结果并在ImageView里显示。

 @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == TAKE_PHOTO_REQUEST_CODE) {
            if (resultCode == Activity.RESULT_OK) {
                try {
                    InputStream inputStream = getContentResolver().openInputStream(imageUri);
                    Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                    mImg.setImageBitmap(bitmap);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

8.注册内容提供者(Provider)。在 AndroidManifest.xml注册。

其中,android:name属性值是固定的,android:authorities 属性的值必须要和上面takePhoto()方法里的FileProvider.getUriForFile() 方法中的第二个参数一致,并且该参数固定为"包名(com.xxx.xxx).fileprovider"。另外,这里还有<provider>标签的内部使用<meta-data>来指定Uri的共享路径,并引入一个 @xml/file_paths资源。

在 res -> xml 下创建一个File为“ file_paths”文件,添加以下内容

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-files-path name="image_path" path="/" />
</paths>

其中,external-path 就是用来指定 Uri 共享的,name 属性可以随便填写,path 属性的值表示共享的具体路径。

ManiActivity.java 完整代码

package com.example.takephoto;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;

import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.widget.Button;
import android.widget.ImageView;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class MainActivity extends AppCompatActivity {

    private static final int PERMISSION_REQUEST_CODE = 0;
    private static final int TAKE_PHOTO_REQUEST_CODE = 0;
    private Uri imageUri;

    private ImageView mImg;
    private Button mTakePhoto;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mImg = findViewById(R.id.img);
        mTakePhoto = findViewById(R.id.btn_take_photo);

        mTakePhoto.setOnClickListener(v -> {
            requestPermission();
        });
    }

    /**
     * 申请动态权限
     */
    private void requestPermission() {
        if (ContextCompat.checkSelfPermission(this,Manifest.permission.CAMERA)
                != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.CAMERA}, PERMISSION_REQUEST_CODE);
        }else {
            takePhoto();
        }
    }

    /**
     * 用户选择是否开启权限操作后的回调;TODO 同意/拒绝
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == PERMISSION_REQUEST_CODE) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // TODO 用户同意开启权限,打开相机
                takePhoto();
            }else{
                Log.d("HL", "权限申请拒绝!");
            }
        }
    }

    /**
     * 打开相机,选择头像
     */
    private void takePhoto() {
        Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

        // 确保有一个活动来处理意图
        if (takePhotoIntent.resolveActivity(getPackageManager()) != null) {
            // 创建保存图片的文件夹
            File imageFile = null;
            try {
                imageFile = createImageFile();
            }catch (Exception e){
                e.printStackTrace();
            }
            if (imageFile != null) {
                //TODO imageUri 用来接收拍摄的这张照片的真实路径
                imageUri = FileProvider.getUriForFile(this, "com.example.takePhoto.fileprovider", imageFile);
            }

            takePhotoIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
            startActivityForResult(takePhotoIntent, TAKE_PHOTO_REQUEST_CODE);
        }
    }

    /**
     * 创建一个存放拍的照片的文件
     */
    private File createImageFile() throws IOException {
        // Create an image file name
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault())
                .format(new Date());
        String imageFileName = "JPEG_" + timeStamp + "_";
        Log.d("HL", imageFileName);
        File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
        return File.createTempFile(
                imageFileName,  /* prefix */
                ".bmp",         /* suffix */
                storageDir      /* directory */
        );
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == TAKE_PHOTO_REQUEST_CODE) {
            if (resultCode == Activity.RESULT_OK) {
                try {
                    InputStream inputStream = getContentResolver().openInputStream(imageUri);
                    Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                    mImg.setImageBitmap(bitmap);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1034339.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Ubuntu上安装、使用Redis的详细教程

这篇文章简单地介绍一下怎么在linux虚拟机上完成redis的安装及使用。 目录 1、安装redis 2、使用redis 3、启动/关闭redis 启动redis 启动方式一 启动方式二 启动方式三 重启redis 关闭redis 查看redis状态 4、在宿主机连接redis 5、通过java连接redis 创建maven项…

Webpack监视文件修改,自动重新打包文件

方法一&#xff1a;使用watch监视文件变化 在终端中输入以下指令&#xff1a; npx webpack --watch 我们使用这种方法监听文件变化时只会监听我们计算机本地的文件变化&#xff0c;在开发场景中我们的项目是要部署到服务器中的&#xff0c;因此这种方式并不推荐。 方法二&…

proteus中的各种电阻-可变电阻-排阻

在原理图中使用各类型的电阻是很常见的事情&#xff0c;尤其类似与排阻、可变电阻&#xff0c;但这些电阻对于不熟悉proteus的童鞋来说&#xff0c;一下子可能很难找到&#xff0c;或者很难找心中所想的那个类型&#xff0c;这里分类列出&#xff0c;便于大家使用。 文章目录 一…

Kubernetes集群+Keepalived+Nginx+防火墙实例

文章目录 实验前期规划1.拓扑图结构2.实验要求3.实验环境规划 一.kubeadm 部署 K8S 集群架构1.环境准备2.三个节点安装docker3.三个节点安装kubeadm&#xff0c;kubelet和kubectl4.部署K8S集群&#xff08;1&#xff09;初始化&#xff08;2&#xff09;部署网络插件flannel&am…

腾讯云COS+Picgo+Typora图床搭建

文章目录 什么是图床&#xff1f;配置腾讯云COS整体流程注册腾讯云账号并开通配置COS下载并配置PicGoTypora配置PicGo 可视化管理工具 什么是图床&#xff1f; 百度百科是这样解释的&#xff1a; 图床一般是指储存图片的服务器&#xff0c;有国内和国外之分。国外的图床由于有…

2023-9-22 整数划分

题目链接&#xff1a;整数划分 转化成背包问题 #include <iostream> #include <algorithm>using namespace std;const int N 1010, mod 1e9 7;int n; int f[N];int main() {cin >> n;f[0] 1;// i 相当于第i个物品的体积for(int i 1; i < n; i )// j …

计算机视觉: 三维物体生成

三维物体生成与编辑 论文地址: Controllable Mesh Generation Through Sparse Latent Point Diffusion Models 背景 数据是目前数字化和AI领域最宝贵的财富之一&#xff0c;但是对于目前的开发者来说&#xff0c;收集数据都意味着极大的成本。所以建立一个高效的生成模型能极…

Fair原理篇之Fair逻辑动态化通信实现

Fair 逻辑动态化,是对一期布局动态化的增强。为了实现逻辑动态化,我们当时考虑了多种方案,方案主要集中在这三个方面,一种是对google提供的JIT进行裁切,第二种是自定义解析引擎,第三种借助js的能力。 下面主要讲一下几方面: 架构的标准化通信协议的实现js文件的加载与释…

MongoDB 是什么和使用场景概述(技术选型)

一、从NOSQL(Not Only SQL)说起 常见的数据库可以分为下面的两种类型&#xff1a; RDBMS&#xff08;关系型数据库&#xff09;&#xff1a;常见的关系型数据库有 Oracle、DB2、Microsoft SQL Server、Microsoft Access、MySQL&#xff1b;NoSQL&#xff08;非关系型数据库&a…

计算机视觉与深度学习-循环神经网络与注意力机制-RNN(Recurrent Neural Network)、LSTM-【北邮鲁鹏】

目录 举例应用槽填充&#xff08;Slot Filling&#xff09;解决思路方案使用前馈神经网络输入1-of-N encoding(One-hot)&#xff08;独热编码&#xff09; 输出 问题 循环神经网络&#xff08;Recurrent Neural Network&#xff0c;RNN&#xff09;定义如何工作深度Elman Netwo…

DAB-DETR

DAB-DETR&#xff08;2022ICLR&#xff09; DAB&#xff1a;Dynamic Anchor Boxes 贡献&#xff1a; 明确了不是由于learnable queries导致的收敛缓慢 4D anchor Anchor Update Width & Height Modulated Temperature Tuning 前半部分&#xff1a;Why a positional …

每日一题~将有序数组转换为二叉搜索树

原题链接&#xff1a;108. 将有序数组转换为二叉搜索树 - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a; 思路分析&#xff1a; 今天这道题比较简单&#xff0c;我们看一下数组和树之间的联系很容易就能发现规律。 通过简单观察我们发现&#xff0c;位于数组中…

CSDN博客去水印方法

直接在 创作中心->博客 设置这里关了好像就行了&#xff0c;之前方法是找图片链接?后面的一大串字符给去掉。

Java由浅入深理解线程池设计和原理

目录 1 线程1.1 什么是线程&#xff1f;什么是进程&#xff1f;1.2 java中线程的实现方式有几种?1.3 线程的生命周期是什么&#xff1f; 2 线程存在的问题2.1 一个线程只能执行一个任务2.2 线程执行完后销毁,无法复用2.3 线程过多,导致JVM宕机 3 初识线程池3.1 了解J.U.C3.2 线…

计网第五章(运输层)(六)(TCP可靠传输的实现)

目录 一、基本概述 二、具体实现 1.前后沿&#xff1a; 2.利用指针描述发送窗口的状态 3.有差错情况 之前在数据链路层时已经讨论过可靠传输&#xff08;计网第三章&#xff08;数据链路层&#xff09;&#xff08;二&#xff09;&#xff08;可靠传输&#xff09;&#x…

电表智能管理系统-实现智能化、数字化的电力管理

随着信息技术的发展&#xff0c;智能电表已经成为了现代电力管理的重要组成部分。智能电表能够实时监测和记录用电量&#xff0c;自动控制用电&#xff0c;从而实现更加智能、高效的电力管理。 智能电表是一种能够自动监测和记录用电量&#xff0c;并能够自动控制用电的设备…

IDEA中取消双击shift全局搜索

设置如图步骤&#xff1a; 取消双击shift之后&#xff0c;如果想再次使用全局搜索&#xff0c;可以通过&#xff1a; ctrlshifA

Vue与relation-graph:高效打造关系图的秘诀

产品提需求啦&#xff0c;有一个需求就是实现一个功能&#xff1a;展现各个文件之间的调用关系&#xff0c;通过关系图的形式进行展示出来。 之前考虑使用antv x6实现此功能&#xff0c;但是考虑到只是展示的功能&#xff0c;也不需要进行交互&#xff0c;所以放弃使用antv x6&…

【操作系统笔记十二】Linux常用基础命令

Linux 常用快捷键 Tab 命令或路径等的补全键&#xff0c;特别常用的快捷键Ctrl insert 复制命令行内容&#xff08;常用可提高效率&#xff09;Shift insert 粘贴命令行内容&#xff08;常用可提高效率&#xff09;Ctrl C 中断当前任务&#xff08;退出&#xff09;Ctrl Z…

Java笔记:看清类加载过程

1 类加载的过程 1.1 加载 “加载”是“类加载”(Class Loading)过程的第一步。这个加载过程主要就是靠类器实现的&#xff0c;包括用户自定义类加载器。 加载的过程 在加载的过程中&#xff0c;JVM主要做3件事情 1&#xff09;通过一个类的全限定名来获取定义此类的二进制字节…