Android 调用系统相册、系统相机拍照

Android 调用系统相册、系统相机拍照工具类

第一步(准备工作):设置文件共享

1.1、指定 FileProvider

新建FileProvider类,名字随意,继承自FileProvider

public class MainFileProvider extends FileProvider {
}

1.2 、清单中添加FileProvider、对应权限

修改AndroidManifest.xml文件

<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.myapp"><!--如果有多个摄像头默认使用后置摄像头--><uses-featureandroid:name="android.hardware.camera"android:required="false" /><uses-permission android:name="android.permission.CAMERA" /><!--Android10以下申请这个--><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><!--Android11()以上申请这个--><uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /><application...><providerandroid:name=".MainFileProvider"android:authorities="${applicationId}.fileProvider"android:exported="false"android:grantUriPermissions="true"><meta-dataandroid:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/provider_paths" /></provider>...</application>
</manifest> 

1.3、指定可共享的目录

创建xml文件放于路径res/xml目录下,没有xm文件夹就手动创建
provider_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths><!--name: 名称标志字符串,不可以同名!--><!--path: 文件夹“相对路径”,完整路径取决于当前的标签类型。传空,代表你整个对应路径都可以用于共享--><root-pathname="root"path="" /><files-pathname="files"path="." /><cache-pathname="cache"path="." /><external-pathname="external"path="." /><external-files-pathname="external_files"path="." /><!-- 此标签需要 support-v4:25.0.0以上才可以使用--><external-cache-pathname="external_cache"path="." /></paths>

第二步(工具类):

1.1、工具类代码

PhotoImagePicker.java

