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

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

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

效果图:

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

实现代码:

我的语言布局:

<LinearLayout
    android:id="@+id/chat_item_me_voice_layout"
    app:layout_constraintEnd_toStartOf="@+id/chat_item_me_avatar"
    app:layout_constraintTop_toTopOf="@+id/chat_item_me_avatar"
    app:layout_constraintBottom_toBottomOf="@+id/chat_item_me_avatar"
    android:layout_width="120dp"
    android:layout_height="40dp"
    android:layout_marginEnd="10dp"
    android:background="@drawable/wc_base_voice_green_normal"
    android:gravity="center"
    android:visibility="visible"
    android:orientation="horizontal">

    <androidx.appcompat.widget.AppCompatTextView
        android:id="@+id/chat_item_me_voice_second"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="1'"
        android:layout_marginRight="4dp"
        android:textSize="20sp"/>
    <ImageView
        android:id="@+id/chat_item_me_voice"
        android:layout_width="22dp"
        android:layout_height="22dp"
        android:src="@drawable/wc_chat_me_volume_2"
        android:visibility="visible"/>

</LinearLayout>

好友的语音布局:

<LinearLayout
    android:id="@+id/chat_item_other_voice_layout"
    app:layout_constraintStart_toEndOf="@+id/chat_item_other_avatar"
    app:layout_constraintTop_toTopOf="@+id/chat_item_other_avatar"
    app:layout_constraintBottom_toBottomOf="@+id/chat_item_other_avatar"
    android:layout_width="120dp"
    android:layout_height="40dp"
    android:layout_marginStart="10dp"
    android:gravity="center"
    android:visibility="visible"
    android:background="@drawable/wc_base_voice_green_normal"
    android:orientation="horizontal">

    <ImageView
        android:id="@+id/chat_item_other_voice"
        android:layout_width="22dp"
        android:layout_height="22dp"
        android:src="@drawable/wc_chat_other_volume_2"
        android:visibility="visible"/>

    <androidx.appcompat.widget.AppCompatTextView
        android:id="@+id/chat_item_other_voice_second"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="1'"
        android:layout_marginLeft="4dp"
        android:textSize="20sp"/>

</LinearLayout>
<com.wn.wechatclientdemo.view.ChatRecordButton
    android:id="@+id/chat_record_btn"
    android:layout_width="0dp"
    android:layout_height="38dp"
    android:visibility="gone"
    android:layout_marginHorizontal="10dp"
    android:background="@drawable/wc_chat_voice_selector"
    app:layout_constraintStart_toEndOf="@+id/chat_audio"
    app:layout_constraintEnd_toStartOf="@+id/chat_emoji"
    app:layout_constraintTop_toTopOf="@+id/chat_audio"
    app:layout_constraintBottom_toBottomOf="@+id/chat_audio"
    android:text="按住说话"/>

/**
 * Author : wangning
 * Email : maoning20080809@163.com
 * Date : 2022/5/4 17:36
 * Description : 聊天语言按钮
 */
class ChatRecordButton : AppCompatButton {

    constructor(context: Context) : super(context)
    constructor(context: Context, attributeSet: AttributeSet) :super(context, attributeSet)
    constructor(context: Context, attributeSet: AttributeSet, defStyle : Int) : super(context, attributeSet, defStyle)
    private var mFile : String = ""
    private var mFileMp3 : String = ""
    private var finishedListener: OnFinishedRecordListener? = null

    /**
     * 最短录音时间
     */
    private val MIN_INTERVAL_TIME = 1000

    /**
     * 最长录音时间
     */
    private val MAX_INTERVAL_TIME = 1000 * 60


    private var view: View? = null

    private var mStateTV: TextView? = null

    private var mStateIV: ImageView? = null

    companion object var mRecorder: MediaRecorder? = null
    private val mThread: ObtainDecibelThread? = null
    private var volumeHandler: Handler? = null

    private var y1 : Float = 0f
    private var anim: AnimationDrawable? = null


