Kotlin高仿微信-第12篇-单聊-图片

news/2024/4/26 6:53:13/文章来源:https://blog.csdn.net/maoning20080808/article/details/128110165

 Kotlin高仿微信-项目实践58篇详细讲解了各个功能点,包括:注册、登录、主页、单聊(文本、表情、语音、图片、小视频、视频通话、语音通话、红包、转账)、群聊、个人信息、朋友圈、支付服务、扫一扫、搜索好友、添加好友、开通VIP等众多功能。

Kotlin高仿微信-项目实践58篇,点击查看详情

效果图:

详细的聊天功能请查看Kotlin高仿微信-第8篇-单聊,这里是提取图片功能的部分实现。

实现代码:

显示图片:

<androidx.appcompat.widget.AppCompatImageViewandroid:id="@+id/chat_item_me_img"app:layout_constraintEnd_toStartOf="@+id/chat_item_me_avatar"app:layout_constraintTop_toTopOf="parent"android:layout_width="100dp"android:layout_height="200dp"android:scaleType="centerCrop"android:layout_marginEnd="10dp"android:src="@drawable/wc_loading_default"android:visibility="gone"/>

打开相册:

//单选  // 打开相册
ImageSelector.builder().useCamera(false) // 设置是否使用拍照.setSingle(true) //设置是否单选.canPreview(true) //是否点击放大图片查看,,默认为true.start(this,REQUEST_PICTURE_CODE)
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {super.onActivityResult(requestCode, resultCode, data)if (requestCode == REQUEST_PICTURE_CODE && data != null) {val images = data.getStringArrayListExtra(ImageSelector.SELECT_RESULT)if(images != null && images.size > 0) {AddFileListener.sendFile(ChatBean.CONTENT_TYPE_IMG, images[0], toUserId,0)}}
}

