Android Kotlin 打开相册选择图片(多选)
1. 核心代码
打开系统相册功能,本代码使用两种方式打开本地相册,startActivityForResult 已经废弃,可以使用新的方式。
package com.example.facedetectordemoimport android.content.pm.PackageManager
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.TextView
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.example.facedetectordemo.databinding.ActivityMainBinding
import com.example.facedetectordemo.entity.FaceInfo
import android.Manifest;
import android.annotation.SuppressLint
import android.annotation.TargetApi
import android.app.Activity
import android.content.ContentUris
import android.content.Intent
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Build
import android.provider.DocumentsContract
import android.provider.MediaStore
import com.google.android.material.snackbar.Snackbarclass MainActivity : AppCompatActivity() {private lateinit var binding: ActivityMainBindingprivate val CHOOSE_PHOTO = 1private val requestPermissionLauncher =registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean ->if (isGranted) {Log.i("Permission: ", "Granted")} else {Log.i("Permission: ", "Denied")}}private val launcherActivity = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {val data = it.dataif (it.resultCode == Activity.RESULT_OK) {// 判断手机系统版本号if (Build.VERSION.SDK_INT >= 19) {// 4.4及以上系统使用这个方法处理图片if (data != null) {if(data.clipData != null) {handleImageOnKitKat(data.clipData!!.getItemAt(0).uri)} else if(data.data != null) {handleImageOnKitKat(data.data!!)}}}}}override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding = ActivityMainBinding.inflate(layoutInflater)setContentView(binding.root)// Example of a call to a native methodbinding.openGallery.setOnClickListener{val intent = Intent("android.intent.action.GET_CONTENT")intent.type = "image/*" // */intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)//startActivityForResult(intent, CHOOSE_PHOTO) // 打开相册, 废弃APIlauncherActivity.launch(intent)}val infos = getFaceInfoList()Log.d("zhouyong", "onCreate: size " + infos.size)requestPermission();}override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {super.onActivityResult(requestCode, resultCode, data)when (requestCode) {CHOOSE_PHOTO -> if (resultCode == Activity.RESULT_OK) {// 判断手机系统版本号if (Build.VERSION.SDK_INT >= 19) {// 4.4及以上系统使用这个方法处理图片if (data != null) {if(data.clipData != null) {handleImageOnKitKat(data.clipData!!.getItemAt(0).uri)} else if(data.data != null) {handleImageOnKitKat(data.data!!)}}} else {}}else -> {}}}@TargetApi(19)private fun handleImageOnKitKat(uri: Uri) {var imagePath: String? = null//val uri = data.dataLog.d("TAG", "handleImageOnKitKat: uri is $uri")if (DocumentsContract.isDocumentUri(this, uri)) {// 如果是document类型的Uri,则通过document id处理val docId = DocumentsContract.getDocumentId(uri)if ("com.android.providers.media.documents" == uri!!.authority) {val id = docId.split(":".toRegex()).toTypedArray()[1] // 解析出数字格式的idval selection = MediaStore.Images.Media._ID + "=" + idimagePath = getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection)} else if ("com.android.providers.downloads.documents" == uri.authority) {val contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), java.lang.Long.valueOf(docId))imagePath = getImagePath(contentUri, null)}} else if ("content".equals(uri!!.scheme, ignoreCase = true)) {// 如果是content类型的Uri,则使用普通方式处理imagePath = getImagePath(uri, null)} else if ("file".equals(uri.scheme, ignoreCase = true)) {// 如果是file类型的Uri,直接获取图片路径即可imagePath = uri.path}displayImage(imagePath) // 根据图片路径显示图片}@SuppressLint("Range")private fun getImagePath(uri: Uri?, selection: String?): String? {var path: String? = null// 通过Uri和selection来获取真实的图片路径val cursor = contentResolver.query(uri!!, null, selection, null, null)if (cursor != null) {if (cursor.moveToFirst()) {path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA))}cursor.close()}return path}private fun displayImage(imagePath: String?) {if (imagePath != null) {val bitmap = BitmapFactory.decodeFile(imagePath)binding.imageView.setImageBitmap(bitmap)} else {//Toast.makeText(this, "failed to get image", Toast.LENGTH_SHORT).show()}}fun requestPermission() {when {ContextCompat.checkSelfPermission(this,Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED -> {}ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.CAMERA) -> {requestPermissionLauncher.launch(Manifest.permission.CAMERA)requestPermissionLauncher.launch(Manifest.permission.READ_EXTERNAL_STORAGE)requestPermissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)}else -> {requestPermissionLauncher.launch(Manifest.permission.CAMERA)requestPermissionLauncher.launch(Manifest.permission.READ_EXTERNAL_STORAGE)requestPermissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)}}}fun View.showSnackbar(view: View,msg: String,length: Int,actionMessage: CharSequence?,action: (View) -> Unit) {val snackbar = Snackbar.make(view, msg, length)if (actionMessage != null) {snackbar.setAction(actionMessage) {action(this)}.show()} else {snackbar.show()}}/*** A native method that is implemented by the 'facedetectordemo' native library,* which is packaged with this application.*/external fun stringFromJNI(): Stringexternal fun getFaceInfoList(): Array<FaceInfo>companion object {// Used to load the 'facedetectordemo' library on application startup.init {System.loadLibrary("facedetectordemo")}}
}
2. main_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><Buttonandroid:id="@+id/openGallery"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginBottom="212dp"android:text="打开相册"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintHorizontal_bias="0.498"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/imageView"app:layout_constraintVertical_bias="1.0" /><ImageViewandroid:id="@+id/imageView"android:layout_width="200dp"android:layout_height="200dp"android:layout_marginTop="96dp"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"tools:srcCompat="@tools:sample/avatars" /></androidx.constraintlayout.widget.ConstraintLayout>
相关文章:
Android Kotlin 打开相册选择图片(多选)
1. 核心代码 打开系统相册功能,本代码使用两种方式打开本地相册,startActivityForResult 已经废弃,可以使用新的方式。 package com.example.facedetectordemoimport android.content.pm.PackageManager import androidx.appcompat.app.App…...
java学习路径
ProcessOn Mindmap...
[线程与网络] 网络编程与通信原理(四):深入理解传输层UDP与TCP协议
🌸个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 🏵️热门专栏:🍕 Collection与数据结构 (92平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm1001.2014.3001.5482 🧀Java …...
IEEE编程语言排行榜:深度解析编程语言的四大维度、五大趋势、六大热门与七大挑战
IEEE编程语言排行榜:深度解析编程语言的四大维度、五大趋势、六大热门与七大挑战 在信息技术领域,编程语言排行榜一直是衡量各种编程语言流行度和影响力的重要指标。IEEE(电气电子工程师协会)作为全球最具影响力的科技专业组织之…...
【C++面试50题】
以下是针对C程序员面试可能遇到的一些问题,涵盖了从基础语法、面向对象、STL、内存管理、模板、异常处理、并发编程等多个方面。 ### 基础概念与语法 1. C与C的主要区别是什么? 2. 什么是构造函数和析构函数?它们何时被调用? 3. 什…...
外汇天眼:ESMA发布针对在投资服务中使用人工智能的公司的指导意见
欧洲证券和市场管理局(ESMA),欧盟的金融市场监管机构和监督机构,发布了一份声明,为在向零售客户提供投资服务时使用人工智能技术(AI)的公司提供初步指导。 尽管人工智能的普及仍处于初期阶段&am…...
【前缀和 记忆化搜索】LeetCode1444. 切披萨的方案数
本文涉及的基础知识点 C算法:前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 动态规划 记忆化搜索 LeetCode1444. 切披萨的方案数 给你一个 rows x cols 大小的矩形披萨和一个整数 k ,矩形包含两种字符: ‘A’ ÿ…...
异常处理1--5.31
try--catch--finally格式: try{ }catch(错误类型){ }finally{ } 执行情况: package javatest5;public class test {public static void main(String[] args) {int num115;int num20;try{System.out.println("商等于:"num1/num…...
AI免费插件 批量条码大师,支持100多种条码类型
没想到在网上看到一款和之前 悟空条码 类似的条码插件,叫批量条码大师,他做的比 悟空条码 功能更强,界面更美观,特分享出来给大家。 本插件采用了BWIPJS条码库,支持110种条码、二维码的生成; 支持批量生成,…...
使用 Django 连接 MySQL 数据库
文章目录 步骤一:安装必要的库和驱动步骤二:配置数据库连接步骤三:执行数据库迁移步骤四:开始使用 MySQL 数据库创建一个模型迁移模型到数据库使用模型进行数据操作创建新记录:查询记录:更新记录࿱…...
【谷歌开发者月刊】五月内容汇总,Google I/O 点燃您的创新灵感
五月因 Google I/O 大会的成功举办而备受瞩目,我们在为开发者们带来技术更新的同时,更提供了丰富的学习资源。一起在本期月刊中回顾精彩内容,带着学习热情继续探索技术的更新与发展吧! 本月看点 精彩看点多多,请上下滑…...
wpf 实现长时间未操作自动退出登录
思路 在WPF应用程序中实现长时间未操作自动退出,主要思路是先收集用户操作行为,用一个全局变量记录用户最后操作时间,再用一个异步线程去监控用户的最后操作时间和当前时间进行比较如果超过了设定时间认为长时间未操作自动退出登录并显示相关…...
pytorch学习笔记3
标量数据 标量数据通常指的是单个数值,比如一个损失值、准确率、学习率等。这些单个的数值数据可以被记录下来,用于分析模型的训练过程、性能等。在代码中,writer.add_scalar() 的作用就是将这些标量数据添加到日志中,以便后续在可…...
开源监控工具monit安装部署
Monit 简介 Monit是一个轻量级(500KB)跨平台的用来监控Unix/linux系统的开源工具。部署简单,并且不依赖任何第三方程序、插件或者库。 Monit可以监控服务器进程、文件、文件系统、网络状态(HTTP/SMTP等协议)、远程主机、服务器资源变化等等。…...
Python 时间戳转时间
一、 10 位 时间戳 ,秒级 转换为时间 方式一: import timetimeStamp 1717149862 timeArray time.localtime(timeStamp) timeStr time.strftime("%Y-%m-%d %H:%M:%S", timeArray) print(timeStr) 输出: 2024-05-31 18:04:22方式二…...
【网络层】IP地址基础 与 子网掩码
文章目录 IP地址基础IP地址概念IP地址分类公网地址和私网地址 子网掩码子网掩码作用默认子网掩码网络地址、主机地址、广播地址 IP地址基础 IP地址概念 IP地址:IP Address 在网络中,通信节点都需要有一个IP地址 IP地址以点分十进制表示,有…...
Cholesky分解(A=L * L^T)
Cholesky分解是一种用于解线性方程组和计算矩阵平方根的算法,特别适用于对称正定矩阵。这种方法相比于其他解法(如高斯消元法)在数值稳定性上通常有更好的表现,并且能够有效地利用矩阵的对称性和正定性。下面简要介绍如何使用Chol…...
2024大模型新应用井喷即将到来,算力问题如何解决?
#大模型新应用 #NLP #智合同 随着人工智能技术的加速演进,AI大模型已成为全球科技竞争的新高地、未来产业的新赛道、经济发展的新引擎。大模型的快速发展,特别是在自然语言处理(NLP)和计算机视觉(CV)等…...
SpringBoot 七牛云 OSS 私有模式 获取访问链接
目录 一、问题引出 二、在SpringBoot中获取私有访问路径的操作 一、问题引出 由于七牛云OSS的公有模式存在被盗刷的风险,可能导致服务器额外的费用,于是我选择私有模式进行操作。私有模式的访问路径是一个问题,因为需要对应着token和e这两…...
python-模块-网络编程-多任务
一、模块 1-1 Python 自带模块 Json模块 处理json数据 {"key":"value"} json不是字典 本质是一个有引号的字符串数据 json注意点 {} 中的数据是字符串引号必须是双引号 使用json模块可以实现将json转为字典,使用字典的方法操作数据 。 或者将…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...
从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...
全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...
基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...
OD 算法题 B卷【正整数到Excel编号之间的转换】
文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的:a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...
适应性Java用于现代 API:REST、GraphQL 和事件驱动
在快速发展的软件开发领域,REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名,不断适应这些现代范式的需求。随着不断发展的生态系统,Java 在现代 API 方…...
关于easyexcel动态下拉选问题处理
前些日子突然碰到一个问题,说是客户的导入文件模版想支持部分导入内容的下拉选,于是我就找了easyexcel官网寻找解决方案,并没有找到合适的方案,没办法只能自己动手并分享出来,针对Java生成Excel下拉菜单时因选项过多导…...