    fun setOnFinishedRecordListener(listener: OnFinishedRecordListener?) {
        finishedListener = listener
    }

    private var startTime: Long = 0
    private var recordDialog: Dialog? = null
    private val res = intArrayOf(
        R.drawable.wc_chat_volume_0,
        R.drawable.wc_chat_volume_1,
        R.drawable.wc_chat_volume_2,
        R.drawable.wc_chat_volume_3,
        R.drawable.wc_chat_volume_4,
        R.drawable.wc_chat_volume_5,
        R.drawable.wc_chat_volume_6,
        R.drawable.wc_chat_volume_7,
        R.drawable.wc_chat_volume_8
    )

    //private var audioRecordTool: AudioRecordTool? = null

    init {
        volumeHandler = object : Handler() {
            override fun handleMessage(msg: Message) {
                if (msg.what == -100) {
                    stopRecording()
                    recordDialog!!.dismiss()
                } else if (msg.what != -1) {
                    mStateIV!!.setImageResource(res.get(msg.what))
                }
            }
        }
    }

    override fun onTouchEvent(event: MotionEvent?): Boolean {
        val action = event!!.action
        y1 = event.y
        if (mStateTV != null && mStateIV != null && y1 < 0) {
            mStateTV?.text = "松开手指,取消发送"
            mStateIV?.setImageDrawable(resources.getDrawable(R.drawable.wc_chat_volume_cancel))
        } else if (mStateTV != null) {
            mStateTV?.text = "手指上滑,取消发送"
        }
        when (action) {
            MotionEvent.ACTION_DOWN -> {
                text = "松开发送"
                initDialogAndStartRecord()
            }
            MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                this.text = "按住录音"
                if (y1 >= 0 && System.currentTimeMillis() - startTime <= MAX_INTERVAL_TIME) {
                    TagUtils.d("结束录音:")
                    finishRecord()
                } else if (y1 < 0) {  //当手指向上滑,会cancel
                    cancelRecord()
                }
            }
        }

