Merge branch 'master' of gitlab.navinfo.com:vivo/navinfovivo

 Conflicts:
	app/build.gradle
	app/src/main/java/com/navinfo/volvo/ui/fragments/message/ObtainMessageFragment.kt
This commit is contained in:
squallzhjch 2023-01-09 14:58:25 +08:00
commit 13f3516566
9 changed files with 125 additions and 40 deletions

View File

@ -144,7 +144,7 @@ dependencies {
implementation 'com.github.JagarYousef:ChatVoicePlayer:1.1.0'
// https://github.com/XiaoGe-1996/ImageViewer
implementation 'com.github.XiaoGe-1996:ImageViewer:v1.0.0'
implementation 'com.github.majidarabi:AndroidFilePicker:0.2.1'
// Preferences DataStore
implementation "androidx.datastore:datastore-preferences:1.0.0"
// Proto DataStore

BIN
app/release/app-release.apk Normal file

Binary file not shown.

View File

@ -0,0 +1,20 @@
{
"version": 3,
"artifactType": {
"type": "APK",
"kind": "Directory"
},
"applicationId": "com.navinfo.volvo",
"variantName": "release",
"elements": [
{
"type": "SINGLE",
"filters": [],
"attributes": [],
"versionCode": 1,
"versionName": "1.0",
"outputFile": "app-release.apk"
}
],
"elementType": "File"
}

View File

@ -10,7 +10,7 @@ import java.util.*
class RecorderLifecycleObserver: DefaultLifecycleObserver {
private var mediaRecorder: MediaRecorder? = null
private lateinit var recorderAudioPath: String
private var recorderAudioPath: String = "${SystemConstant.SoundFolder}/${DateUtils.date2Str(Date(), DateUtils.FORMAT_YMDHMS)}.m4a"
fun initAndStartRecorder() {
recorderAudioPath = "${SystemConstant.SoundFolder}/${DateUtils.date2Str(Date(), DateUtils.FORMAT_YMDHMS)}.m4a"
@ -22,17 +22,22 @@ class RecorderLifecycleObserver: DefaultLifecycleObserver {
setOutputFile(recorderAudioPath)
try {
prepare()
start()
} catch (e: Exception) {
XLog.e("prepare() failed")
}
start()
}
}
fun stopAndReleaseRecorder(): String {
mediaRecorder?.stop()
mediaRecorder?.release()
mediaRecorder = null
try {
mediaRecorder?.stop()
} catch (exception: Exception) {
XLog.e(exception.message)
} finally {
mediaRecorder?.release()
mediaRecorder = null
}
return recorderAudioPath
}

View File

@ -4,8 +4,6 @@ import android.os.Parcelable
import androidx.room.Entity
import androidx.room.PrimaryKey
import androidx.room.TypeConverters
import kotlinx.android.parcel.Parcelize
import org.jetbrains.annotations.NotNull
@Entity(tableName = "GreetingMessage")
@TypeConverters(AttachmentConverters::class)
@ -37,7 +35,7 @@ data class GreetingMessage @JvmOverloads constructor(
var sendVins: String? = "",
var sendType: String? = "",
var del: String? = "",
var version: String? = "",
var version: String? = "1",
// /**
// * 附件列表
// */

View File

@ -0,0 +1,3 @@
package com.navinfo.volvo.model
data class VolvoModel(val version: String, val model: String, val num:String)

View File

@ -13,6 +13,7 @@ import android.widget.AdapterView
import android.widget.AdapterView.OnItemSelectedListener
import android.widget.ArrayAdapter
import android.widget.Toast
import androidx.core.content.ContextCompat
import androidx.core.widget.addTextChangedListener
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
@ -29,6 +30,13 @@ import com.easytools.tools.ResourceUtils
import com.easytools.tools.ThreadPoolUtils.runOnUiThread
import com.easytools.tools.ToastUtils
import com.elvishew.xlog.XLog
import com.github.file_picker.FileType
import com.github.file_picker.ListDirection
import com.github.file_picker.adapter.FilePickerAdapter
import com.github.file_picker.data.model.Media
import com.github.file_picker.extension.showFilePicker
import com.github.file_picker.listener.OnItemClickListener
import com.github.file_picker.listener.OnSubmitClickListener
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.gredicer.datetimepicker.DateTimePickerFragment
import com.hjq.permissions.OnPermissionCallback
@ -41,6 +49,7 @@ import com.navinfo.volvo.database.entity.AttachmentType
import com.navinfo.volvo.database.entity.GreetingMessage
import com.navinfo.volvo.databinding.FragmentObtainMessageBinding
import com.navinfo.volvo.http.DownloadCallback
import com.navinfo.volvo.model.VolvoModel
import com.navinfo.volvo.ui.markRequiredInRed
import com.navinfo.volvo.util.PhotoLoader
import com.navinfo.volvo.utils.EasyMediaFile
@ -55,6 +64,7 @@ import top.zibin.luban.OnCompressListener
import java.io.File
import java.io.FileInputStream
import java.util.*
import kotlin.streams.toList
@AndroidEntryPoint
@ -70,6 +80,7 @@ class ObtainMessageFragment : Fragment() {
private val dateSendFormat = "yyyy-MM-dd HH:mm:ss"
private val dateShowFormat = "yyyy-MM-dd HH:mm"
private var startRecordTime = System.currentTimeMillis()
// This property is only valid between onCreateView and
// onDestroyView.
@ -155,12 +166,11 @@ class ObtainMessageFragment : Fragment() {
binding.layerAudioResult.visibility = if (hasAudio) VISIBLE else GONE
binding.layerGetAudio.visibility = if (hasAudio) GONE else VISIBLE
// binding.llAudioPlay.visibility = if (hasAudio) VISIBLE else GONE
if (!hasAudio) {
binding.llAudioPlay.visibility = GONE
}
}
)
lifecycle.addObserver(recorderLifecycleObserver)
initView()
return root
@ -184,15 +194,12 @@ class ObtainMessageFragment : Fragment() {
binding.imgAudioDelete.setOnClickListener {
obtainMessageViewModel.updateMessageAudio("")
}
val sendToArray = mutableListOf<String>("LYVXFEFEXNL754427")
binding.edtSendTo.adapter = ArrayAdapter<String>(
context!!,
android.R.layout.simple_dropdown_item_1line, android.R.id.text1, sendToArray
)
binding.edtSendTo.onItemSelectedListener = object : OnItemSelectedListener {
val sendToArray = mutableListOf<VolvoModel>(VolvoModel("XC60", "智雅", "LYVXFEFEXNL754427"))
binding.edtSendTo.adapter = ArrayAdapter<String>(requireContext(),
android.R.layout.simple_dropdown_item_1line, android.R.id.text1, sendToArray.stream().map { it -> "${it.version} ${it.model} ${it.num}" }.toList())
binding.edtSendTo.onItemSelectedListener = object: OnItemSelectedListener {
override fun onItemSelected(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) {
obtainMessageViewModel.getMessageLiveData().value?.toWho = sendToArray[p2]
obtainMessageViewModel.getMessageLiveData().value?.toWho = sendToArray[p2].num
}
override fun onNothingSelected(p0: AdapterView<*>?) {
@ -242,14 +249,14 @@ class ObtainMessageFragment : Fragment() {
return
}
// 开始启动拍照界面
photoHelper.setCrop(true).takePhoto(activity!!)
photoHelper.setCrop(true).takePhoto(requireActivity())
}
override fun onDenied(permissions: MutableList<String>, never: Boolean) {
if (never) {
Toast.makeText(activity, "永久拒绝授权,请手动授权拍照权限", Toast.LENGTH_SHORT).show()
// 如果是被永久拒绝就跳转到应用权限系统设置页面
XXPermissions.startPermissionActivity(context!!, permissions)
XXPermissions.startPermissionActivity(requireContext(), permissions)
} else {
onCameraDenied()
showRationaleForCamera(permissions)
@ -260,13 +267,56 @@ class ObtainMessageFragment : Fragment() {
}
binding.btnStartPhoto.setOnClickListener {
photoHelper.setCrop(true).selectPhoto(activity!!)
photoHelper.setCrop(true).selectPhoto(requireActivity())
}
// 用户选择录音文件
binding.btnSelectSound.setOnClickListener {
photoHelper.setCrop(false).selectAudio(activity!!)
// SingleAudioPicker.showPicker(context!!) {
// photoHelper.setCrop(false).selectAudio(requireActivity())
showFilePicker(
submitText = "确认",
fileType = FileType.AUDIO,
title = "选择音频文件",
cancellable = true,
listDirection = ListDirection.RTL,
accentColor = ContextCompat.getColor(requireContext(), R.color.purple_700),
titleTextColor = ContextCompat.getColor(requireContext(), R.color.purple_700),
onSubmitClickListener = object : OnSubmitClickListener {
override fun onClick(files: List<Media>) {
// Do something here with selected files
val audioFile = files.get(0).file
if (!audioFile.parentFile.parentFile.absolutePath.equals(SystemConstant.SoundFolder)) {
val copyResult = FileIOUtils.writeFileFromIS(File(SystemConstant.SoundFolder, audioFile.name), FileInputStream(audioFile))
XLog.e("拷贝结果:"+copyResult)
if (!copyResult) {
ToastUtils.showToast("无法访问该文件,请重新选择其他文件")
return
}
obtainMessageViewModel.updateMessageAudio(File(SystemConstant.SoundFolder, audioFile.name).absolutePath)
} else {
obtainMessageViewModel.updateMessageAudio(audioFile.absolutePath)
}
}
},
onItemClickListener = object : OnItemClickListener {
override fun onClick(media: Media, position: Int, adapter: FilePickerAdapter) {
if (!media.file.isDirectory) {
if (!media.file.name.endsWith(".m4a")) {
ToastUtils.showToast("只能选择.m4a文件")
return
}
if (media.file.length()>2*1000*1000) {
ToastUtils.showToast("文件不能超过2M")
return
}
adapter.setSelected(position)
}
}
}
)
// SingleAudioPicker.showPicker(requireContext()) {
// val audioFile = File(it.contentUri.path)
// ToastUtils.showToast(audioFile.absolutePath)
// if (!audioFile.parentFile.parentFile.absolutePath.equals(SystemConstant.SoundFolder)) {
@ -295,12 +345,16 @@ class ObtainMessageFragment : Fragment() {
MotionEvent.ACTION_DOWN -> {
// 申请权限
recorderLifecycleObserver.initAndStartRecorder()
ToastUtils.showToast("开始录音!")
startRecordTime = System.currentTimeMillis()
false
}
MotionEvent.ACTION_UP -> {
val recorderAudioPath =
if (System.currentTimeMillis() - startRecordTime<2000) {
ToastUtils.showToast("录音时间太短!")
recorderLifecycleObserver.stopAndReleaseRecorder()
return
}
val recorderAudioPath = recorderLifecycleObserver.stopAndReleaseRecorder()
if (File(recorderAudioPath).exists()) {
obtainMessageViewModel.updateMessageAudio(recorderAudioPath)
}
@ -316,7 +370,7 @@ class ObtainMessageFragment : Fragment() {
if (never) {
Toast.makeText(activity, "永久拒绝授权,请手动授权拍照权限", Toast.LENGTH_SHORT).show()
// 如果是被永久拒绝就跳转到应用权限系统设置页面
XXPermissions.startPermissionActivity(context!!, permissions)
XXPermissions.startPermissionActivity(requireContext(), permissions)
} else {
onCameraDenied()
showRationaleForCamera(permissions)
@ -531,7 +585,7 @@ class ObtainMessageFragment : Fragment() {
localAttachmentList.add(audioAttachment)
}
if (localAttachmentList.isNotEmpty()) {
MaterialAlertDialogBuilder(context!!)
MaterialAlertDialogBuilder(requireContext())
.setTitle("提示")
.setMessage("当前照片及音频内容需首先上传,是否尝试上传?")
.setPositiveButton(
@ -558,10 +612,13 @@ class ObtainMessageFragment : Fragment() {
val sendDate = DateUtils.str2Date(messageData?.sendDate, dateSendFormat)
val cal = Calendar.getInstance()
cal.time = Date()
cal.set(Calendar.MINUTE, cal.get(Calendar.MINUTE) + 1)
if (cal.time.time < sendDate.time) { // 发送时间设置小于当前时间1分钟前Toast提示用户并自动设置发送时间
cal.set(Calendar.MINUTE, cal.get(Calendar.MINUTE)+1)
if (sendDate.time < cal.time.time) { // 发送时间设置小于当前时间1分钟后Toast提示用户并自动设置发送时间
messageData?.sendDate = DateUtils.date2Str(cal.time, dateSendFormat)
ToastUtils.showToast("自动调整发送时间为1分钟后发送")
messageData.version = "1" // 立即发送
} else {
messageData.version = "0" // 预约发送
}
// 开始网络提交数据
@ -610,12 +667,12 @@ class ObtainMessageFragment : Fragment() {
fun showRationaleForCamera(permissions: MutableList<String>) {
// showRationaleDialog(R.string.permission_camera_rationale, request)
// Toast.makeText(context, "当前操作需要您授权相机权限!", Toast.LENGTH_SHORT).show()
MaterialAlertDialogBuilder(context!!)
MaterialAlertDialogBuilder(requireContext())
.setTitle("提示")
.setMessage("当前操作需要您授权拍摄权限!")
.setPositiveButton("确定", DialogInterface.OnClickListener { dialogInterface, i ->
dialogInterface.dismiss()
XXPermissions.startPermissionActivity(activity!!, permissions)
XXPermissions.startPermissionActivity(requireActivity(), permissions)
})
.show()
}
@ -626,16 +683,15 @@ class ObtainMessageFragment : Fragment() {
}
fun showRationaleForRecorder(permissions: MutableList<String>) {
MaterialAlertDialogBuilder(context!!)
MaterialAlertDialogBuilder(requireContext())
.setTitle("提示")
.setMessage("当前操作需要您授权录音权限!")
.setPositiveButton("确定", DialogInterface.OnClickListener { dialogInterface, i ->
dialogInterface.dismiss()
XXPermissions.startPermissionActivity(activity!!, permissions)
XXPermissions.startPermissionActivity(requireActivity(), permissions)
})
.show()
}
fun onRecorderDenied() {
ToastUtils.showToast("当前操作需要您授权录音权限!")
}

View File

@ -177,6 +177,7 @@ class ObtainMessageViewModel @Inject constructor(
}
} else {
ToastUtils.showToast(result.msg)
XLog.d(result.msg)
}
} catch (e: Exception) {
ToastUtils.showToast(e.message)
@ -250,7 +251,8 @@ class ObtainMessageViewModel @Inject constructor(
"mediaUrl" to message?.mediaUrl,
"who" to message?.who,
"toWho" to message?.toWho,
"sendDate" to message?.sendDate
"sendDate" to message?.sendDate,
"version" to message?.version
)
val result =
NavinfoVolvoCall.getApi().insertCardByApp(insertData as Map<String, String>)
@ -283,7 +285,8 @@ class ObtainMessageViewModel @Inject constructor(
"mediaUrl" to message?.mediaUrl,
"who" to message?.who,
"toWho" to message?.toWho,
"sendDate" to message?.sendDate
"sendDate" to message?.sendDate,
"version" to message?.version
)
val result =
NavinfoVolvoCall.getApi().updateCardByApp(updateData as Map<String, String>)

View File

@ -373,7 +373,7 @@
android:layout_height="wrap_content"
style="@style/Widget.Material3.Button.ElevatedButton"
app:icon="@drawable/ic_baseline_access_time_24"
android:text="现在"
android:text="选择时间"
android:padding="@dimen/default_widget_padding"></com.google.android.material.button.MaterialButton>
</LinearLayout>
<com.nhaarman.supertooltips.ToolTipRelativeLayout