当前位置: 首页 > news >正文

Android -- 调用系统相册之图片裁剪保存

前言

最近线上反馈,部分vivo手机更换头像时调用系统相册保存图片失败,经本人测试,确实有问题。

经修复后,贴出这块的代码供小伙伴们参考使用。

功能

更换头像选择图片:

  • 调用系统相机拍照,调用系统图片裁剪并保存。
  • 调用系统相册选择照片,调用系统图片裁剪并保存。

此功能需要动态申请 相机和读写外部存储的权限,此处省略了,请自行动态申请添加。

String[] permissions=new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE};

1、布局文件activity_picture.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"><Buttonandroid:id="@+id/takePictureFromCamera"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="拍照" /><Buttonandroid:id="@+id/takePictureFromLib"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="从相册选取" /><ImageViewandroid:id="@+id/img"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="10dp"/>
</LinearLayout>

2、PictureActivity:

public class PictureActivity extends AppCompatActivity {public class Const {public static final int PHOTO_GRAPH = 1;// 拍照public static final int PHOTO_ZOOM = 2; // 相册public static final int PHOTO_RESOULT = 3;// 结果public static final String IMAGE_UNSPECIFIED = "image/*";}public String authority;private ImageView imageView;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_picture);authority = getApplicationContext().getPackageName() + ".fileprovider";imageView = findViewById(R.id.img);findViewById(R.id.takePictureFromCamera).setOnClickListener(v -> openCamera(Const.PHOTO_GRAPH));findViewById(R.id.takePictureFromLib).setOnClickListener(v -> openCamera(Const.PHOTO_ZOOM));}private void openCamera(int type) {Intent intent;if (type == Const.PHOTO_GRAPH) {//打开相机intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);//指定调用相机拍照后照片的储存路径File photoFile = new File(CoreConstants.getNurseDownloadFile(this), "temp.jpg");if (!photoFile.exists()) {photoFile.getParentFile().mkdirs();}Uri uri = FileUtil.getUri(this, authority, photoFile);intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);} else {//打开相册intent = new Intent(Intent.ACTION_PICK, null);intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, Const.IMAGE_UNSPECIFIED);}startActivityForResult(intent, type);}/*** 调用系统的裁剪图片*/private void crop(Uri uri) {try {Intent intent = new Intent("com.android.camera.action.CROP");String contentURl = CoreConstants.getNurseDownloadFile(this)+ File.separator + "temp.jpg";File cropFile = new File(contentURl);Uri cropUri;//在7.0以上跨文件传输uri时候,需要用FileProviderif (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {cropUri = FileProvider.getUriForFile(this, getPackageName() + ".fileprovider", cropFile);intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);} else {cropUri = Uri.fromFile(cropFile);}intent.putExtra(MediaStore.EXTRA_OUTPUT, cropUri);intent.setDataAndType(uri, Const.IMAGE_UNSPECIFIED);intent.putExtra("crop", "true");// 裁剪框的比例,1:1intent.putExtra("aspectX", 1);intent.putExtra("aspectY", 1);// 裁剪后输出图片的尺寸大小intent.putExtra("outputX", 200);intent.putExtra("outputY", 200);intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());// 图片格式intent.putExtra("noFaceDetection", true);// 取消人脸识别intent.putExtra("return-data", true);//是否返回裁剪后图片的Bitmapintent.putExtra("output", cropUri);//重要!!!添加权限,不然裁剪完后报 “保存时发生错误,保存失败”List<ResolveInfo> resInfoList = getPackageManager().queryIntentActivities(intent,PackageManager.MATCH_DEFAULT_ONLY);for (ResolveInfo resolveInfo : resInfoList) {String packageName = resolveInfo.activityInfo.packageName;grantUriPermission(packageName, cropUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);}ComponentName componentName = intent.resolveActivity(getPackageManager());if (componentName != null) {// 开启一个带有返回值的Activity,请求码为PHOTO_REQUEST_CUTstartActivityForResult(intent, Const.PHOTO_RESOULT);}} catch (Exception e) {String s = e.getMessage().toString();}}public Bitmap convertUriToBitmap(Uri uri) {ContentResolver contentResolver = getContentResolver();try {// 将Uri转换为字节数组return BitmapFactory.decodeStream(contentResolver.openInputStream(uri));} catch (Exception e) {e.printStackTrace();return null;}}@Overrideprotected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {super.onActivityResult(requestCode, resultCode, data);// 拍照if (requestCode == Const.PHOTO_GRAPH) {// 设置文件保存路径File picture = new File(CoreConstants.getNurseDownloadFile(this)+ File.separator + "temp.jpg");Uri uri = FileUtil.getUri(this, authority, picture);crop(uri);}if (data == null)return;//读取相册图片if (requestCode == Const.PHOTO_ZOOM) {crop(data.getData());}//处理裁剪后的结果if (requestCode == Const.PHOTO_RESOULT) {Bundle extras = data.getExtras();Bitmap photo = null;if(extras != null) {photo = extras.getParcelable("data");}if (photo == null && data.getData() != null) {//部分小米手机extras是个null,所以想拿到Bitmap要转下photo = convertUriToBitmap(data.getData());}if (photo != null) {//拿到Bitmap后直接显示在Image控件上imageView.setImageBitmap(photo);//将图片上传到服务器
//                String fileName = CommonCacheUtil.getUserId();
//                final File file = FileUtil.saveImgFile(this, photo, fileName);
//                final String fileKey = UUID.randomUUID().toString().replaceAll("-", "");//将file通过post上传到服务器//TODO:后续自行发挥}}}
}

3、FileUtil 工具类:

public class FileUtil {public static Uri getUri(Context context, String authority, File file) {Uri uri = null;if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {uri = FileProvider.getUriForFile(context, authority, file);} else {uri = Uri.fromFile(file);}return uri;}public static File saveImgFile(Context context, Bitmap bitmap, String fileName) {if (fileName == null) {System.out.println("saved fileName can not be null");return null;} else {fileName = fileName + ".png";String path = context.getFilesDir().getAbsolutePath();String lastFilePath = path + "/" + fileName;File file = new File(lastFilePath);if (file.exists()) {file.delete();}try {FileOutputStream outputStream = context.openFileOutput(fileName, 0);bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);outputStream.flush();outputStream.close();} catch (FileNotFoundException var7) {var7.printStackTrace();} catch (IOException var8) {var8.printStackTrace();}return file;}}
}