        return true
    }


    /**
     * 初始化录音对话框 并 开始录音
     */
    private fun initDialogAndStartRecord() {
        startTime = System.currentTimeMillis()
        recordDialog = Dialog(context, R.style.like_toast_dialog_style)
        // view = new ImageView(getContext());
        view = inflate(context, R.layout.wc_chat_dialog_record, null)
        mStateIV = view?.findViewById<ImageView>(R.id.rc_audio_state_image)
        mStateTV = view?.findViewById<TextView>(R.id.rc_audio_state_text)
        mStateIV?.setImageDrawable(resources.getDrawable(R.drawable.anim_mic))
        anim = mStateIV?.getDrawable() as AnimationDrawable
        anim?.start()
        mStateIV?.setVisibility(VISIBLE)
        //mStateIV.setImageResource(R.drawable.ic_volume_1);
        mStateTV?.setVisibility(VISIBLE)
        mStateTV?.setText("手指上滑,取消发送")
        recordDialog?.setContentView(view!!, LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT)
        )
        recordDialog?.setOnDismissListener(onDismiss)
        val lp = recordDialog?.getWindow()!!.attributes
        lp.gravity = Gravity.CENTER
        startRecording()
        recordDialog?.show()
    }

    /**
     * 放开手指,结束录音处理
     */
    private fun finishRecord() {
        val intervalTime: Long = System.currentTimeMillis() - startTime
        if (intervalTime < MIN_INTERVAL_TIME) {
            TagUtils.d("录音时间太短")
            volumeHandler!!.sendEmptyMessageDelayed(-100, 500)
            //view.setBackgroundResource(R.drawable.ic_voice_cancel);
            mStateIV!!.setImageDrawable(resources.getDrawable(R.drawable.wc_chat_volume_wraning))
            mStateTV!!.text = "录音时间太短"
            anim!!.stop()
            val file = File(mFile!!)
            file.delete()
            return
        } else {
            stopRecording()
            recordDialog!!.dismiss()
        }
        TagUtils.d("录音完成的路径:$mFile")
        val mediaPlayer = MediaPlayer()
        try {
            mediaPlayer.setDataSource(mFile)
            mediaPlayer.prepare()
            mediaPlayer.duration
            TagUtils.d("获取到的时长:" + mediaPlayer.duration / 1000)
        } catch (e: Exception) {
        }
        //if (finishedListener != null) finishedListener!!.onFinishedRecord( mFile, mediaPlayer.duration / 1000)
        //删除原文件
        TagUtils.d("amr录音保存路径:${mFile}")
        File(mFile).delete()
        /*TagUtils.d("pcm录音保存路径:${audioRecordTool?.pcmFileName}")
        audioRecordTool?.deletePcmFile()
        //最终使用的是wav录音文件,音质非常的好
        mFile = audioRecordTool?.wavFileName!!
        TagUtils.d("wav录音保存路径:${audioRecordTool?.wavFileName!!}")*/
        TagUtils.d("mp3录音保存路径:${mFileMp3}")
        if (finishedListener != null) finishedListener!!.onFinishedRecord( mFileMp3, mediaPlayer.duration / 1000)
    }

    /**
     * 取消录音对话框和停止录音
     */
    fun cancelRecord() {
        stopRecording()
        recordDialog!!.dismiss()
        val file = File(mFile)
        file.delete()

        LameMp3Manager.instance.cancelRecorder()
        var mp3File = File(mFileMp3)
        mp3File.delete()

    }


    /**
     * 执行录音操作
     */
    private fun startRecording() {

        if(ContextCompat.checkSelfPermission(WcApp.getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED){
            mFile = FileUtils.getBaseFile("voice_" + System.currentTimeMillis() + ".amr").absolutePath
            mFileMp3 = FileUtils.getBaseFile("voice_" + System.currentTimeMillis() + ".mp3").absolutePath
        } else {
            ToastUtils.makeText(R.string.wc_permission_tip_record)
            return
        }
        //使用MP3文件代替wav,因为mp3语音清晰,占用空间小
        LameMp3Manager.instance.startRecorder(mFileMp3)
        /*audioRecordTool = AudioRecordTool()
        //初始化
        audioRecordTool?.createAudioRecord()
        audioRecordTool?.start()*/

        if (mRecorder != null) {
            mRecorder?.reset()
        } else {
            mRecorder = MediaRecorder()
        }
        mRecorder?.setAudioSource(MediaRecorder.AudioSource.MIC)
        mRecorder?.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB)
        mRecorder?.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB)
        mRecorder?.setOutputFile(mFile)
        try {
            mRecorder?.prepare()
            mRecorder?.start()
        } catch (e: Exception) {
            TagUtils.d("preparestart异常,重新开始录音:$e")
            e.printStackTrace()
            mRecorder?.release()
            mRecorder = null
            startRecording()
        }
    }


    private fun stopRecording() {
        //audioRecordTool?.stop()
        LameMp3Manager.instance.stopRecorder()

        if (mThread != null) {
            mThread.exit()
            //mThread = null
        }
        if (mRecorder != null) {
            try {
                mRecorder?.stop() //停止时没有prepare,就会报stop failed
                mRecorder?.reset()
                mRecorder?.release()
                mRecorder = null
            } catch (pE: RuntimeException) {
                pE.printStackTrace()
            } finally {
                if (recordDialog!!.isShowing) {
                    recordDialog!!.dismiss()
                }
            }
        }
    }

    private class ObtainDecibelThread(val obj: ChatRecordButton) : Thread() {
        @Volatile
        private var running = true


        fun exit() {
            running = false
        }

        override fun run() {
            TagUtils.d("检测到的分贝001:")
            while (running) {

                if (obj.mRecorder == null || !running) {
                    break
                }
                // int x = recorder.getMaxAmplitude(); //振幅
                val db: Int = obj.mRecorder!!.getMaxAmplitude() / 600
                TagUtils.d("检测到的分贝002:$")
                if (db != 0 && obj.y1 >= 0) {
                    val f = (db / 5)
                    if (f == 0) obj.volumeHandler?.sendEmptyMessage(0) else if (f == 1) obj.volumeHandler?.sendEmptyMessage(
                        1
                    ) else if (f == 2) obj.volumeHandler?.sendEmptyMessage(2) else if (f == 3) obj.volumeHandler?.sendEmptyMessage(
                        3
                    ) else if (f == 4) obj.volumeHandler?.sendEmptyMessage(4) else if (f == 5) obj.volumeHandler?.sendEmptyMessage(
                        5
                    ) else if (f == 6) obj.volumeHandler?.sendEmptyMessage(6) else obj.volumeHandler?.sendEmptyMessage(
                        7
                    )
                }
                obj.volumeHandler?.sendEmptyMessage(-1)
                if (System.currentTimeMillis() - obj.startTime > 20000) {
                    obj.finishRecord()
                }
                try {
                    sleep(200)
                } catch (e: InterruptedException) {
                    e.printStackTrace()
                }
            }
        }
    }

    private val onDismiss = DialogInterface.OnDismissListener { stopRecording() }

    interface OnFinishedRecordListener{
        fun onFinishedRecord(audioPath : String, time : Int)
    }

}