/*** 调用系统拍照、系统相册* 使用前请自行进行权限申请* 拍照图片会保存在/storage/emulated/0/Android/data/<应用包名>/files/Pictures*/
public class PhotoImagePicker {private static volatile PhotoImagePicker instance = null;private PhotoPickCallback callback;private static final int PICK_IMAGE_CHOOSER_REQUEST_CODE = 200;private Uri outputFileUri;//拍照输出的uripublic static PhotoImagePicker getInstance() {if (instance == null) {synchronized (PhotoImagePicker.class) {if (instance == null)instance = new PhotoImagePicker();}}return instance;}/*** 启动照相机(Activity)*/public void startCamera(Activity activity, PhotoPickCallback callback) {this.callback = callback;outputFileUri = Uri.fromFile(new File(activity.getExternalFilesDir(Environment.DIRECTORY_PICTURES), System.currentTimeMillis() + ".jpg"));Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);intent.putExtra(MediaStore.EXTRA_OUTPUT, getIntentUri(activity, outputFileUri));activity.startActivityForResult(intent, PICK_IMAGE_CHOOSER_REQUEST_CODE);}/*** 启动照相机(Fragment)*/public void startCamera(Fragment fragment, PhotoPickCallback callback) {this.callback = callback;outputFileUri = Uri.fromFile(new File(fragment.requireContext().getExternalFilesDir(Environment.DIRECTORY_PICTURES), System.currentTimeMillis() + ".jpg"));Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);intent.putExtra(MediaStore.EXTRA_OUTPUT, getIntentUri(fragment.requireContext(), outputFileUri));fragment.startActivityForResult(intent, PICK_IMAGE_CHOOSER_REQUEST_CODE);}/*** 启动图库选择器(Activity)*/public void startGallery(Activity activity, PhotoPickCallback callback) {this.callback = callback;Intent intent = new Intent(Intent.ACTION_GET_CONTENT);intent.addCategory(Intent.CATEGORY_OPENABLE);intent.setType("image/*");activity.startActivityForResult(intent, PICK_IMAGE_CHOOSER_REQUEST_CODE);}/*** 启动图库选择器(Fragment)*/public void startGallery(Fragment fragment, PhotoPickCallback callback) {this.callback = callback;Intent intent = new Intent(Intent.ACTION_GET_CONTENT);intent.addCategory(Intent.CATEGORY_OPENABLE);intent.setType("image/*");fragment.startActivityForResult(intent, PICK_IMAGE_CHOOSER_REQUEST_CODE);}/*** 启动文件选择器(Activity)*/public void startChooser(Activity activity, String mime, PhotoPickCallback callback) {this.callback = callback;Intent intent = new Intent(Intent.ACTION_GET_CONTENT);intent.addCategory(Intent.CATEGORY_OPENABLE);intent.setType(mime);activity.startActivityForResult(intent, PICK_IMAGE_CHOOSER_REQUEST_CODE);}/*** 启动文件选择器(Fragment)*/public void startChooser(Fragment fragment, String mime, PhotoPickCallback callback) {this.callback = callback;Intent intent = new Intent(Intent.ACTION_GET_CONTENT);intent.addCategory(Intent.CATEGORY_OPENABLE);intent.setType(mime);fragment.startActivityForResult(intent, PICK_IMAGE_CHOOSER_REQUEST_CODE);}/*** 图片选择结果回调,在 {@link Activity#onActivityResult(int, int, Intent)} 中调用*/@SuppressWarnings("JavadocReference")public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {onActivityResultInner(activity, null, requestCode, resultCode, data);}/*** 图片选择结果回调,在 {@link Fragment#onActivityResult(int, int, Intent)} 中调用*/public void onActivityResult(Fragment fragment, int requestCode, int resultCode, Intent data) {onActivityResultInner(null, fragment, requestCode, resultCode, data);}private void onActivityResultInner(Activity activity, Fragment fragment, int requestCode, int resultCode, Intent data) {if (resultCode != Activity.RESULT_OK) {if (callback != null)callback.onCanceled();return;}Context context;if (activity != null) {context = activity;} elsecontext = fragment.getContext();if (context != null && requestCode == PICK_IMAGE_CHOOSER_REQUEST_CODE) {boolean isCamera = true;if (data != null && data.getData() != null) {String action = data.getAction();isCamera = action != null && action.equals(MediaStore.ACTION_IMAGE_CAPTURE);}Uri pickImageUri = isCamera || data.getData() == null ? outputFileUri : data.getData();handlePickImage(context, pickImageUri);}}/*** 选择图片结果回调*/private void handlePickImage(Context context, Uri imageUri) {if (callback != null)callback.onPickImage(handleUri(context, imageUri));outputFileUri = null;}/*** 兼容 Android N,Intent中不能使用 file:///**/private Uri getIntentUri(Context context, @NonNull Uri uri) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {return FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".fileProvider", new File(Objects.requireNonNull(uri.getPath())));} elsereturn uri;}/*** 处理返回图片的 uri,content 协议自动转换 file 协议,避免 {@link FileNotFoundException}*/private Uri handleUri(Context context, Uri uri) {String realPath = "";if (DocumentsContract.isDocumentUri(context, uri)) {//如果是document类型的Uri,则通过document id处理String docId = DocumentsContract.getDocumentId(uri);if ("com.android.providers.media.documents".equals(uri.getAuthority())) {String id = docId.split(":")[1]; // 解析出数字格式的idString selection = MediaStore.Images.Media._ID + "=" + id;realPath = getRealPathFromUri(context, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection);} else if ("com.android.providers.downloads.documents".equals(uri.getAuthority())) {Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.parseLong(docId));realPath = getRealPathFromUri(context, contentUri, null);}} else if ("content".equalsIgnoreCase(uri.getScheme())) {//如果是content类型的Uri,则使用普通方式处理realPath = getRealPathFromUri(context, uri, null);} else if ("file".equalsIgnoreCase(uri.getScheme()))  //如果是file类型的Uri,直接获取图片路径即可realPath = uri.getPath();if (!TextUtils.isEmpty(realPath))return Uri.fromFile(new File(realPath));elsereturn uri;}/*** 获取文件的真实路径,比如:content://media/external/images/media/74275 的真实路径 file:///storage/sdcard0/Pictures/X.jpg* http://stackoverflow.com/questions/20028319/how-to-convert-content-media-external-images-media-y-to-file-storage-sdc*/private String getRealPathFromUri(Context context, Uri uri, String selection) {Cursor cursor = null;try {String[] proj = {MediaStore.Images.Media.DATA};cursor = context.getContentResolver().query(uri, proj, selection, null, null);if (cursor == null)return "";if (cursor.moveToFirst())return cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA));return "";} catch (IllegalStateException e) {return e.getMessage();} finally {if (cursor != null)cursor.close();}}
}

1.2、回调类代码

PhotoPickCallback.java

public interface PhotoPickCallback {/*** 用户取消回调*/void onCanceled();/*** 图片返回回调*/void onPickImage(@Nullable Uri imageUri);
}

第三步(使用):

