[Modify]声音签名功能完善

This commit is contained in:
wushaocheng
2023-01-07 15:37:40 +08:00
parent 99cc60b4f4
commit d5c2d4552a
8 changed files with 241 additions and 27 deletions

View File

@@ -6,6 +6,7 @@ import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.drawable.Drawable
import android.os.SystemClock
import android.util.Log
import android.view.View
import android.widget.Chronometer
import android.widget.Chronometer.OnChronometerTickListener
@@ -19,8 +20,15 @@ import com.yizhuan.erban.audio.viewmodel.SoundViewModel
import com.yizhuan.erban.base.BaseViewBindingActivity
import com.yizhuan.erban.common.widget.dialog.DialogManager.OkCancelDialogListener
import com.yizhuan.erban.databinding.ActivitySoundSignatureBinding
import com.yizhuan.erban.ui.widget.dialog.CommonTipDialog
import com.yizhuan.xchat_android_core.file.FileModel
import com.yizhuan.xchat_android_core.room.model.AvRoomModel
import com.yizhuan.xchat_android_core.statistic.StatisticManager
import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol
import com.yizhuan.xchat_android_library.utils.ResUtil
import com.yizhuan.xchat_android_library.utils.SingleToastUtil
import io.reactivex.SingleObserver
import io.reactivex.disposables.Disposable
import java.util.*
/**
@@ -31,7 +39,6 @@ class SoundSignatureActivity : BaseViewBindingActivity<ActivitySoundSignatureBin
View.OnClickListener {
companion object {
const val EXTRA_VOICE_ID = "voice_id"
const val AUDIO_FILE = "AUDIO_FILE"
const val AUDIO_DURA = "AUDIO_DURA"
const val MIN_RECORD_VOICE_DURATION = 1 // 最少1秒
@@ -101,6 +108,46 @@ class SoundSignatureActivity : BaseViewBindingActivity<ActivitySoundSignatureBin
finishView(it)
}
soundViewModel.saveRecordLiveData.observe(this) {
hideLoad()
StatisticManager.Instance().onEvent(
StatisticsProtocol.EVENT_MY_SOUND_RECORD_SAVE,
ResUtil.getString(R.string.audio_presenter_recordingvoicepresenter_02)
)
refreshButtonView(SoundViewModel.STATE_RECORD_SAVE_SUCCESS)
SingleToastUtil.showToast(getString(R.string.update_success))
val intent = Intent()
intent.putExtra(AUDIO_FILE, soundViewModel.audioUrl)
intent.putExtra(AUDIO_DURA, soundViewModel.audioDur)
setResult(RESULT_OK, intent)// 上传声音成功之后退出页面
}
soundViewModel.hideLoadLiveData.observe(this) {
hideLoad()
}
soundViewModel.loadingLiveData.observe(this) { loading ->
if (loading) dialogManager.showProgressDialog(this)
else dialogManager.dismissDialog()
}
soundViewModel.deleteRecordLiveData.observe(this) {
refreshButtonView(SoundViewModel.STATE_RECORD_NORMAL)
}
}
private fun showLoad() {
runOnUiThread {
dialogManager.showProgressDialog(
context,
ResUtil.getString(R.string.erban_audio_recordingvoiceactivity_022)
)
}
}
private fun hideLoad() {
runOnUiThread { dialogManager.dismissDialog() }
}
@SuppressLint("CheckResult")
@@ -125,17 +172,56 @@ class SoundSignatureActivity : BaseViewBindingActivity<ActivitySoundSignatureBin
soundViewModel.clickCenterIcon()
}
R.id.ivSaveRecord -> {//保存按钮
finishRecord()
}
R.id.frDeleteBg -> {//删除按钮
deleteRecord()
}
R.id.frRestartBg -> {//重新录制按钮
soundViewModel.reRecord()
soundViewModel.reRecord()
}
}
}
private fun deleteRecord() {
val tipDialog = CommonTipDialog(this)
tipDialog.setTipMsg(ResUtil.getString(R.string.sure_to_delete_sound))
tipDialog.setOkText(getString(R.string.sure))
tipDialog.setOnActionListener(
object : CommonTipDialog.OnActionListener {
override fun onOk() {
soundViewModel.deleteRecord()
}
}
)
tipDialog.show()
}
/**
* 上传声音,完成录制
*/
private fun finishRecord() {
soundViewModel.audioFile?.let {
Log.i("result_url", "upload before:" + it.absolutePath)
showLoad()
FileModel.get()
.uploadFile(it.absolutePath)
.compose(bindToLifecycle())
.subscribe(object : SingleObserver<String> {
override fun onSubscribe(d: Disposable) {}
override fun onSuccess(url: String) {
Log.i("result_url", "upload success:$url")
soundViewModel.saveRecord(url)
}
override fun onError(e: Throwable) {
SingleToastUtil.showToast(ResUtil.getString(R.string.audio_presenter_recordingvoicepresenter_01))
hideLoad()// 声音文件上传失败时
}
})
}
}
private fun refreshButtonView(state: Int) {
when (state) {
SoundViewModel.STATE_RECORD_NORMAL -> {
@@ -151,6 +237,7 @@ class SoundSignatureActivity : BaseViewBindingActivity<ActivitySoundSignatureBin
binding.groupRsRecord.visibility = View.INVISIBLE
binding.groupSaveSound.visibility = View.INVISIBLE
binding.groupDeleteSound.visibility = View.INVISIBLE
binding.tvUnderReview.visibility = View.INVISIBLE
}
SoundViewModel.STATE_RECORD_RECORDING -> {
binding.ivSoundStatus.post { binding.ivSoundStatus.setImageResource(R.drawable.ic_start_record) }
@@ -158,6 +245,7 @@ class SoundSignatureActivity : BaseViewBindingActivity<ActivitySoundSignatureBin
binding.groupRsRecord.visibility = View.INVISIBLE
binding.groupSaveSound.visibility = View.INVISIBLE
binding.groupDeleteSound.visibility = View.INVISIBLE
binding.tvUnderReview.visibility = View.INVISIBLE
}
SoundViewModel.STATE_RECORD_SUCCESS -> {
binding.ivSoundStatus.post { binding.ivSoundStatus.setImageResource(R.drawable.ic_pause_record) }
@@ -165,6 +253,15 @@ class SoundSignatureActivity : BaseViewBindingActivity<ActivitySoundSignatureBin
binding.groupRsRecord.visibility = View.VISIBLE
binding.groupSaveSound.visibility = View.VISIBLE
binding.groupDeleteSound.visibility = View.INVISIBLE
binding.tvUnderReview.visibility = View.INVISIBLE
}
SoundViewModel.STATE_RECORD_SAVE_SUCCESS -> {
binding.ivSoundStatus.post { binding.ivSoundStatus.setImageResource(R.drawable.ic_pause_record) }
binding.tvRecordTip.text = getString(R.string.click_to_listen)
binding.groupRsRecord.visibility = View.VISIBLE
binding.groupSaveSound.visibility = View.INVISIBLE
binding.groupDeleteSound.visibility = View.VISIBLE
binding.tvUnderReview.visibility = View.VISIBLE
}
}
}
@@ -223,6 +320,14 @@ class SoundSignatureActivity : BaseViewBindingActivity<ActivitySoundSignatureBin
finish()
}
override fun onLeftClickListener() {
soundViewModel.leaveThePage()
}
override fun onBackPressed() {
onLeftClickListener() // 物理返回
}
override fun onPause() {
super.onPause()
soundViewModel.pausePage()

View File

@@ -13,6 +13,8 @@ import com.yizhuan.erban.audio.helper.OnPlayListener
import com.yizhuan.erban.base.BaseViewModel
import com.yizhuan.xchat_android_core.audio.AudioPlayAndRecordManager
import com.yizhuan.xchat_android_core.manager.AvRoomDataManager
import com.yizhuan.xchat_android_core.sound.model.SoundModel
import com.yizhuan.xchat_android_core.utils.toast
import com.yizhuan.xchat_android_library.common.application.BaseApp
import com.yizhuan.xchat_android_library.utils.ResUtil
import com.yizhuan.xchat_android_library.utils.SingleToastUtil
@@ -31,15 +33,16 @@ class SoundViewModel : BaseViewModel() {
const val STATE_RECORD_NORMAL = 0//普通状态
const val STATE_RECORD_RECORDING = 1//录音中
const val STATE_RECORD_SUCCESS = 2//录音完成
const val STATE_RECORD_SAVE_SUCCESS = 3//保存成功
}
private var audioState = STATE_RECORD_NORMAL
private var audioManager: AudioPlayAndRecordManager ?= null
private var audioManager: AudioPlayAndRecordManager? = null
private var audioRecorder: AudioRecorder? = null
private var audioFile: File? = null
private var audioDur = 0
private var audioUrl: String? = null
var audioFile: File? = null
var audioDur = 0
var audioUrl: String? = null
private val _showConfirmLiveData = MutableLiveData<String?>()
val showConfirmLiveData: MutableLiveData<String?> = _showConfirmLiveData
@@ -62,6 +65,15 @@ class SoundViewModel : BaseViewModel() {
private val _finishViewLiveData = MutableLiveData<Intent?>()
val finishViewLiveData: MutableLiveData<Intent?> = _finishViewLiveData
private val _hideLoadLiveData = MutableLiveData<String?>()
val hideLoadLiveData: MutableLiveData<String?> = _hideLoadLiveData
private val _saveRecordLiveData = MutableLiveData<String?>()
val saveRecordLiveData: MutableLiveData<String?> = _saveRecordLiveData
private val _deleteRecordLiveData = MutableLiveData<String?>()
val deleteRecordLiveData: MutableLiveData<String?> = _deleteRecordLiveData
init {
audioManager = AudioPlayAndRecordManager.getInstance()
}
@@ -156,9 +168,9 @@ class SoundViewModel : BaseViewModel() {
/**
* 显示默认状态,即初始状态
*/
private fun showNormalState() {
fun showNormalState() {
audioState = STATE_RECORD_NORMAL
refreshLiveData.value = audioState
_refreshLiveData.value = audioState
if (null != audioRecorder) {
audioRecorder?.destroyAudioRecorder()
audioRecorder = null
@@ -170,7 +182,7 @@ class SoundViewModel : BaseViewModel() {
*/
private fun showRecordSuccessState() {
audioState = STATE_RECORD_SUCCESS
refreshLiveData.value = audioState
_refreshLiveData.value = audioState
}
/**
@@ -214,7 +226,7 @@ class SoundViewModel : BaseViewModel() {
* 离开页面处理
*/
fun leaveThePage() {
if (audioRecorder != null && audioRecorder!!.isRecording) {
if (audioRecorder != null && audioRecorder?.isRecording == true) {
stopRecord() // 录制过程被中断(如点了返回按钮或电话接入等):【自动跳转到试听状态】停止录音
return
}
@@ -256,7 +268,7 @@ class SoundViewModel : BaseViewModel() {
TAG,
"duration = $currDuration"
)
showCountDownLiveData.value = (currDuration / 1000).toInt()
_showCountDownLiveData.value = (currDuration / 1000).toInt()
}
override fun onCompletion() {
@@ -269,4 +281,26 @@ class SoundViewModel : BaseViewModel() {
}
}
fun saveRecord(audioUrl: String, second: Int = audioDur) {
this.audioUrl = audioUrl
safeLaunch(
onError = {
it.message.toast()
_hideLoadLiveData.value = null
},
block = {
_saveRecordLiveData.value = SoundModel.saveRecord(audioUrl, second)
}
)
}
fun deleteRecord() {
safeLaunch(
true,
block = {
_deleteRecordLiveData.value = SoundModel.deleteRecord()
}
)
}
}

View File

@@ -22,9 +22,8 @@ import com.yalantis.ucrop.UCrop
import com.yizhuan.erban.R
import com.yizhuan.erban.UIHelper
import com.yizhuan.erban.application.XChatApplication
import com.yizhuan.erban.audio.RecordingVoiceActivity
import com.yizhuan.erban.audio.SoundSignatureActivity
import com.yizhuan.erban.base.BaseViewBindingActivity
import com.yizhuan.xchat_android_library.common.file.FileHelper
import com.yizhuan.erban.common.util.BitmapUtil
import com.yizhuan.erban.databinding.ActivityUserInfoModifyBinding
import com.yizhuan.erban.ui.login.ModifyInfoActivity
@@ -38,6 +37,7 @@ import com.yizhuan.xchat_android_core.user.UserModel
import com.yizhuan.xchat_android_core.user.bean.UserInfo
import com.yizhuan.xchat_android_core.user.bean.UserPhoto
import com.yizhuan.xchat_android_core.utils.Logger
import com.yizhuan.xchat_android_library.common.file.FileHelper
import com.yizhuan.xchat_android_library.common.photo.PhotoProviderNew
import com.yizhuan.xchat_android_library.common.util.PhotoCompressCallback
import com.yizhuan.xchat_android_library.common.util.PhotoCompressUtil
@@ -249,7 +249,7 @@ class UserInfoModifyActivity : BaseViewBindingActivity<ActivityUserInfoModifyBin
}, R.string.ask_again,
Manifest.permission.RECORD_AUDIO
)
R.id.ll_audio_record ->checkPermission(
R.id.ll_audio_record -> checkPermission(
{
// 点击跳转到声音签名页面
UIHelper.showSoundAct(
@@ -386,16 +386,16 @@ class UserInfoModifyActivity : BaseViewBindingActivity<ActivityUserInfoModifyBin
setResult(RESULT_OK, it)
// 获取数据并刷新显示
audioFileUrl = it.getStringExtra(RecordingVoiceActivity.AUDIO_FILE)
val audioDuration = it.getIntExtra(RecordingVoiceActivity.AUDIO_DURA, 0)
audioFileUrl = it.getStringExtra(SoundSignatureActivity.AUDIO_FILE)
val audioDuration = it.getIntExtra(SoundSignatureActivity.AUDIO_DURA, 0)
// 更新用户信息
val user = UserInfo()
user.uid = AuthModel.get().currentUid
user.userVoice = audioFileUrl
user.voiceDura = audioDuration
UserModel.get().requestUpdateUserInfo(user)
.subscribe(userInfoUpdateObserver)
// // 更新用户信息
// val user = UserInfo()
// user.uid = AuthModel.get().currentUid
// user.userVoice = audioFileUrl
// user.voiceDura = audioDuration
// UserModel.get().requestUpdateUserInfo(user)
// .subscribe(userInfoUpdateObserver)
}
}
Method.PHOTO -> {

View File

@@ -204,4 +204,15 @@
android:layout_height="wrap_content"
app:constraint_referenced_ids="frDeleteBg,tvDeleteSound" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tvUnderReview"
android:text="@string/sound_audit_in_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tvRecordTip"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -22,7 +22,7 @@
android:lineSpacingMultiplier="1.2"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:textColor="@color/color_333333"
android:textColor="@color/text_title_color"
android:textSize="14sp"
tools:text="@string/layout_layout_ok_cancel_dialog_01" />
@@ -53,6 +53,7 @@
android:text="@string/text_ok"
android:textColor="@color/white"
android:textSize="15sp" />
</LinearLayout>
</LinearLayout>

View File

@@ -0,0 +1,45 @@
package com.yizhuan.xchat_android_core.sound.model
import com.yizhuan.xchat_android_core.base.BaseModel
import com.yizhuan.xchat_android_core.bean.response.ServiceResult
import com.yizhuan.xchat_android_core.earn.bean.*
import com.yizhuan.xchat_android_core.home.bean.*
import com.yizhuan.xchat_android_core.utils.net.launchRequest
import com.yizhuan.xchat_android_library.net.rxnet.RxNet
import retrofit2.http.POST
import retrofit2.http.Query
object SoundModel : BaseModel() {
private val api = RxNet.create(Api::class.java)
suspend fun saveRecord(audioUrl: String, second: Int): String? =
launchRequest {
api.saveRecord(audioUrl, second)
}
suspend fun deleteRecord(): String? =
launchRequest {
api.deleteRecord()
}
private interface Api {
/**
* @return
*/
@POST("/audioCard/save")
suspend fun saveRecord(
@Query("audioUrl") audioUrl: String,
@Query("second") second: Int
): ServiceResult<String>
/**
* @return
*/
@POST("/audioCard/del")
suspend fun deleteRecord(): ServiceResult<String>
}
}

View File

@@ -876,7 +876,6 @@ public final class UserModel extends BaseModel implements IUserModel {
@Field("shareChannel") String shareChannel,
@Field("shareUid") String shareUid,
@Field("roomUid") String roomUid,
@Field("signture") String signture,
@Field("userVoice") String userVoice,
@Field("voiceDura") String voiceDura,

View File

@@ -288,6 +288,13 @@ public class UserInfo implements Serializable {
@Setter
private boolean banAccount;
/**
* 声音签名
*/
@Getter
@Setter
private SoundBean soundBean;
/**
* "用户自己的房间是否牌照房"
*/
@@ -809,5 +816,17 @@ public class UserInfo implements Serializable {
private String iconPic;
private String fixedWord;
}
/**
* 声音签名
*/
@Data
public static class SoundBean {
private long uid;
private String audioUrl;//音频七牛云url
private Integer second;//时间
private Integer status;//0=初始状态1=审核中, 2=审核通过3=审核不通过4=被下架)
}
}