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

Android 使用 registerForActivityResult() 打开系统相册或相机获取图像

一、简介

当使用了 AndroidX 后,发现 `startActivityForResult()` 标记为过时了,而是推荐我们使用 `registerForActivityResult()` 函数。

`registerForActivityResult()` 函数是 Android 中用于启动 Activity 结果回调的新方式。这个函数的目的是简化在 Activity 和 Fragment 之间进行启动其他 Activity 并接收结果的过程,取代了传统的 `startActivityForResult()``onActivityResult()` 方法。

使用 `registerForActivityResult()` 函数,您可以更容易地管理 Activity 结果的处理,使代码更清晰和模块化。

AndroidX 介绍:

AndroidX 是 Android 中的一个开发库,旨在简化 Android 应用程序的开发和维护。AndroidX 提供了一组替代 Android Support Library 的库,它们包括了新的功能、改进的性能和更好的兼容性,以便开发人员更轻松地构建现代化、高质量的 Android 应用程序。

主要包括:

  1. 新功能和改进: AndroidX 引入了许多新的功能和改进,包括更好的 Jetpack 组件、性能优化、Kotlin 支持、Android 架构组件等,以提高开发效率和用户体验。
  2. 向后兼容性: AndroidX 专注于提供向后兼容性,以确保应用程序在不同 Android 版本上能够稳定运行。这意味着即使您的应用使用了 AndroidX 库,也可以在较旧的 Android 版本上运行。
  3. 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 后&#xff0c;发现 startActivityForResult() 标记为过时了&#xff0c;而是推荐我们使用 registerForActivityResult() 函数。 registerForActivityResult() 函数是 Android 中用于启动 Activity 结果回调的新方式。这个函数的目的是简化在 Act…...

如何制作网页 ico

1. 制作 icon 可以通过 https://www.iconfont.cn/collections/detail?spma313x.7781069.1998910419.de12df413&cid13720 或者自己在 PPT 制作&#xff0c;然后截图导出png 文件。 2. 转换为 ico 文件 使用&#xff1a;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 &#xff08; nums[nums.length - 1] 的下一个元素是 nums[0] &#xff09;&#xff0c;返回 nums 中每个元素的 下一个更大元素 。 数字 x 的 下一个更大的元素 是按数组遍历顺序&#xff0c;这个数字之后的第一个比它更大的数…...

详解利用高斯混合模型拆解多模态分布 + 精美可视化

文章目录 一、前言二、主要内容三、总结🍉 CSDN 叶庭云:https://yetingyun.blog.csdn.net/ 一、前言 本文旨在介绍如何利用高斯混合模型(Gaussian Mixture Models,简称 GMMs)将一维多模态分布拆分为多个分布。作为统计 / / /机器学习领域常用的概率模型...

排序算法之【归并排序】

&#x1f4d9;作者简介&#xff1a; 清水加冰&#xff0c;目前大二在读&#xff0c;正在学习C/C、Python、操作系统、数据库等。 &#x1f4d8;相关专栏&#xff1a;C语言初阶、C语言进阶、C语言刷题训练营、数据结构刷题训练营、有感兴趣的可以看一看。 欢迎点赞 &#x1f44d…...

Qt中QTimer定时器的用法

Qt中提供了两种定时器的方式一种是使用Qt中的事件处理函数&#xff0c;另一种就是Qt中的定时器类QTimer。 使用QTimer类&#xff0c;需要创建一个QTimer类对象&#xff0c;然后调用其start()方法开启定时器&#xff0c;此后QTimer对象就会周期性的发出timeout()信号。 1.QTimer…...

vue-组件定义注册使用

vue组件使用的步骤 定义组件注册组件使用组件 定义组件 Vue.extend(options) 其中options和new Vue(options)出入的options对象几乎一样&#xff0c;但是也有不同。 创建 el不用写—最终所有组件需要经过一个vm的管理&#xff0c;由vm的el决定服务哪个容器。 data必须写成函…...

斑馬打印機打印中文