调用相机

                            PhotoImagePicker.getInstance().startCamera(this, new PhotoPickCallback() {@Overridepublic void onCanceled() {//用户取消}@Overridepublic void onPickImage(@Nullable Uri imageUri) {//TODO do some things}});

调用相册

              PhotoImagePicker.getInstance().startGallery(this, new PhotoPickCallback() {@Overridepublic void onCanceled() {//用户取消}@Overridepublic void onPickImage(@Nullable Uri imageUri) {//TODO do some things}});

设置回调回传

    @Overridepublic void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {super.onActivityResult(requestCode, resultCode, data);PhotoImagePicker.getInstance().onActivityResult(this, requestCode, resultCode, data);}

注意事项:

  • 使用前请自行进行对应权限申请
  • 拍照图片默认保存在/storage/emulated/0/Android/data/<应用包名>/files/Pictures

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

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

相关文章

【小白专用 已验证24.6.7】C# MySQL数据库访问操作封装类

一、底层库介绍 本文主要介绍数据库访问操作类&#xff0c;包含&#xff1a;SQL插入脚本、SQL查询脚本、数据库表是否存在判断、带参脚本执行、包含事务回滚脚本执行、存储过程脚本等等。 特殊说明 在使用之前&#xff0c;先安装 MySql.Data 插件 二、底层库源码 2.1 程序源…

C++ 24 之 拷贝构造函数

c24拷贝构造函数.cpp #define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std;class Person3 { private:int p_age; public:// 构造函数分类&#xff1a;// 按参数分类&#xff1a;1、有参 2、无参// 按类型分类:普通、拷贝&#xff08;复制&…

仲恺ZK——信计专业《软件体系结构》复习总结

前言 以下是我在总结的复习内容&#xff0c;有需要可以参考借鉴一下。我的主页还有另外一篇《2024年考试回忆》&#xff0c;两者结合起来复习&#xff0c;帮助你轻松过考试&#x1f60a;。总的来说&#xff0c;考试不会太难&#xff0c;只要你了解了各类设计模式的含义即可&am…

国家秘密的密级、保密期限和知悉范围变更的,应当及时( )通知知悉范围内的机关、单位或者人员。

国家秘密的密级、保密期限和知悉范围变更的&#xff0c;应当及时&#xff08; &#xff09;通知知悉范围内的机关、单位或者人员。详细答案查看 A. 口头B. 电话 C. 无须D. 书面 &#xff08; &#xff09;保密行政管理部门主管全国的保密工作。&#xff08; &#xff09;级以上…

第2章 Rust初体验5/8:match表达式和模式匹配:更富表达力:猜骰子冷热游戏

讲动人的故事,写懂人的代码 2.5 故事3: 比较答案与点数之和 贾克强:“同学们,我们开始用三种语言来实现故事3吧!” 2.5.1 Rust版故事3 这个故事实在是轻松容易地实现了。赵可菲照着书,一下子就写好了。 @@ -1,4 +1,5 @@use rand::Rng; +use std::cmp::Ordering;use std…

简单工厂模式(大话设计模式)C/C++版本

简单工厂模式 C版本 参考&#xff1a;https://www.cnblogs.com/Galesaur-wcy/p/15926669.html #include <iostream> using namespace std; // 运算类 class Operation { private:double _NumA;double _NumB;public:void SetNumA(){cout << "Enter a double…

【动态规划】| 路径问题之最小路径和 力扣64

&#x1f397;️ 主页&#xff1a;小夜时雨 &#x1f397;️专栏&#xff1a;动态规划 &#x1f397;️如何活着&#xff0c;是我找寻的方向 目录 1. 题目解析2. 代码 1. 题目解析 题目链接: https://leetcode.cn/problems/minimum-path-sum/description/ 这道题目和之前一道…

使用CSS、JavaScript、jQuery三种方式实现手风琴效果

手风琴效果有不少&#xff0c;王者荣耀官网&#xff08;源网址 https://pvp.qq.com/raiders/ &#xff09;有一处周免英雄&#xff0c;使用的就是手风琴效果&#xff0c;如图所示。 我试着用css、js、jQuery三种方式实现了这种效果&#xff0c;最终效果差不多&#xff0c;美中不…

周四 A股震荡走低,行情总结

文章正文 周四&#xff0c;A股全日震荡走低&#xff0c;上证指数收跌0.28%&#xff0c;深成指跌近0.创业板指跌0.09%。猪肉、有色金属、中药、磷化工、煤炭、房地产、白酒行业跌幅靠前。科特估概念股掀起20cm涨停潮&#xff0c;半导体、机器人、消费电子、光伏、虚拟电厂概念股…

Webrtc支持FFMPEG硬解码之解码实现(三)

前言 此系列文章分分为三篇, Webrtc支持FFMPEG硬解码之Intel(一)-CSDN博客 Webrtc支持FFMPEG硬解码之NVIDA(二)-CSDN博客 Webrtc支持FFMPEG硬解码之解码实现(三)-CSDN博客 AMD硬解目前还没找到可用解码器,欢迎留言交流 环境 Windows平台 VS2019 <

问题:以下描写乡村词语的是() #媒体#媒体#知识分享

问题&#xff1a;以下描写乡村词语的是&#xff08;&#xff09; A&#xff0e;高楼林立 B&#xff0e;车水马龙 C&#xff0e;依山傍水 参考答案如图所示

Docker面试整理-Docker容器与虚拟机比较,安全性如何?

Docker 容器与传统的虚拟机(VM)在许多方面都不同,其中之一是安全性。每种技术都有其特定的安全特点和潜在的风险。了解这些差异可以帮助你做出更好的决策,适当地使用它们来保障系统安全。 容器与虚拟机的安全性对比: 1. 隔离性: ● 虚拟机:提供较高的隔离性。每个虚拟机…

ThinkPHP+Bootstrap简约自适应网址导航网站源码

使用 ThinkPHPbootstrap 开发&#xff0c;后台采用全局 ajax 无刷新加载&#xff0c;前后台自适应&#xff0c;前台页面非常简洁适合自己收藏网站或做导航网站。 搭建教程&#xff1a; 1.整个主机 2.绑定解析域名 3.上传源码&#xff0c;解压 把解压出来的 nav.sql 文件导入数…

STM32自己从零开始实操05:接口电路原理图

一、TTL 转 USB 驱动电路设计 1.1指路 延续使用芯片 CH340E 。 实物图 原理图与封装图 1.2数据手册重要信息提炼 1.2.1概述 CH340 是一个 USB 总线的转接芯片&#xff0c;实现 USB 与串口之间的相互转化。 1.2.2特点 支持常用的 MODEM 联络信号 RTS&#xff08;请求发送&…

ubuntu下使用cmake编译opencv4.8.0+ffmpeg4.2.2+cuda11.1

1.源码下载 &#xff08;1&#xff09;下载ffmpeg4.2.2、opencv4.8.0源码&#xff0c;这里提供一个百度网盘地址&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1pBksr0_RtKL0cM6Gsf2MGA?pwdcyai 提取码&#xff1a;cyai &#xff08;2&#xff09;解压所有文件 例…

okHttp的https请求忽略ssl证书认证

使用okhttp请求第三方https接口返回异常 sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target意思就是非安全的调用&#…

我的高考往事

高考对于每一个参加过的人来说&#xff0c;都是一段非常难忘的回忆。 我参加高考&#xff0c;是在2001年。虽然迄今已经过去了23年&#xff0c;但很多细节仍然记忆犹新。 今天这篇文章&#xff0c;我就和大家分享一下&#xff0c;我的高考往事。 █ 青少年时代 我的老家是在江西…

开个技术外挂 | 数字孪生技术如何成为美洲杯帆船赛成功的关键?

若您对数据分析以及人工智能感兴趣&#xff0c;欢迎与我们一起站在全球视野关注人工智能的发展&#xff0c;与Forrester 、德勤、麦肯锡等全球知名企业共探AI如何加速工业变革&#xff0c;共享众多优秀行业案例&#xff0c;开启AI人工智能全球新视野&#xff01;&#xff01; …

Ubuntu Server 20.04挂载磁盘

先查看磁盘信息&#xff1a; sudo fdisk -l然后提供NTFS文件系统支持&#xff1a; sudo mkfs.ntfs /dec/sda -F这个过程非常久… 处理完如上图。&#xff08;ps. 这个 Have a nice day. 好浪漫~&#xff09; 接着挂载磁盘&#xff1a; sudo mount /dev/sda ~/device设置开机…

计算机网络(4) 最长前缀匹配(路由转发表)

一.路由转发 网络数据包IP段只包含源地址与目的地址&#xff0c;经过数据链路层包装与物理层信号形式转换&#xff0c;最终经由不同的链路节点到达目的地址。这个过程是一步一步&#xff08;hop by hop&#xff09;进行的&#xff0c;路过一个路由节点则称为一跳。每个路由节点…