4、工具类 CoreConstants:

public class CoreConstants {public static String getNurseDownloadFile(Context context) {return context.getExternalFilesDir("").getAbsolutePath() + "/img";}
}

5、在 AndroidManifest.xml 中配置 FileProvider:

 <application....><providerandroid:name="androidx.core.content.FileProvider"android:authorities="${applicationId}.fileprovider"android:exported="false"android:grantUriPermissions="true" ><meta-dataandroid:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/filepaths" /></provider></application>

6、filepaths.xml 文件:

<paths><external-path path="notePadRecorder/" name="notePadRecorder" /><external-path name="my_images" path="Pictures"/><external-path name="external_files" path="."/><root-path name="root_path" path="." />
</paths>

这部分代码在小米和vivo手机上测过,是正常的。

目前线上也没有反馈在其他机型上该功能有问题,如有问题,后续持续更新此文章。

相关文章:

Android -- 调用系统相册之图片裁剪保存

前言 最近线上反馈&#xff0c;部分vivo手机更换头像时调用系统相册保存图片失败&#xff0c;经本人测试&#xff0c;确实有问题。 经修复后&#xff0c;贴出这块的代码供小伙伴们参考使用。 功能 更换头像选择图片&#xff1a; 调用系统相机拍照&#xff0c;调用系统图片…...

读《道德经》让人感到心胸气闷?董仲舒篡改

为什么读《道德经》会让人感到心胸气闷&#xff1f;难道是董仲舒篡改所致&#xff1f; 作为世界智慧源头的《老子》&#xff0c;享誉古今中外&#xff0c;是世界历史上最伟大的著作之一。 然而&#xff0c;很多人读《道德经》时会感到心胸气闷&#xff0c;这究竟是为什么呢&am…...

D52【python 接口自动化学习】- python基础之模块与标准库

day52 标准库 学习日期&#xff1a;20241029 学习目标&#xff1a;模块与标准库 -- 67 标准库&#xff1a;Python默认提供的便携功能有哪些&#xff1f; 学习笔记 标准库中的常见组件 如何通过官方文档学习标准 from urllib.request import urlopen with urlopen(http://ww…...

基于yolov8的布匹缺陷检测系统,支持图像、视频和摄像实时检测【pytorch框架、python源码】