创建项目 首先說一下&#xff0c;本文章是借鉴了其他大佬的文章&#xff0c;然后我记录一下的文章。 首先创建好一个.net framework的winform项目。 这里面主要用到两个库文件&#xff1a; Fnthex32.dll、LabelPrint.dll。 Fnthex32这个有8位参数和9位参数的&#xff0c;我这…...

(一)Apache log4net™ 手册 - 介绍

0、相关概念 Log4j 几乎每个大型应用程序都包含自己的日志记录或跟踪 API。根据这一规则&#xff0c;E.U. SEMPER &#x1f339;项目决定编写自己的跟踪 API。那是在 1996 年初。经过无数次的增强、几个化身和大量的工作&#xff0c;API 已经发展成为 log4j —— 一个流行的 Ja…...

基于Java的民宿管理系统设计与实现(源码+lw+部署文档+讲解等)(民宿预约、民宿预订、民宿管理、酒店预约通用)

文章目录 前言具体实现截图论文参考详细视频演示代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/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 采用方式二&#xff1a;DaemonSetHostNetworknodeSelector 三、采用方式二&#xff1a;DeploymentNo…...

分布式锁如何实现

分布式是现在的比较主流的技术&#xff0c;常常和微服务一起出现。那么对于多个实例之间&#xff0c;如何证分布式系统中多个进程或线程同步访问共享资源呢&#xff1f;我们其实一想到的就是锁&#xff0c;我们在java里边有 synchronized, 在python里有lock&#xff0c;但是这个…...

Mysql存储-EAV模式

Mysql存储-EAV模式 最近又又又搞一点新东西&#xff0c;要整合不同业务进行存储和查询&#xff0c;一波学习过后总结了一下可扩展性MAX的eav模式存储。 在eav这里的数据结构设计尤为关键&#xff0c;需要充分考虑你需要使用的字段、使用场景&#xff0c;当数据结构设计完成后便…...

全局变量报错:\Output\STM32.axf: Error: L6218E: Undefined symbol

全局变量报错&#xff1a; .\Output\STM32.axf: Error: L6218E: Undefined symbol key_num (referred from main.o). 这里只说全局变量哦&#xff0c;这是因为你在调用的.c文件里 把定义写在了函数里面&#xff0c;写函数外面就没事了 改为&#xff1a; .h的声明文件根本不用写…...

算法错题簿(持续更新)

自用算法错题簿&#xff0c;按算法与数据结构分类 python1、二维矩阵&#xff1a;记忆化搜索dp2、图论&#xff1a;DFS3、回溯&#xff1a;129612964、二叉树&#xff1a;贪心算法5、字符串&#xff1a;记忆化搜索6、01字符串反转&#xff1a;结论题7、二进制数&#xff1a;逆向…...

基于Springboot实现疫情网课管理系统项目【项目源码+论文说明】

基于Springboot实现疫情网课管理系统演示 摘要 随着科学技术的飞速发展&#xff0c;各行各业都在努力与现代先进技术接轨&#xff0c;通过科技手段提高自身的优势&#xff1b;对于疫情网课管理系统当然也不能排除在外&#xff0c;随着网络技术的不断成熟&#xff0c;带动了疫情…...

Linux文件与目录的增删改查

一、增 1、mkdir命令 作用&#xff1a; 创建一个新目录。 格式&#xff1a; mkdir [选项] 要创建的目录 常用参数&#xff1a; -p&#xff1a;创建目录结构中指定的每一个目录&#xff0c;如果目录不存在则创建&#xff0c;如果目录已存在也不会被覆盖。 用法示例&a…...

JVM的内存模型

一、JVM的内存模型 1.1、目标 内存模型是用来描述JVM内部的内存结构和内存管理的模型。它定义了JVM在运行Java程序时所需要的各种内存区域&#xff0c;以及每个内存区域的作用和特点。 1.2、结构划分 1.2.1、栈 每个线程在执行Java方法时会创建一个栈帧&#xff08;Stack …...

高效AI专著生成:20万字专著一键搞定,AI写专著工具实测推荐!

学术专著写作挑战与AI工具助力 对于初次尝试编写学术专著的研究者来说&#xff0c;写作过程就像是在“摸索着走过一条未知的小路”&#xff0c;处处都有挑战等待着他们。在选题上常常感到迷惘&#xff0c;难以在“有意义”与“可操作性”之间找到合适的平衡&#xff1a;有的研…...