//录音完成回调
chat_record_btn.setOnFinishedRecordListener(object : ChatRecordButton.OnFinishedRecordListener{
    override fun onFinishedRecord(audioPath: String, time: Int) {
        chat_content.isFocusable = false
        SoftInputUtils.hideSoftInput(chat_record_btn)
        AddFileListener.sendFile(ChatBean.CONTENT_TYPE_VOICE, audioPath, toUserId, time)
    }
})

/**
 * 发送图片、小视频、语音
 * @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 = time

        if(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 = filePath

            TagUtils.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.imgPath
                    chatBean = 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 = resultFilePath
                    chatBean = chatBeanServer
                }
            } else if(fileType == ChatBean.CONTENT_TYPE_VIDEO){
                //小视频
                var chatBeanServer = UploadFileUtils.uploadChatVideo(account, toUserId, resultFilePath, second)
                if(chatBeanServer != null){
                    chatBeanServer.videoLocal = resultFilePath
                    chatBean = 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.voice
                    ChatManagerUtils.getInstance().sendMessage(toUserId, content)
                } else if(fileType == ChatBean.CONTENT_TYPE_VIDEO){
                    var content = CommonUtils.Chat.VIDEO_MARK + chatBean.video
                    ChatManagerUtils.getInstance().sendMessage(toUserId, content)
                } else if(fileType == ChatBean.CONTENT_TYPE_IMG){
                    var content = CommonUtils.Chat.IMAGE_MARK + chatBean.imgPath
                    ChatManagerUtils.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()
        }
    }
}

//接收图片、语音、小视频文件监听
fun addFileListerer() {
    val manager = getFileTransferManager()

    manager.addFileTransferListener { request ->
        CoroutineScope(Dispatchers.IO).launch {
            //文件接收
            val transfer = request.accept()

            OutgoingFileTransfer.getResponseTimeout()

            //获取文件名字
            val fileName = transfer.fileName
            TagUtils.d("接收图片、语音:${fileName}")
            //本地创建文件
            val sdCardDir  = File(FileUtils.CHAT_ALBUM_PATH)
            if (!sdCardDir.exists()) { //判断文件夹目录是否存在
                sdCardDir.mkdir() //如果不存在则创建
            }
            //val savePath: String = FileUtils.CHAT_ALBUM_PATH + fileName
            val savePath: String = FileUtils.getBaseFile(fileName).path
            val file = File(savePath)
            //接收文件
            try {
                transfer.recieveFile(file)
                while (!transfer.isDone) {
                    if (transfer.status == FileTransfer.Status.error) {
                        TagUtils.d("接收、语音文件 ERROR!!! " + transfer.error)
                    } else {
                        TagUtils.d("接收、语音文件" + transfer.status + " , " + transfer.progress)
                    }

                    //接收小视频,要停顿一下,否则小视频不完整打不开。
                    Thread.sleep(20)

                }
                if (transfer.isDone) {

                    var account = DataStoreUtils.getAccount()
                    var chatBean : ChatBean? = null
                    var userType = ChatBean.USER_TYPE_OTHER
                    var peer = transfer.peer
                    TagUtils.d("接收文件完成peer:${peer}")
                    var toUserId = BaseUtils.getChatAccountFrom(peer)
                    TagUtils.d("接收文件完成toUserId:${toUserId}, account = ${account}")
                    if(fileName.endsWith(".mp3", true)){
                        //接收语音
                        var second = CommonUtils.Media.getMediaTime(savePath, ChatBean.CONTENT_TYPE_VOICE)
                        chatBean = CommonUtils.Chat.getChatBeanVoice(toUserId, account, userType, ChatBean.CONTENT_TYPE_VOICE, savePath, second)
                    } else if(fileName.endsWith(".mp4", true)){
                        //接收小视频
                        var second = CommonUtils.Media.getMediaTime(file.path, ChatBean.CONTENT_TYPE_VIDEO)
                        TagUtils.d("接收的小视频文件:${savePath}, ${second}秒")
                        chatBean = CommonUtils.Chat.getChatBeanVideo(toUserId, account, userType,  ChatBean.CONTENT_TYPE_VIDEO, savePath, second)
                    } else {
                        //接收图片
                        chatBean = CommonUtils.Chat.getChatBean(toUserId, account, userType, "", ChatBean.CONTENT_TYPE_IMG, savePath,0.0, 0.0)
                    }

                    chatBean?.let {
                        ChatRepository.insertChat(chatBean)
                        EventBus.getDefault().post(chatBean)
                    }
                }
            } catch (e: XMPPException) {
                e.printStackTrace()
            }
        }

    }
}

 

//web服务器方式下载
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_OTHER

                if(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 = true
                    EventBus.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 = true
                    EventBus.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 = true
                    processDownload(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 = true
                    processDownload(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 = true
                    processDownload(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 = true
                    EventBus.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 = true
                    EventBus.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 = second
                chatBean.voiceLocal = filePath
            } else if(chatBean.contentType == ChatBean.CONTENT_TYPE_VIDEO){
                chatBean.videoLocal = filePath
                var 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) {
        }
    })
}
根据提供的引用内容,出现了两个关于Kotlin的错误信息。第一个引用中显示了一个无法解析依赖的错误,指出无法下载kotlin-reflect.jar文件。第二个引用中显示了一个关于kotlin-gradle-1.8.10.jar (org.jetbrains.kotlin:kotlin-reflect)",这个错误通常是由于Gradle无法找到所需的kotlin-reflect库而引起的。解决这个问题的方法是确保你的项目的Gradle配置正确,并且指定了正确的Kotlin版本。 你可以尝试以下几个步骤来解决这个问题: 1. 确保你的项目的build.gradle文件中包含了正确的Kotlin版本和kotlin-gradle-plugin版本。你可以在build.gradle文件中找到类似于以下代码的部分: ```groovy ext { kotlin_version = '1.8.10' } dependencies { // ... implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" // ... } buildscript { // ... dependencies { // ... classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // ... } } ``` 请确保kotlin_version变量的值与你想要使用的Kotlin版本一致,并且在dependencies和buildscript的classpath中正确引用了kotlin-gradle-plugin。 2. 如果你已经确认了build.gradle文件中的配置正确无误,那么可能是因为Gradle无法从远程仓库下载kotlin-reflect.jar文件。你可以尝试清除Gradle的缓存并重新构建项目。在命令行中执行以下命令: ```shell ./gradlew clean ``` 然后重新构建项目: ```shell ./gradlew build ``` 这将清除Gradle的缓存并重新下载所需的依赖。 3. 如果上述步骤***切换到其他网络环境来解决这个问题。 希望以上步骤能够帮助你解决问题。如果你还有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

六毛六66

你的鼓励是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值