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

Android类似微信聊天页面教程(Kotlin)五——选择发送图片

 

前提条件

安装并配置好Android Studio

Android Studio Electric Eel | 2022.1.1 Patch 2
Build #AI-221.6008.13.2211.9619390, built on February 17, 2023
Runtime version: 11.0.15+0-b2043.56-9505619 amd64
VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o.
Windows 11 10.0
GC: G1 Young Generation, G1 Old Generation
Memory: 1280M
Cores: 6
Registry:
    external.system.auto.import.disabled=true
    ide.text.editor.with.preview.show.floating.toolbar=false
    ide.balloon.shadow.size=0
 
Non-Bundled Plugins:
    com.intuit.intellij.makefile (1.0.15)
    com.github.setial (4.0.2)
    com.alayouni.ansiHighlight (1.2.4)
    GsonOrXmlFormat (2.0)
    GLSL (1.19)
    com.mistamek.drawablepreview.drawable-preview (1.1.5)
    com.layernet.plugin.adbwifi (1.0.5)
    com.likfe.ideaplugin.eventbus3 (2020.0.2)

gradle-wrapper.properties

#Tue Apr 25 13:34:44 CST 2023
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME

build.gradle(:Project)

// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {id 'com.android.application' version '7.3.1' apply falseid 'com.android.library' version '7.3.1' apply falseid 'org.jetbrains.kotlin.android' version '1.7.20' apply false
}


setting.gradle

pluginManagement {repositories {maven { url 'https://maven.aliyun.com/repository/public' }google()mavenCentral()gradlePluginPortal()maven { url 'https://jitpack.io' }}
}
dependencyResolutionManagement {repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)repositories {maven { url 'https://maven.aliyun.com/repository/public' }google()mavenCentral()gradlePluginPortal()maven { url 'https://jitpack.io' }}
}
rootProject.name = "FeChat"
include ':app'


build.gralde(:app)

plugins {id 'com.android.application'id 'org.jetbrains.kotlin.android'id 'kotlin-android'id 'kotlin-kapt'
}android {namespace 'com.example.fechat'compileSdk 33defaultConfig {applicationId "com.example.fechat"minSdk 26targetSdk 33versionCode 1versionName "1.0"}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}}compileOptions {sourceCompatibility JavaVersion.VERSION_11targetCompatibility JavaVersion.VERSION_11}kotlinOptions {jvmTarget = '1.8'}
}dependencies {implementation 'androidx.core:core-ktx:1.7.0'implementation 'androidx.appcompat:appcompat:1.6.1'implementation 'com.google.android.material:material:1.8.0'implementation 'androidx.constraintlayout:constraintlayout:2.1.4'implementation 'androidx.cardview:cardview:1.0.0'implementation("androidx.activity:activity-ktx:1.7.1")// 沉浸式状态栏 https://github.com/gyf-dev/ImmersionBarimplementation 'com.gyf.immersionbar:immersionbar:3.0.0'implementation 'com.gyf.immersionbar:immersionbar-components:3.0.0' // fragment快速实现(可选)implementation 'com.gyf.immersionbar:immersionbar-ktx:3.0.0' // kotlin扩展(可选)implementation 'com.google.code.gson:gson:2.8.9'implementation "androidx.room:room-runtime:2.4.2"implementation "androidx.room:room-ktx:2.4.2"kapt "androidx.room:room-compiler:2.4.2"implementation 'org.apache.commons:commons-csv:1.5'implementation 'com.permissionx.guolindev:permissionx:1.4.0'implementation 'com.blankj:utilcodex:1.30.0' // 无implementation 'com.github.bumptech.glide:glide:4.12.0'kapt 'com.github.bumptech.glide:compiler:4.12.0'implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.3'implementation 'com.github.li-xiaojun:XPopup:latest.release'
}


对Kotlin语言有基本了解

内容在前一篇博客中写了基础配置,如果本篇内容看不懂,可以先去上一篇。

使用 Jetpack activity 协定

为了简化照片选择器的集成,请添加 1.7.0 版或更高版本的 androidx.activity 库。

您可以使用以下 activity 结果协定来启动照片选择器:

  • PickVisualMedia,用于选择单张图片或单个视频。
  • PickMultipleVisualMedia,用于选择多张图片或多个视频。

如果照片选择器在设备上不可用,该库会自动调用 ACTION_OPEN_DOCUMENT intent 操作。搭载 Android 4.4(API 级别 19)或更高版本的设备支持此 intent。您可以通过调用 isPhotoPickerAvailable() 来验证照片选择器在给定设备上是否可用。

图片选择

