Android 使用 registerForActivityResult() 打开系统相册或相机获取图像
一、简介
当使用了 AndroidX 后,发现 `startActivityForResult()` 标记为过时了,而是推荐我们使用 `registerForActivityResult()` 函数。
`registerForActivityResult()` 函数是 Android 中用于启动 Activity 结果回调的新方式。这个函数的目的是简化在 Activity 和 Fragment 之间进行启动其他 Activity 并接收结果的过程,取代了传统的 `startActivityForResult()` 和 `onActivityResult()` 方法。
使用 `registerForActivityResult()` 函数,您可以更容易地管理 Activity 结果的处理,使代码更清晰和模块化。
AndroidX 介绍:
AndroidX 是 Android 中的一个开发库,旨在简化 Android 应用程序的开发和维护。AndroidX 提供了一组替代 Android Support Library 的库,它们包括了新的功能、改进的性能和更好的兼容性,以便开发人员更轻松地构建现代化、高质量的 Android 应用程序。
主要包括:
- 新功能和改进: AndroidX 引入了许多新的功能和改进,包括更好的 Jetpack 组件、性能优化、Kotlin 支持、Android 架构组件等,以提高开发效率和用户体验。
- 向后兼容性: AndroidX 专注于提供向后兼容性,以确保应用程序在不同 Android 版本上能够稳定运行。这意味着即使您的应用使用了 AndroidX 库,也可以在较旧的 Android 版本上运行。
- Jetpack 组件: AndroidX 包括了 Android Jetpack 组件,这是一组库和工具,旨在简化 Android 应用程序的常见开发任务,例如导航、数据存储、UI 构建、生命周期管理等。Jetpack 组件的目标是提高应用程序的可维护性、稳定性和性能。
二、打开相册获取图像
1. 代码示例
public class MainActivity extends AppCompatActivity {private ActivityResultLauncher<String> mGalleryLauncher;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 需要事先注册mGalleryLauncher = registerForActivityResult(// 获取内容,回调函数的参数将是一个URInew ActivityResultContracts.GetContent(),// 回调函数this::handleGalleryResult);}private void openGallery() {if (mGalleryLauncher != null) {// launch的输入参数是泛型,对应ActivityResultLauncher<String>mGalleryLauncher.launch("image/*");}}private void handleGalleryResult(Uri imageUri) {if (imageUri != null) {try {Bitmap selectedBitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageUri);int rotation = ImageUtil.getRotation(this, imageUri);Bitmap rotatedBitmap = ImageUtil.rotateBitmap(selectedBitmap, rotation);// 后续处理逻辑} catch (Exception e) {e.printStackTrace();}}}
}
2. ImageUtil部分函数
public static Bitmap rotateBitmap(Bitmap bitmap, int rotation) {if (rotation == 0) {return bitmap;}return rotateResizeBitmap(bitmap, rotation, 1f);
}public static Bitmap rotateResizeBitmap(Bitmap source, float angle, float scale) {Matrix matrix = new Matrix();matrix.postRotate(angle);if (scale != 1f) {matrix.setScale(scale, scale);}return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
}public static int getRotation(Context context, Uri photoUri) {if (photoUri == null) {return 0;}ExifInterface ei;try {InputStream inputStream = context.getContentResolver().openInputStream(photoUri);ei = new ExifInterface(inputStream);} catch (IOException e) {return 0;}int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);switch (orientation) {case ExifInterface.ORIENTATION_ROTATE_90:return 90;case ExifInterface.ORIENTATION_ROTATE_180:return 180;case ExifInterface.ORIENTATION_ROTATE_270:return 270;default:return 0;}
}
三、打开相机获取图像
因为使用的是系统相机应用,所以也不需要额外申请相机权限了。
1. 代码示例
public class MainActivity extends AppCompatActivity {private ActivityResultLauncher<Intent> mCameraLauncher;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 需要事先注册mCameraLauncher = registerForActivityResult(// 回调函数的参数将是一个ActivityResultnew ActivityResultContracts.StartActivityForResult(),// 回调函数this::handleCameraResult);}private void openCamera() {if (mCameraLauncher != null) {// launch的输入参数是泛型,对应ActivityResultLauncher<Intent>Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);// 确保有相机应用可用if (takePictureIntent.resolveActivity(getPackageManager()) != null) {mCameraLauncher.launch(takePictureIntent);}}}private void handleCameraResult(ActivityResult result) {if (result.getResultCode() == RESULT_OK) {Intent data = result.getData();if (data != null) {Bundle extras = data.getExtras();if (extras != null) {Uri uri = data.getData();Bitmap imageBitmap = (Bitmap) extras.get("data");// 后续处理逻辑}}}}
}
注意:
由于Bundle本身能够携带的数据大小限制,上面这种方式获取的相机图像分辨率通常很低。如果希望能够获取较大分辨率的图像,则可以先将相机图像保存到本地,再通过文件路径加载。具体方式如下:
2. 修改openCamera()
在打开相机的Intent中添加一个文件输出的Uri,告诉相机需要保存到指定位置。
private String mPhotoPath; // 用于存储文件保存的路径private void openCamera() {if (mCameraLauncher != null) {// launch的输入参数是泛型,对应ActivityResultLauncher<Intent>Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);// 确保有相机应用可用if (takePictureIntent.resolveActivity(getPackageManager()) != null) {// 创建一个用于存储拍照结果的文件File photoFile = ImageUtil.createImageFile(this);mPhotoPath = photoFile.getAbsolutePath();Uri photoUri = FileProvider.getUriForFile(this,"com.afei.demo.provider", // 对应 AndroidManifest.xml 中的声明photoFile);takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);mCameraLauncher.launch(takePictureIntent);}}
}
3. ImageUtil.createImageFile() 代码
创建一个可写的文件即可。
public static File createImageFile(Context context) {String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date(System.currentTimeMillis()));String imageFileName = "JPEG_" + timeStamp + "_";File storageDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);if (!storageDir.exists()) {storageDir.mkdirs();}File imageFile = null;try {imageFile = File.createTempFile(imageFileName, /* 文件名 */".jpg", /* 文件扩展名 */storageDir /* 存储目录 */);imageFile.setWritable(true);} catch (IOException e) {e.printStackTrace();}return imageFile;
}
4. 自定义的FileProvider
上述代码中还使用到了一个 `FileProvider.getUriForFile()` 方法,作为四大组件之一,也是需要在 AndroidManifest.xml 文件中声明和使用的。
a. AndroidManifest.xml 文件中
<application>...<providerandroid:name="androidx.core.content.FileProvider"android:authorities="com.afei.demo.provider"android:exported="false"android:grantUriPermissions="true"><meta-dataandroid:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/file_paths" /></provider>
</application>
authorities 通常可以用 `包名+.provider`。
b. xml/file_paths 文件
在 res 文件夹下面创建一个 xml 子文件夹,并新建 file_paths.xml 文件(文件名可以修改,和AndroidManifest.xml中对应上就行),内容如下:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android"><external-pathname="my_images"path="." />
</paths>
关于FileProvider的使用这里不过多介绍了,不清楚的可以查阅其他资料。
5. 修改 handleCameraResult(ActivityResult result)
这里就不再需要通过 ActivityResult 获取数据了,而是从之前存储的 `mPhotoPath` 中获取。
private void handleCameraResult(ActivityResult result) {if (result.getResultCode() == RESULT_OK) {Bitmap bitmap = BitmapFactory.decodeFile(mPhotoPath);// 后续处理逻辑}
}
相关文章:
Android 使用 registerForActivityResult() 打开系统相册或相机获取图像
一、简介 当使用了 AndroidX 后,发现 startActivityForResult() 标记为过时了,而是推荐我们使用 registerForActivityResult() 函数。 registerForActivityResult() 函数是 Android 中用于启动 Activity 结果回调的新方式。这个函数的目的是简化在 Act…...
如何制作网页 ico
1. 制作 icon 可以通过 https://www.iconfont.cn/collections/detail?spma313x.7781069.1998910419.de12df413&cid13720 或者自己在 PPT 制作,然后截图导出png 文件。 2. 转换为 ico 文件 使用:https://www.bitbug.net/ 上传并且转换成自己要的…...
golang gorm 增删改查以及使用原生SQL(以操作mysql为例)
gorm mysql增删改查 model定义 package _caseimport "gorm.io/gorm"func init() {DB.Migrator().AutoMigrate(Teacher{}, Course{}) } type Roles []stringtype Teacher struct {gorm.ModelName string gorm:"size:256"Email string gorm:&q…...
代码随想录 单调栈part2
503. 下一个更大元素 II 给定一个循环数组 nums ( nums[nums.length - 1] 的下一个元素是 nums[0] ),返回 nums 中每个元素的 下一个更大元素 。 数字 x 的 下一个更大的元素 是按数组遍历顺序,这个数字之后的第一个比它更大的数…...
详解利用高斯混合模型拆解多模态分布 + 精美可视化
文章目录 一、前言二、主要内容三、总结🍉 CSDN 叶庭云:https://yetingyun.blog.csdn.net/ 一、前言 本文旨在介绍如何利用高斯混合模型(Gaussian Mixture Models,简称 GMMs)将一维多模态分布拆分为多个分布。作为统计 / / /机器学习领域常用的概率模型...
排序算法之【归并排序】
📙作者简介: 清水加冰,目前大二在读,正在学习C/C、Python、操作系统、数据库等。 📘相关专栏:C语言初阶、C语言进阶、C语言刷题训练营、数据结构刷题训练营、有感兴趣的可以看一看。 欢迎点赞 👍…...
Qt中QTimer定时器的用法
Qt中提供了两种定时器的方式一种是使用Qt中的事件处理函数,另一种就是Qt中的定时器类QTimer。 使用QTimer类,需要创建一个QTimer类对象,然后调用其start()方法开启定时器,此后QTimer对象就会周期性的发出timeout()信号。 1.QTimer…...
vue-组件定义注册使用
vue组件使用的步骤 定义组件注册组件使用组件 定义组件 Vue.extend(options) 其中options和new Vue(options)出入的options对象几乎一样,但是也有不同。 创建 el不用写—最终所有组件需要经过一个vm的管理,由vm的el决定服务哪个容器。 data必须写成函…...
斑馬打印機打印中文
创建项目 首先說一下,本文章是借鉴了其他大佬的文章,然后我记录一下的文章。 首先创建好一个.net framework的winform项目。 这里面主要用到两个库文件: Fnthex32.dll、LabelPrint.dll。 Fnthex32这个有8位参数和9位参数的,我这…...
(一)Apache log4net™ 手册 - 介绍
0、相关概念 Log4j 几乎每个大型应用程序都包含自己的日志记录或跟踪 API。根据这一规则,E.U. SEMPER 🌹项目决定编写自己的跟踪 API。那是在 1996 年初。经过无数次的增强、几个化身和大量的工作,API 已经发展成为 log4j —— 一个流行的 Ja…...
基于Java的民宿管理系统设计与实现(源码+lw+部署文档+讲解等)(民宿预约、民宿预订、民宿管理、酒店预约通用)
文章目录 前言具体实现截图论文参考详细视频演示代码参考源码获取 前言 💗博主介绍:✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技…...
039:mapboxGL更换地图上的鼠标样式
第039个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+mapbox中更换地图上的鼠标的样式。 直接复制下面的 vue+mapbox源代码,操作2分钟即可运行实现效果 文章目录 示例效果配置方式示例源代码(共74行)相关API参考:专栏目标示例效果 配置方式 1)查看基础设置:htt…...
【云原生】K8S对外服务之Ingress
目录 一、Ingress 简介1.1Ingress 组成1.3Ingress-Nginx 工作原理 二、部署 nginx-ingress-controller2.1部署ingress-controller Pod及相关资源2.2ingress 暴露服务的方式2.3 采用方式二:DaemonSetHostNetworknodeSelector 三、采用方式二:DeploymentNo…...
分布式锁如何实现
分布式是现在的比较主流的技术,常常和微服务一起出现。那么对于多个实例之间,如何证分布式系统中多个进程或线程同步访问共享资源呢?我们其实一想到的就是锁,我们在java里边有 synchronized, 在python里有lock,但是这个…...
Mysql存储-EAV模式
Mysql存储-EAV模式 最近又又又搞一点新东西,要整合不同业务进行存储和查询,一波学习过后总结了一下可扩展性MAX的eav模式存储。 在eav这里的数据结构设计尤为关键,需要充分考虑你需要使用的字段、使用场景,当数据结构设计完成后便…...
全局变量报错:\Output\STM32.axf: Error: L6218E: Undefined symbol
全局变量报错: .\Output\STM32.axf: Error: L6218E: Undefined symbol key_num (referred from main.o). 这里只说全局变量哦,这是因为你在调用的.c文件里 把定义写在了函数里面,写函数外面就没事了 改为: .h的声明文件根本不用写…...
算法错题簿(持续更新)
自用算法错题簿,按算法与数据结构分类 python1、二维矩阵:记忆化搜索dp2、图论:DFS3、回溯:129612964、二叉树:贪心算法5、字符串:记忆化搜索6、01字符串反转:结论题7、二进制数:逆向…...
基于Springboot实现疫情网课管理系统项目【项目源码+论文说明】
基于Springboot实现疫情网课管理系统演示 摘要 随着科学技术的飞速发展,各行各业都在努力与现代先进技术接轨,通过科技手段提高自身的优势;对于疫情网课管理系统当然也不能排除在外,随着网络技术的不断成熟,带动了疫情…...
Linux文件与目录的增删改查
一、增 1、mkdir命令 作用: 创建一个新目录。 格式: mkdir [选项] 要创建的目录 常用参数: -p:创建目录结构中指定的每一个目录,如果目录不存在则创建,如果目录已存在也不会被覆盖。 用法示例&a…...
JVM的内存模型
一、JVM的内存模型 1.1、目标 内存模型是用来描述JVM内部的内存结构和内存管理的模型。它定义了JVM在运行Java程序时所需要的各种内存区域,以及每个内存区域的作用和特点。 1.2、结构划分 1.2.1、栈 每个线程在执行Java方法时会创建一个栈帧(Stack …...
智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql
智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...
关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
【JVM】- 内存结构
引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...
《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...
push [特殊字符] present
push 🆚 present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中,push 和 present 是两种不同的视图控制器切换方式,它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...
[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.
ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #:…...
Chrome 浏览器前端与客户端双向通信实战
Chrome 前端(即页面 JS / Web UI)与客户端(C 后端)的交互机制,是 Chromium 架构中非常核心的一环。下面我将按常见场景,从通道、流程、技术栈几个角度做一套完整的分析,特别适合你这种在分析和改…...
软件工程 期末复习
瀑布模型:计划 螺旋模型:风险低 原型模型: 用户反馈 喷泉模型:代码复用 高内聚 低耦合:模块内部功能紧密 模块之间依赖程度小 高内聚:指的是一个模块内部的功能应该紧密相关。换句话说,一个模块应当只实现单一的功能…...