更多目标检测和图像分类识别项目可看我主页其他文章 功能演示&#xff1a; 基于yolov8的布匹缺陷检测系统&#xff0c;支持图像、视频和摄像实时检测【pytorch框架、python源码】_哔哩哔哩_bilibili &#xff08;一&#xff09;简介 基于yolov8的布匹缺陷检测系统是在 PyTo…...

SQL Server 中,将单行数据转换为多行数据

在 SQL Server 中&#xff0c;将单行数据转换为多行数据通常涉及到将某个字段中的逗号分隔的值拆分成多行。这种操作通常称为“拆分”或“展开”&#xff08;Explode&#xff09;。以下是一些常用的方法来实现这一目标&#xff1a; 1. 使用内置函数 STRING_SPLIT 从 SQL Serv…...

解决数组两数之和问题与逻辑推理找出谋杀案凶手

给定一个整数数组nums和一个整数目标值target(2<nums.length<10^4)&#xff0c;请你在该数组中找出和为目标值target 的那两个整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案&#xff0c;并且你不能使用两次相同的元素。 你可以按任意顺序返…...

uniapp的IOS证书申请(测试和正式环境)及UDID配置流程

1.说明 本教程只提供uniapp在ios端的证书文件申请&#xff08;包含正式环境和开发环境&#xff09;、UDID配置说明&#xff0c;请勿用文档中的账号和其他隐私数据进行测试&#xff0c;请勿侵权&#xff01; 2.申请前准备 证书生成网站&#xff1a;苹果应用上传、解析&#x…...

windows 安装apex_Nvidia Apex安装

参见windows 安装apex_Nvidia Apex安装 重点&#xff1a; 1、在安装前先检查一下&#xff0c;电脑的cuda版本和pytorch内的cuda版本是否一样&#xff0c;不一样的话就把低版本的进行升级&#xff1b; $ git clone https://github.com/NVIDIA/apex$ cd apex2、在保证cuda版本一…...

Laravel5 抓取第三方网站图片,存储到本地

背景 近期发现&#xff0c;网站上的部分图片无法显示&#xff0c; 分析发现&#xff0c;是因为引用的第三方网站图片&#xff08;第三方服务器证书已过期&#xff09; 想着以后显示的方便 直接抓取第三方服务器图片&#xff0c;转存到本地服务器 思路 1. 查询数据表&#xff0…...

DevOps和CI/CD以及在微服务架构中的作用

DevOps 和 CI/CD 是现代软件开发和运维中两个重要的概念,它们之间有紧密的联系,但也有不同的侧重点。以下是对这两个概念的详细介绍和比较。 1. DevOps 定义: DevOps 是一种文化、运动和实践,旨在通过促进开发(Development)和运维(Operations)团队之间的协作,提升软…...

Rust 力扣 - 5. 最长回文子串

文章目录 题目描述题解思路题解代码题解链接 题目描述 题解思路 从中心点先寻找和中心点相等的左右端点&#xff0c;在基于左右端点进行往外扩散&#xff0c;直至左右端点不相等或者越界&#xff0c;然后左右端点这个范围内就是我们找寻的回文串&#xff0c;我们遍历中心点&am…...

DDOS防护介绍

DDoS攻击的基本概念 分布式拒绝服务攻击&#xff08;DDoS&#xff09;是一种网络攻击方式&#xff0c;攻击者通过控制多个被感染的计算机&#xff08;僵尸网络&#xff09;同时向目标服务器发送大量的网络请求&#xff0c;导致目标服务器资源耗尽&#xff0c;无法正常提供服务…...

深入了解 kotlinx-datetime:配置与使用指南

深入了解 kotlinx-datetime&#xff1a;配置与使用指南 在Kotlin多平台开发中&#xff0c;处理日期和时间是常见的需求。kotlinx-datetime库提供了强大且简洁的API来帮助开发者应对这一挑战。本文将详细介绍如何配置kotlinx-datetime库&#xff0c;并通过生动的示例演示其核心…...

Qt编程技巧小知识点(6)根据 *IDN? 对程控仪器连接状态进行确认

文章目录 Qt编程技巧小知识点&#xff08;6&#xff09;根据 *IDN? 对程控仪器连接状态进行确认小结 Qt编程技巧小知识点&#xff08;6&#xff09;根据 *IDN? 对程控仪器连接状态进行确认 确定仪器连接问题&#xff0c;常用的是监测仪器的连接状态&#xff0c;如下代码所示&…...