照片选择器提供了一个可浏览、可搜索的界面,其中按日期(从最近到最早)顺序向用户呈现其媒体库中的文件。您可以指定用户只能看到照片或只能看到视频,并且默认情况下,允许的媒体选择量上限设置为 1

单图选择器

ActivityResultContracts.PickVisualMedia()

多图选择器

ActivityResultContracts.PickMultipleVisualMedia("自定义选择上限")

平台会限制您可以让用户在照片选择器中选择的文件数量上限。如需访问此限制,请调用 getPickImagesMaxLimit()。 在不支持照片选择器的设备上,系统会忽略此上限。

注意:如果照片选择器不可用,且支持库调用 ACTION_OPEN_DOCUMENT intent 操作,则系统会忽略指定的可选媒体文件数量上限。

适用的设备

照片选择器适用于符合以下条件的设备:

  • 搭载 Android 11(API 级别 30)或更高版本
  • 通过 Google 系统更新接收对模块化系统组件的更改

搭载 Android 4.4(API 级别 19)到 Android 10(API 级别 29)的旧款设备,以及搭载 Android 11 或 12 且支持 Google Play 服务的 Android Go 设备,都可以安装向后移植的照片选择器版本。如需通过 Google Play 服务自动安装向后移植的照片选择器模块,请将以下条目添加到应用清单文件的 <application> 标记中:

<!-- Trigger Google Play services to install the backported photo picker module. -->
<service android:name="com.google.android.gms.metadata.ModuleDependencies"android:enabled="false"android:exported="false"><intent-filter><action android:name="com.google.android.gms.metadata.MODULE_DEPENDENCIES" /></intent-filter><meta-data android:name="photopicker_activity:0:required" android:value="" />
</service>

保留媒体文件访问权限

默认情况下,系统会授予应用对媒体文件的访问权限,直到设备重启或应用停止运行。如果您的应用执行长时间运行的工作(例如在后台上传大型文件),您可能需要将此访问权限保留更长时间。为此,请调用 takePersistableUriPermission() 方法:

val flag = Intent.FLAG_GRANT_READ_URI_PERMISSION
context.contentResolver.takePersistableUriPermission(uri, flag)

实现方案

根据官方文档介绍,于是有了以下的初始化方式(此处在context的create生命周期中调用):

private var media: ActivityResultLauncher<PickVisualMediaRequest>? = null
fun initPicker(activity: AppCompatActivity,maxFiles: Int = 1,listener: PickFileResultListener
) {val contract = if (maxFiles == 1)ActivityResultContracts.PickVisualMedia()elseActivityResultContracts.PickMultipleVisualMedia(maxFiles)media =activity.registerForActivityResult(contract) { uri ->if (uri != null) {val uris = uri.toString().substring(1, uri.toString().length - 1).split(",")listener.onPick(uris)Log.e("PhotoPicker", "Selected URI: $uris")} else {Log.e("PhotoPicker", "No media selected")}}
}

选择回调监听器

interface PickFileResultListener {fun onPick(uris: List<String>)
}

调用如下

fun pickMedia(fileType: String) {media?.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.SingleMimeType(fileType)))
}

其中选择类型定义为:

const val PICK_IMAGE_VIDEO = "*/*"
const val PICK_IMAGE = "image/*"
const val PICK_VIDEO = "video/*"
const val PICK_GIF = "image/gif"

转化路径

这样得到的Uri如果想要使用,需要先转化为绝对路径

fun Uri2Path(context: Context, uri: Uri?): String? {if (uri == null) {return null}if (ContentResolver.SCHEME_FILE == uri.scheme) {return uri.path} else if (ContentResolver.SCHEME_CONTENT == uri.scheme) {val authority: String = uri.authority!!if (authority.startsWith("com.android.externalstorage")) {return "${Environment.getExternalStorageDirectory()}/${uri.path?.split(":")?.get(1)}"} else {try {var idStr = ""if (authority == "media") {idStr = uri.toString().substring(uri.toString().lastIndexOf('/') + 1)} else if (authority.startsWith("com.android.providers")) {idStr = DocumentsContract.getDocumentId(uri).split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[1]}val contentResolver = context.contentResolverval cursor: Cursor? = contentResolver.query(MediaStore.Files.getContentUri("external"),arrayOf(MediaStore.Files.FileColumns.DATA),"_id=?",arrayOf(idStr),null)if (cursor != null) {cursor.moveToFirst()val idx: Int = cursor.getColumnIndex(MediaStore.Files.FileColumns.DATA)val path = cursor.getString(idx)cursor.close()return path}} catch (e: Exception) {e.printStackTrace()}}}return null
}

大图预览