/*** 发送图片、小视频、语音* @param fileType Int* @param picPath String* @param toUserID String*/
fun sendFile(fileType: Int, filePath : String, toUserId : String, time: Int) {CoroutineScope(Dispatchers.IO).launch {//语音、小视频多少秒val toId: String = BaseUtils.getChatId(toUserId) + "/Smack"var resultFilePath = ""if(TextUtils.isEmpty(filePath)){return@launch}if(!File(filePath).exists()){return@launch}var second = timeif(fileType == ChatBean.CONTENT_TYPE_VOICE){second = time} else if(fileType == ChatBean.CONTENT_TYPE_VIDEO){second = CommonUtils.Media.getMediaTime(filePath, fileType)}//先刷新页面,再慢慢上传文件var chatBean = processSendChatBean(toUserId, fileType, filePath, second)if(fileType == ChatBean.CONTENT_TYPE_IMG){//图片//压缩图片后路径var resultPicPath = UploadFileUtils.getCompressFile(filePath)resultFilePath = resultPicPath} else if(fileType == ChatBean.CONTENT_TYPE_VOICE){//语音resultFilePath = filePathTagUtils.d("语音时间:${second}")} else if(fileType == ChatBean.CONTENT_TYPE_VIDEO){//小视频var videoFilePath = UploadFileUtils.getVideoCompressFile()//TagUtils.d("开始发送小视频压缩前文件2:${videoFilePath}")var compressResult = VideoController.getInstance().convertVideo(filePath, videoFilePath, VideoController.COMPRESS_QUALITY_LOW, object : VideoController.CompressProgressListener {override fun onProgress(percent: Float) {//TagUtils.d("压缩小视频进度:${percent}")}})TagUtils.d("小视频时间:${second}")resultFilePath = videoFilePath}TagUtils.d("上传文件:${resultFilePath}")val filetosend = File(resultFilePath)if (!filetosend.exists()) {return@launch}try {var account : String = DataStoreUtils.getAccount()if(fileType == ChatBean.CONTENT_TYPE_IMG){//图片TagUtils.d("图片发送成功。")var chatBeanServer = UploadFileUtils.uploadChatImages(account, toUserId, resultFilePath,0)if(chatBeanServer != null){chatBeanServer.imgPath = chatBeanServer.imgPathchatBean = chatBeanServer}} else if(fileType == ChatBean.CONTENT_TYPE_VOICE){//录音完成,要转码,等待0.2秒再发送delay(100)//语音var chatBeanServer = UploadFileUtils.uploadChatVoice(account, toUserId, resultFilePath, second)if(chatBeanServer != null){chatBeanServer.voiceLocal = resultFilePathchatBean = chatBeanServer}} else if(fileType == ChatBean.CONTENT_TYPE_VIDEO){//小视频var chatBeanServer = UploadFileUtils.uploadChatVideo(account, toUserId, resultFilePath, second)if(chatBeanServer != null){chatBeanServer.videoLocal = resultFilePathchatBean = chatBeanServer}}chatBean?.let {ChatRepository.updateChat(it)}var baseSystemBoolean = BaseSystemRepository.getBaseSystemSync(WcApp.getContext().packageName)if(baseSystemBoolean != null && baseSystemBoolean.sync == CommonUtils.Sync.SERVER_SYNC){//同步不需要使用transfer上传文件,因为transfer上传太慢了, 直接上传到服务器,然后发送普通的消息if(fileType == ChatBean.CONTENT_TYPE_VOICE){var content = CommonUtils.Chat.VOICE_MARK + chatBean.voiceChatManagerUtils.getInstance().sendMessage(toUserId, content)} else if(fileType == ChatBean.CONTENT_TYPE_VIDEO){var content = CommonUtils.Chat.VIDEO_MARK + chatBean.videoChatManagerUtils.getInstance().sendMessage(toUserId, content)} else if(fileType == ChatBean.CONTENT_TYPE_IMG){var content = CommonUtils.Chat.IMAGE_MARK + chatBean.imgPathChatManagerUtils.getInstance().sendMessage(toUserId, content)}return@launch}val fileTransferManager = getFileTransferManager()val transfer = fileTransferManager.createOutgoingFileTransfer(toId) // 创建一个输出文件传输对象//对方用户在线才需要上传文件if(XmppConnectionManager.getInstance().isOnLine(toUserId)){TagUtils.d("${toUserId} 在线 开始上传。")transfer.sendFile(filetosend,"recv img")while (!transfer.isDone) {if (transfer.status == FileTransfer.Status.error) {TagUtils.d("聊天文件上传错误 , ERROR!!! " + transfer.error)} else {TagUtils.d("聊天文件上传 " + transfer.status +" , " + transfer.progress)}Thread.sleep(20)}} else {TagUtils.d("toUserId 不在线")}if (transfer.isDone) {//上传完成}} catch (e1: XMPPException) {e1.printStackTrace()}}
}
/*** Author : wangning* Email : maoning20080809@163.com* Date : 2022/5/31 16:31* Description : 处理聊天信息发来的信息*/
class ChatManagerListener : ChatManagerListener {override fun chatCreated(chat: Chat, createdLocally: Boolean) {TagUtils.d("消息监听回调:chat = ${chat} , createdLocally = ${createdLocally}")if(!createdLocally){chat.addMessageListener { chat, message ->TagUtils.d("获取好友发来的信息 ${message.from} , ${message.to}, ${message.body}")var content = message.getBody()if(!TextUtils.isEmpty(content) && content.length > 0){var fromUser = BaseUtils.getChatAccountFrom(message.from)var toUser = BaseUtils.getChatAccount(message.to)var userType = ChatBean.USER_TYPE_OTHERif(content.startsWith(CommonUtils.Chat.LOCATION_MARK)){//发送定位//去掉location###标志var remarkContent = CommonUtils.Chat.getLocation(content)//使用逗号分隔符,分别读取经纬度var contents = remarkContent.split(",")var latitude = contents[0].toDouble()var longitude = contents[1].toDouble()var chatBean = CommonUtils.Chat.getChatBean(fromUser, toUser, userType, content, ChatBean.CONTENT_TYPE_LOCATION, "", latitude, longitude)ChatRepository.insertChat(chatBean)chatBean.isReceive = trueEventBus.getDefault().post(chatBean)} else if(content.startsWith(CommonUtils.Chat.REDPACKET_MARK)){//发送红包, 去掉redpacket###写入数据库content = CommonUtils.Chat.getRedpacket(content).toString()var chatBean = CommonUtils.Chat.getChatBean(fromUser, toUser, userType, content, ChatBean.CONTENT_TYPE_REDPACKET, "",0.0, 0.0)ChatRepository.insertChat(chatBean)chatBean.isReceive = trueEventBus.getDefault().post(chatBean)} else if(content.startsWith(CommonUtils.Chat.VOICE_MARK)){//发送语音, 去掉voice###写入数据库content = CommonUtils.Chat.getMedia(content, CommonUtils.Chat.VOICE_MARK)var chatBean = CommonUtils.Chat.getChatBeanVoiceServer(fromUser, toUser, userType,ChatBean.CONTENT_TYPE_VOICE, content,0)chatBean.isReceive = trueprocessDownload(chatBean)} else if(content.startsWith(CommonUtils.Chat.VIDEO_MARK)){//发送小视频, 去掉video###写入数据库content = CommonUtils.Chat.getMedia(content, CommonUtils.Chat.VIDEO_MARK)var chatBean = CommonUtils.Chat.getChatBeanVideoServer(fromUser, toUser, userType,ChatBean.CONTENT_TYPE_VIDEO, content,0)chatBean.isReceive = trueprocessDownload(chatBean)} else if(content.startsWith(CommonUtils.Chat.IMAGE_MARK)){//发送图片, 去掉image###写入数据库content = CommonUtils.Chat.getMedia(content, CommonUtils.Chat.IMAGE_MARK)var chatBean = CommonUtils.Chat.getChatBeanImageServer(fromUser, toUser, userType,ChatBean.CONTENT_TYPE_IMG, content,0)chatBean.isReceive = trueprocessDownload(chatBean)} else if(content.startsWith(CommonUtils.Chat.TRANSFER_MARK)){//发送转账, 去掉transfer###写入数据库content = CommonUtils.Chat.getTransfer(content).toString()var chatBean = CommonUtils.Chat.getChatBean(fromUser, toUser, userType, content, ChatBean.CONTENT_TYPE_TRANSFER, "",0.0, 0.0)ChatRepository.insertChat(chatBean)chatBean.isReceive = trueEventBus.getDefault().post(chatBean)} else if(content.startsWith(CommonUtils.QRCommon.QR_RECEIVE_CODE)){//向个人发送收款var balance = content.substring(CommonUtils.QRCommon.QR_RECEIVE_CODE.length, content.length)TagUtils.d("MyChatManagerListener 向个人发送收款金额: ${fromUser} , ${toUser},  ${balance}")updateBalanceServer(fromUser, toUser, CommonUtils.User.OPERATOR_PLUS, balance.toFloat())} else if(content.startsWith(CommonUtils.QRCommon.QR_PAYMENT_CODE)){//向商家付款var balance = content.substring(CommonUtils.QRCommon.QR_RECEIVE_CODE.length, content.length)TagUtils.d("MyChatManagerListener 向商家付款金额: ${fromUser} , ${toUser}, ${balance}")updateBalanceServer(fromUser, toUser, CommonUtils.User.OPERATOR_MINUS, balance.toFloat())} else {var chatBean = CommonUtils.Chat.getChatBean(fromUser, toUser, userType, content, ChatBean.CONTENT_TYPE_TEXT, "",0.0, 0.0)ChatRepository.insertChat(chatBean)chatBean.isReceive = trueEventBus.getDefault().post(chatBean)}ChatNotificationUtils.sendNotification(fromUser)}}}}/*** 下载图片、语音、小视频*/private fun processDownload(chatBean : ChatBean){var fileName = ""if(chatBean.contentType == ChatBean.CONTENT_TYPE_VOICE){fileName = chatBean.voice} else if(chatBean.contentType == ChatBean.CONTENT_TYPE_VIDEO){fileName = chatBean.video} else if(chatBean.contentType == ChatBean.CONTENT_TYPE_IMG){fileName = chatBean.imgPath} else {return}var videoUrl = CommonUtils.Moments.getReallyImageUrl(fileName)var videoFile = FileUtils.getBaseFile(fileName)TagUtils.d("下载多媒体Url :${videoUrl} ")TagUtils.d("下载多媒体File :${videoFile} ")VideoDownloadManager.downloadFast(videoUrl, videoFile, object : VideoDownloadInter {override fun onDone(filePath: String) {TagUtils.d("小视频多媒体完成:${filePath}")if(chatBean.contentType == ChatBean.CONTENT_TYPE_VOICE){var second = CommonUtils.Media.getMediaTime(filePath, chatBean.contentType)chatBean.second = secondchatBean.voiceLocal = filePath} else if(chatBean.contentType == ChatBean.CONTENT_TYPE_VIDEO){chatBean.videoLocal = filePathvar second = CommonUtils.Media.getMediaTime(filePath, chatBean.contentType)chatBean.second = second} else if(chatBean.contentType == ChatBean.CONTENT_TYPE_IMG){chatBean.imgPathLocal = filePath}ChatRepository.insertChat(chatBean)EventBus.getDefault().post(chatBean)}override fun onError() {}override fun onProgress(process: Int) {}})}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_39108.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【JavaEE】MyBatis

文章目录1.MyBatis介绍2.MyBatis快速入门3.Mapper代理开发4.MyBatis核心配置文件5.配置文件完成增删改查5.1 查询5.2 添加/修改5.3 删除6.MyBatis参数传递7.注解完成增删改查1.MyBatis介绍 1.什么是MyBatis? MyBatis是一款优秀的 持久层框架&#xff0c;用于简化JDBC开发MyBat…

入门力扣自学笔记208 C++ (题目编号:895)

895. 最大频率栈​​​​​​ 题目&#xff1a; 设计一个类似堆栈的数据结构&#xff0c;将元素推入堆栈&#xff0c;并从堆栈中弹出出现频率最高的元素。 实现 FreqStack 类: FreqStack() 构造一个空的堆栈。 void push(int val) 将一个整数 val 压入栈顶。 int pop() 删除…

Kotlin高仿微信-第11篇-单聊-语音

Kotlin高仿微信-项目实践58篇详细讲解了各个功能点&#xff0c;包括&#xff1a;注册、登录、主页、单聊(文本、表情、语音、图片、小视频、视频通话、语音通话、红包、转账)、群聊、个人信息、朋友圈、支付服务、扫一扫、搜索好友、添加好友、开通VIP等众多功能。 Kotlin高仿…

基于Tree-LSTM网络语义表示模型

TC&#xff1b;DR 目前的LSTM仅能对序列信息进行建模&#xff0c; 但是自然语言中通常由词组成的短语形成了句法依存的语义树。为了学习到树结构的语义信息。论文中提出了两种Tree-LSTM模型。Child-Sum、Tree-LSTM、和N-ary Tree LSTMs。实验部分的Tree-LSTM、对比多种LSTMs的…

nuxtjs中asyncData异步数据请求、代理配置、fetch网络请求、vuex的使用、中间件处理

文章目录1. asyncData异步数据请求2. 代理配置3. fetch网络请求4. vuex4.1 state中的数据展示4.2 同步方法与异步方法4.3 数据持久化处理5. 中间件处理1. asyncData异步数据请求 Nuxt.js 扩展了 Vue.js&#xff0c;增加了一个叫 asyncData 和 fetch 的方法&#xff0c;使得我们…

这或许是全网最详细的介绍预言机赛道的视频课程,通俗易通,有趣有料!

图片来源&#xff1a;由无界版图 AI 绘画工具生成有一句话在创业者中很流行&#xff1a;Web3创业三大坑&#xff0c;隐私、跨链、预言机……搞塌加密市场的DK和SBF还在豪华度假酒店里思考人生搞隐私&#xff0c;一毛钱没赚到的Tornado cash开发者却在吃牢饭……加密圈前十大资产…

力扣(LeetCode)895. 最大频率栈(C++)

设计 ①维护最大频率&#xff0c;②维护每个数的出现次数&#xff0c;③维护出现次数对应的栈。 压栈时&#xff0c;新数压入出现次数对应的栈&#xff0c;每次压入新数&#xff0c;维护最大频率(所有出现次数中的最大出现次数)。 弹栈时&#xff0c;找最大频率对应的栈&…

拖死项目的不是团队,可能是失败的管理

项目中的活动&#xff0c;归根结底是由人来完成的&#xff0c;如何发挥项目成员的能力&#xff0c;对于项目的成败起着至关重要的作用。如何充分地发挥团队成员的能力&#xff0c;对项目经理也是一个挑战。 在团队管理者我们会遇见这些难题&#xff1a; 1、团队凝聚力不足&a…

【MySQL 18】Docker 安装 MySQL8 .0.30

1、查看可用的 MySQL 版本 访问 MySQL 镜像库地址&#xff1a; https://hub.docker.com/_/mysql?tabtags 。2、拉取 MySQL 8.0.30 镜像 拉取官方的指定版本的镜像&#xff1a; docker pull mysql:8.0.30[rootlocalhost deploy]# docker pull mysql:8.0.30 8.0.30: Pulling…

云小课|云小课教您如何选择Redis实例类型

阅识风云是华为云信息大咖&#xff0c;擅长将复杂信息多元化呈现&#xff0c;其出品的一张图(云图说)、深入浅出的博文(云小课)或短视频(云视厅)总有一款能让您快速上手华为云。更多精彩内容请单击此处。 摘要&#xff1a;购买Redis实例时&#xff0c;实例类型有单机、主备、Pr…

公司新来一个同事,把网关系统设计的炉火纯青,万能通用,稳的一批。。

本文准备围绕七个点来讲网关&#xff0c;分别是网关的基本概念、网关设计思路、网关设计重点、流量网关、业务网关、常见网关对比&#xff0c;对基础概念熟悉的朋友可以根据目录查看自己感兴趣的部分。 什么是网关 网关&#xff0c;很多地方将网关比如成门&#xff0c; 没什么…

Casein-PEG-Rhodamine B 络蛋白-聚乙二醇-罗丹明B Casein-RB

产品名称&#xff1a;络蛋白-聚乙二醇-罗丹明B 英文名称&#xff1a;Casein-PEG-Rhodamine B 质量控制&#xff1a;95% 原料分散系数PDI&#xff1a;≤1.05 存储条件&#xff1a;-20C&#xff0c;避光&#xff0c;避湿 用 途&#xff1a;仅供科研实验使用&#xff0c;不用于诊…

全波形反演的深度学习方法: 第三章 常规反演

本章介绍反演的基础知识, 以及工程中的常规反演. 仅供内部培训. 3.1 地震数据采集 地震勘探中常使用人工激发的振动进行数据采集. 相应装置包括: 激发器是产生震动的装置, 如炸药, 地震车 (撞击地面). 在城市道路等具有车辆会产生振动的地方, 也可以不安装这类装置;地震检波…

【Linux】高频指令及简单的vim使用(0基础带你快速入门)

目录 一、目录操作指令 1.1、ls 1.2、pwd 1.3、cd 1.4、touch 1.5、cat 1.6、echo 1.7、mkdir 1.8、rm 1.9、mv 1.10、cp 二、Linux中如何手动安装插件 三、vim 3.1、打开文件 3.2、编辑文件 3.3、保存退出 一、目录操作指令 1.1、ls 语法&#xff1a; 第一种&#…

Android中简单使用aspectj

Android中简单使用aspectj 前言&#xff1a; 面向切面编程&#xff08;AOP是Aspect Oriented Program的首字母缩写&#xff09;,这种在运行时&#xff0c;动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程. 1.简介&#xff1a; 在Android中使用注解…

onnx删除无用属性

这里写自定义目录标题在推理onnx模型时&#xff0c;报了一个错&#xff0c;如下&#xff1a;InvalidGraph: [ONNXRuntimeError] : 10 : INVALID_GRAPH : This is an invalid model. In Node, ("Conv_0", Conv, "", -1) : ("x": tensor(float),&q…

xxljob

分为调度中心 执行器 调度中心&#xff1a;提供可视化界面&#xff0c;配置定时任务&#xff0c;定时去调用执行器 调度中心执行器管理&#xff1a;每个springboot作为执行器&#xff0c; 也就是执行器的标识 任务管理&#xff1a;选中执行器&#xff0c;创建改该执行器下的任…

c++ - 第15节 - 二叉树进阶

1. 二叉搜索树 1.1.二叉搜索树概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或者是具有以下性质的二叉树: 若它的左子树不为空&#xff0c;则左子树上所有节点的值都小于根节点的值若它的右子树不为空&#xff0c;则右子树上所有节点的值都大于根节…

iphone怎么传数据到另一个手机,苹果如何转移数据到新手机,两台iphone怎么同步所有数据

换新手机后&#xff0c;需要迁移旧苹果手机的数据到新苹果手机里面&#xff0c;那么&#xff0c;iphone怎么传数据到另一个手机&#xff1f;本篇文章带您深度了解苹果手机的数据传输技巧。 方法一、通过“快速开始”传输数据 苹果手机如何数据传输&#xff1f;我记得之前换 iP…

沉睡者IT - Web3的未来在哪里?

欢迎关注沉睡者IT&#xff0c;点上面关注我 ↑ ↑ 专家说&#xff0c;web3将颠覆现在的互联网 今天我们来讨论一下&#xff0c;web3会颠覆现在的互联网呢&#xff1f; 看了小编往期的作品你应该知道&#xff0c;如果同样的作品发在web3平台上&#xff0c;你将获取到收益。 那…