【Android】Kotlin教程(4)

文章目录 1.field2.计算属性3.主构造函数4.次构造函数5.默认参数6.初始化块7.初始化顺序7.延迟初始化lateinit8.惰性初始化 1.field field 关键字通常与属性的自定义 getter 和 setter 一起使用。当你需要为一个属性提供自定义的行为时&#xff0c;可以使用 field 来访问或设置…...

机票电子行程单如何批量查验?Java机票电子行程单查验接口示例-发票查验接口

机票电子行程单来了&#xff0c;它方便了人们的出行。现如今&#xff0c;随着旅游、差旅市场的回暖与线上业务的蓬勃发展&#xff0c;机票电子行程单的需求量急剧攀升&#xff0c;如何高效且准确地查验这些电子行程单成为许多企业和财务部门关注的焦点。传统的人工查验流程耗时…...

记录element-ui改造select显示为table,并支持多查询条件

最近遇到的一个需求 &#xff0c; 很有趣&#xff0c;是需要一个select组件&#xff0c;要求显示工号&#xff0c;员工姓名&#xff0c;以及区域 三个字段&#xff0c;并且要支持三个字段的查询。显然element原生的组件不适用&#xff0c;这时候我们需要改造一下&#xff0c;把…...

Spearman、Pearson、Euclidean、Cosine、Jaccard,用来衡量不同数据之间的相似性或差异性

1. Spearman相关系数&#xff1a; 用于衡量两个变量之间的排序关系的强度和方向。Spearman相关系数关注的是两个变量的排序一致性&#xff0c;而不关心具体的数值大小。值的范围为-1到1&#xff0c;1表示完全正相关&#xff0c;-1表示完全负相关&#xff0c;0表示无相关性。常…...

Suno 歌曲生成 API 对接说明

随着 AI 的应用变广&#xff0c;各类 AI 程序已逐渐普及。AI 已逐渐深入到人们的工作生活方方面面。而 AI 涉及的行业也越来越多&#xff0c;从最初的写作&#xff0c;到医疗教育&#xff0c;再到现在的音乐。 Suno 是一个专业高质量的 AI 歌曲和音乐创作平台&#xff0c;用户…...

详细且系统的Spring Boot应用开发

为了帮助大家更好地理解如何使用Spring Boot来构建一个基础的Web应用程序&#xff0c;我将通过一个简单的例子来进行说明。这个例子将是一个基本的RESTful API服务&#xff0c;用于管理图书信息。 项目准备 1. 开发环境设置&#xff08;这个我之前有发文&#xff0c;这里就不详…...

Vim 调用外部命令学习笔记

Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解

突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 ​安全措施依赖问题​ GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...

OpenLayers 可视化之热力图

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 热力图&#xff08;Heatmap&#xff09;又叫热点图&#xff0c;是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查

在对接支付宝API的时候&#xff0c;遇到了一些问题&#xff0c;记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO&#xff1a;支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题&#xff1a;MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者&#xff1a;Yanyuan Chen, Dexuan Xu, Yu Hu…...

模型参数、模型存储精度、参数与显存

模型参数量衡量单位 M&#xff1a;百万&#xff08;Million&#xff09; B&#xff1a;十亿&#xff08;Billion&#xff09; 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的&#xff0c;但是一个参数所表示多少字节不一定&#xff0c;需要看这个参数以什么…...

【Linux】C语言执行shell指令

在C语言中执行Shell指令 在C语言中&#xff0c;有几种方法可以执行Shell指令&#xff1a; 1. 使用system()函数 这是最简单的方法&#xff0c;包含在stdlib.h头文件中&#xff1a; #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

CentOS下的分布式内存计算Spark环境部署

一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架&#xff0c;相比 MapReduce 具有以下核心优势&#xff1a; 内存计算&#xff1a;数据可常驻内存&#xff0c;迭代计算性能提升 10-100 倍&#xff08;文档段落&#xff1a;3-79…...

多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验

一、多模态商品数据接口的技术架构 &#xff08;一&#xff09;多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如&#xff0c;当用户上传一张“蓝色连衣裙”的图片时&#xff0c;接口可自动提取图像中的颜色&#xff08;RGB值&…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...