预览框架采用XPopup

需要添加依赖

implementation 'com.github.li-xiaojun:XPopup:latest.release'
private fun showImageView(imageView: ImageView, currentPosition: Int) {XPopup.Builder(context).isDestroyOnDismiss(true).asImageViewer(imageView, currentPosition, uris,{ popupView, position ->/*Toast.makeText(context, "切换到第" + position + "个图片", Toast.LENGTH_SHORT).show()*/},SmartGlideImageLoader(R.mipmap.ic_launcher)).show()
}

相关文章:

Android类似微信聊天页面教程(Kotlin)五——选择发送图片

前提条件 安装并配置好Android Studio Android Studio Electric Eel | 2022.1.1 Patch 2 Build #AI-221.6008.13.2211.9619390, built on February 17, 2023 Runtime version: 11.0.150-b2043.56-9505619 amd64 VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o. Windows 11 …...

MongoDB:Win/Linux环境安装及一键部署脚本

1. Win安装 1.1 下载 MongoDB 安装程序 访问 MongoDB 官网&#xff0c;进入下载页面&#xff1a;Download MongoDB Community Server | MongoDB 选择 Windows 平台并下载最新版的 MongoDB 安装程序。 1.2 安装 MongoDB 双击安装程序&#xff0c;按照提示完成 MongoDB 的安装…...

KingbaseES V8R3 集群运维系列 -- failover切换后集群自动恢复

​ 案例说明&#xff1a; KingbaseES V8R3集群默认在触发failover切换后&#xff0c;为保证数据安全&#xff0c;原主库需要通过人工介入后&#xff0c;恢复为新的备库加入到集群。在无人值守的现场环境&#xff0c;需要在触发failover切换后&#xff0c;主库可以自动恢复为新备…...

【Selenium中】——全栈开发——如桃花来

目录索引 查找元素&#xff1a;查找方法&#xff1a;单个元素查找&#xff1a;多个元素查找&#xff1a;*代码演示&#xff1a;* 元素交互操作&#xff1a;清空文字&#xff1a; 推荐的变量名定义名称&#xff1a;执行JavaScript &#xff1a;滚动页面方法&#xff1a;*滚动到底…...

Sarsa增强版之Sarsa-λ依然走迷宫

Sarsa-λ&#xff08;Sarsa Lambda&#xff09;是Sarsa算法的一种变体&#xff0c;其中“λ”表示一个介于0和1之间的参数&#xff0c;用于平衡当前状态和之前所有状态的重要性。 Sarsa算法是一种基于Q-learning算法的增量式学习方法&#xff0c;通过在实际环境中不断探索和学…...

生成 Cypher 能力:MOSS VS ChatGLM

生成 Cypher 能力&#xff1a;MOSS VS ChatGLM 生成 Cypher 能力&#xff1a;MOSS VS ChatGLM一、 测试结果二、 测试代码&#xff08;包含Prompt&#xff09; Here’s the table of contents: 生成 Cypher 能力&#xff1a;MOSS VS ChatGLM MOSS介绍&#xff1a;MOSS 是复旦大…...

数据库的键和存储

主键:数据库表中对存储数据对象给予以唯一和完整表示的数据列或属性的组合。一个数据列只能有一个主键&#xff0c;且主键的取值不能缺失&#xff0c;即不能为空。 外键:在一个表中存在另一个表得主键称此为表的外键。 为什么用自增列作为主键&#xff1f; 如果我们定义了主…...

基于AT89C51单片机的并入串出乘法口诀的设计与仿真

点击链接获取Keil源码与Project Backups仿真图&#xff1a; https://download.csdn.net/download/qq_64505944/87779146?spm1001.2014.3001.5503 源码获取 并入串出乘法口诀的设计与仿真系统设计 目录 第一章 概述 3 1.1课题研究及意义 3 1.2课题设计内容 4 第二章系统设计…...

人生在世皆有过错,来一起看看Java中的异常吧!!!

Java中的异常问题详解 一、异常的概念与分类 1.异常概念 概念&#xff1a;Java异常是一个描述在代码段中发生异常的对象&#xff0c;当发生异常情况时&#xff0c;一个代表该异常的对象被创建并且在导致该异常的方法中被抛出&#xff0c;而该方法可以选择自己处理异常或者传…...

linux 测试连接网络和端口 telnet

一、安装telnet 1、检测telnet-server的rpm包是否安装 [rootlocalhost ~]# rpm -qa telnet-server 若无输入内容&#xff0c;则表示没有安装。出于安全考虑telnet-server.rpm是默认没有安装的&#xff0c;而telnet的客户端是标配。即下面的软件是默认安装的。 2、若未安装&…...