NotebookLM文档召回率骤降73%?(内部实验报告首次公开:BM25+SBERT混合排序实战框架)

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;NotebookLM相似文档推荐 NotebookLM 是 Google 推出的基于用户上传文档构建个性化 AI 助手的实验性工具&#xff0c;其核心能力之一是“相似文档推荐”——即在用户提问时&#xff0c;自动从已导入的文…...

终极免费方案:如何用Wand-Enhancer解锁WeMod高级功能完整指南

终极免费方案&#xff1a;如何用Wand-Enhancer解锁WeMod高级功能完整指南 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/gh_mirrors/we/Wand-Enhancer 你是否厌倦了WeMod免费版的种种…...

如何彻底解决C盘空间不足:Windows Cleaner终极清理指南

如何彻底解决C盘空间不足&#xff1a;Windows Cleaner终极清理指南 【免费下载链接】WindowsCleaner Windows Cleaner——专治C盘爆红及各种不服&#xff01; 项目地址: https://gitcode.com/gh_mirrors/wi/WindowsCleaner 你是否经常遇到C盘空间不足的困扰&#xff1f;…...

ESP32S3驱动1.3寸圆形AMOLED屏(RM67162芯片)的完整避坑指南:从SPI配置到LVGL局部刷新修复

ESP32S3驱动1.3寸圆形AMOLED屏&#xff08;RM67162芯片&#xff09;全流程实战&#xff1a;从SPI配置到LVGL优化 这块1.3寸圆形AMOLED屏幕以其出色的显示效果和独特的外形设计&#xff0c;在智能穿戴设备和小型嵌入式项目中越来越受欢迎。然而&#xff0c;当它与ESP32S3开发板结…...

两阶段目标检测器核心原理与流程详解

两阶段目标检测器的核心思想是&#xff1a;第一阶段先找候选区域&#xff0c;第二阶段再对候选区域做分类和精修。典型代表是&#xff1a; R-CNN Fast R-CNN Faster R-CNN Mask R-CNN现在最典型的是 Faster R-CNN / Mask R-CNN&#xff0c;所以我以它为主来讲。1. 两阶段目标检…...

SC4541SKTRT 2MHz 2.9V~22V升/降压单线LED驱动器Semtech电子元器件IC芯片

SC4541SKTRT是Semtech&#xff08;升特&#xff09;推出的高频LED驱动器芯片&#xff0c;该器件集升压与降压拓扑于一体&#xff0c;支持2.9V至22V超宽输入电压并具备25V输出电压能力&#xff0c;利用内置肖特基二极管和功率开关&#xff0c;将外部电路减至最少&#xff0c;实现…...

FreeRTOS互斥信号量实战:用STM32CubeIDE解决多任务访问共享串口的优先级翻转问题

FreeRTOS互斥信号量实战&#xff1a;用STM32CubeIDE解决多任务访问共享串口的优先级翻转问题 在嵌入式系统开发中&#xff0c;多任务并发访问共享资源是一个常见且棘手的问题。想象一下这样的场景&#xff1a;你的STM32设备上有两个任务需要向同一个串口发送数据——一个高优先…...

企业无线网络进阶:FreeRadius服务器配置与TLS证书实战

1. 为什么企业无线网络需要FreeRadius与TLS证书 想象一下你公司的Wi-Fi像是一个没有门禁的公共广场&#xff0c;任何人都能随意进出。这种情况对于企业网络来说简直是灾难——数据泄露、带宽被占、内网渗透风险接踵而至。而FreeRadiusTLS证书的方案&#xff0c;就相当于给这个广…...

Linux依赖冲突回溯生产排障流程

Linux依赖冲突回溯生产排障流程这是一篇面向中级 Linux 使用者的技术文章&#xff0c;主题聚焦在依赖冲突回溯&#xff0c;重点讨论库版本关系、安装失败和升级影响。在真实生产环境中&#xff0c;依赖冲突回溯相关问题往往不会以单一错误形式出现&#xff0c;而是混杂在日志、…...