一文快速入门体验 Hibernate

前言 Hibernate 是一个优秀的持久层的框架&#xff0c;当然&#xff0c;虽然现在说用得比较多的是 MyBaits&#xff0c;但是我工作中也不得不接触 Hibernate&#xff0c;特别是一些老项目需要你维护的时候。所以&#xff0c;在此写下这篇文章&#xff0c;方便自己回顾&#xf…...

【RabbitMQ】SpringAMQP

RabbitMQ 1.初识MQ 1.1.同步和异步通讯 微服务间通讯有同步和异步两种方式&#xff1a; 同步通讯&#xff1a;就像打电话&#xff0c;需要实时响应。 异步通讯&#xff1a;就像发邮件&#xff0c;不需要马上回复。 两种方式各有优劣&#xff0c;打电话可以立即得到响应&am…...

错题汇总08

1.如果友元函数重载一个运算符时&#xff0c;其参数表中没有任何参数则说明该运算符是 A 一元运算符 B 二元运算符 C 选项A&#xff09;和选项B&#xff09;都可能 D 重载错误 运算符重载 1.重载成类的成员函数------>形参数目看起来比该运算符需要的参数个数少1&#x…...

使用urllib库简单入门

使用urllib库简单入门 Python中的urllib库是一个非常强大的工具&#xff0c;它提供了一些模块&#xff0c;如urllib.request、urllib.parse、urllib.error、urllib.robotparser等&#xff0c;可以用来处理URLs和网页数据的获取、发送和处理。 在本文中&#xff0c;我们将介绍…...

C++学习 Day11

目录 1. 再谈构造函数 1.1 构造函数体赋值 1.2 初始化列表 1.3 explicit关键字 2. stastic成员 2.1 概念 2.2 特性 1. 再谈构造函数 1.1 构造函数体赋值 在创建对象时&#xff0c;编译器通过调用构造函数&#xff0c;给对象中各个成员变量一个合适的初始值。 class Date…...

python中函数与类 类中的方法-静态方法/动态方法

class student():position即令def __init__(self,name,age):self.namenameself.ageagedef eat(self):passclassmethoddef cla(cls):passstaticmethoddef sta():passpassstustudent(name张三,age12) print(stu.position)stu.sta() stu.cla()# 直接使用静态和类方法 student.cla(…...

基于trace_id实现ForkJoinPool的链路追踪

一、引言 之前写过一篇博客&#xff1a;基于trace_id的链路追踪&#xff08;含Feign、Hystrix、线程池等场景&#xff09;&#xff0c;主要介绍在微服务体系架构中&#xff0c;如何实现分布式系统的链路追踪的博客&#xff0c;其中主要实现了以下几种场景&#xff1a; Filter…...

Qt推流程序(视频文件/视频流/摄像头/桌面转成流媒体rtmp+hls+webrtc)可在网页和播放器远程观看

一、前言说明 推流直播就是把采集阶段封包好的内容传输到服务器的过程。其实就是将现场的视频信号从手机端&#xff0c;电脑端&#xff0c;摄影机端打包传到服务器的过程。“推流”对网络要求比较高&#xff0c;如果网络不稳定&#xff0c;直播效果就会很差&#xff0c;观众观…...

ChatGPT入门到高级【第一章】

第一章&#xff1a;Chatgpt的起源和发展 1.1 人工智能和Chatbot的概念 1.2 Chatbot的历史发展 1.3 机器学习技术在Chatbot中的应用 1.4 Chatgpt的诞生和发展 第二章&#xff1a;Chatgpt的技术原理 2.1 自然语言处理技术 2.2 深度学习技术 2.3 Transformer模型 2.4 GPT模型 第…...

云原生应用架构

本博客地址&#xff1a;https://security.blog.csdn.net/article/details/130566883 一、什么是云原生应用架构 成为云原生应用至少需要满足下面几个特点&#xff1a; ● 使用微服务架构对业务进行拆分。单个微服务是个自治的服务领域&#xff0c;对这个领域内的业务实体能够…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容&#xff0c;我认为是AI开发里面非常重要的内容。它在AI开发里无处不在&#xff0c;当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗"&#xff0c;或者让翻译模型 "将这段合同翻译成商务日语" 时&#xff0c;输入的这句话就是 Prompt。…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试

作者&#xff1a;Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位&#xff1a;中南大学地球科学与信息物理学院论文标题&#xff1a;BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接&#xff1a;https://arxiv.…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

Spring Boot面试题精选汇总

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包&#xff1a; for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向&#xff0c;可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)

本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...

Caliper 负载(Workload)详细解析

Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...