|
|
@@ -26,7 +26,6 @@ import com.adealink.frame.util.onClick
|
|
|
import com.adealink.frame.util.runOnUiThread
|
|
|
import com.adealink.weparty.App
|
|
|
import com.adealink.weparty.R
|
|
|
-import com.adealink.weparty.commonui.ext.dp
|
|
|
import com.adealink.weparty.commonui.ext.show
|
|
|
import com.adealink.weparty.databinding.LayoutSoundViewBinding
|
|
|
import com.adealink.weparty.module.profile.data.VoiceData
|
|
|
@@ -51,19 +50,18 @@ class SoundView @JvmOverloads constructor(
|
|
|
}
|
|
|
|
|
|
data class LoadSoundTask(
|
|
|
- val url: String
|
|
|
+ val voice: VoiceData
|
|
|
)
|
|
|
|
|
|
private val binding = LayoutSoundViewBinding.inflate(LayoutInflater.from(context), this)
|
|
|
|
|
|
- private var durationTextSize = 12.dp()
|
|
|
+ private var durationTextSize = 12
|
|
|
|
|
|
private var showPlayButton: Boolean = true
|
|
|
private var showWave: Boolean = true
|
|
|
|
|
|
- private var soundUrl: String? = null
|
|
|
- private var soundPath: String? = null
|
|
|
- private var soundDuration: Long? = null //单位:毫秒
|
|
|
+ private var voiceData: VoiceData? = null
|
|
|
+ private var soundDuration: Long? = null
|
|
|
|
|
|
private var loadingAnimation: Animation? = null
|
|
|
|
|
|
@@ -80,7 +78,7 @@ class SoundView @JvmOverloads constructor(
|
|
|
val currentPosition =
|
|
|
max((AudioPlayer.getInstance().playPosition / 1000), 1)
|
|
|
binding.tvDuration.text = "${max(soundDuration - currentPosition, 0)}\""
|
|
|
- if (AudioPlayer.getInstance().isPlaying && AudioPlayer.getInstance().path == soundPath) {
|
|
|
+ if (AudioPlayer.getInstance().isPlaying && AudioPlayer.getInstance().path == voiceData?.path) {
|
|
|
sendEmptyMessageDelayed(MSG_UPDATE_PLAY_DURATION, 1000L)
|
|
|
} else {
|
|
|
sendEmptyMessage(MSG_UPDATE_DURATION)
|
|
|
@@ -110,7 +108,7 @@ class SoundView @JvmOverloads constructor(
|
|
|
) {
|
|
|
durationTextSize = getDimensionPixelSize(
|
|
|
R.styleable.SoundView_sound_duration_text_size,
|
|
|
- durationTextSize
|
|
|
+ 12
|
|
|
)
|
|
|
textGravity = getInt(
|
|
|
R.styleable.SoundView_sound_duration_text_gravity,
|
|
|
@@ -142,79 +140,99 @@ class SoundView @JvmOverloads constructor(
|
|
|
}
|
|
|
|
|
|
fun setSoundUrl(url: String?) {
|
|
|
- this.soundUrl = url
|
|
|
- this.soundPath = null
|
|
|
+ this.voiceData = VoiceData(url = url, null)
|
|
|
this.soundDuration = null
|
|
|
stopPlay()
|
|
|
loadSound()
|
|
|
}
|
|
|
|
|
|
- fun setSound(voice: VoiceData?){
|
|
|
-
|
|
|
+ fun setSound(voice: VoiceData?) {
|
|
|
+ this.voiceData = voice
|
|
|
+ stopPlay()
|
|
|
+ loadSound()
|
|
|
}
|
|
|
|
|
|
private fun loadSound() {
|
|
|
- val url = soundUrl
|
|
|
- if (url.isNullOrEmpty()) {
|
|
|
- Log.e(TAG, "playSound fail, url is null")
|
|
|
+ val voiceData = this.voiceData
|
|
|
+ if (voiceData == null || voiceData.isNull()) {
|
|
|
+ Log.d(TAG, "loadSound return, for voiceData is null")
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- downloadSound(
|
|
|
- onFinish = { soundPath ->
|
|
|
- Log.d(TAG, "loadSound, path:$soundPath")
|
|
|
- val loadSoundTask = LoadSoundTask(url)
|
|
|
- MediaPlayer().apply {
|
|
|
- try {
|
|
|
- setDataSource(soundPath)
|
|
|
-
|
|
|
- // 设置准备完成监听器
|
|
|
- setOnPreparedListener { mp ->
|
|
|
- Log.e(TAG, "loadSound, onPrepared")
|
|
|
- if (loadSoundTask.url == soundUrl) {
|
|
|
- soundDuration = mp.duration.toLong()
|
|
|
- Log.e(TAG, "loadSound, url:$soundUrl, duration:$soundDuration")
|
|
|
- handler.sendEmptyMessage(MSG_UPDATE_DURATION)
|
|
|
- }
|
|
|
-
|
|
|
- //释放
|
|
|
- release()
|
|
|
+ fun onDownloadFinish(downloadPath: String) {
|
|
|
+ Log.d(TAG, "loadSound, path:$downloadPath")
|
|
|
+ val loadSoundTask = LoadSoundTask(voiceData)
|
|
|
+ MediaPlayer().apply {
|
|
|
+ try {
|
|
|
+ setDataSource(downloadPath)
|
|
|
+
|
|
|
+ // 设置准备完成监听器
|
|
|
+ setOnPreparedListener { mp ->
|
|
|
+ Log.d(TAG, "loadSound, onPrepared")
|
|
|
+ if (loadSoundTask.voice == this@SoundView.voiceData) {
|
|
|
+ soundDuration = mp.duration.toLong()
|
|
|
+ Log.d(TAG, "loadSound, voice:$voiceData, duration:$soundDuration")
|
|
|
+ handler.sendEmptyMessage(MSG_UPDATE_DURATION)
|
|
|
}
|
|
|
|
|
|
- // 设置错误监听器
|
|
|
- setOnErrorListener { _, what, extra ->
|
|
|
- Log.e(TAG, "loadSound error")
|
|
|
- if (loadSoundTask.url == soundUrl) {
|
|
|
- soundDuration = 0
|
|
|
- handler.sendEmptyMessage(MSG_UPDATE_DURATION)
|
|
|
- }
|
|
|
- false
|
|
|
- }
|
|
|
+ //释放
|
|
|
+ release()
|
|
|
+ }
|
|
|
|
|
|
- setOnCompletionListener {
|
|
|
- release()
|
|
|
+ // 设置错误监听器
|
|
|
+ setOnErrorListener { _, what, extra ->
|
|
|
+ Log.e(TAG, "loadSound error")
|
|
|
+ if (loadSoundTask.voice == this@SoundView.voiceData) {
|
|
|
+ soundDuration = 0
|
|
|
+ handler.sendEmptyMessage(MSG_UPDATE_DURATION)
|
|
|
}
|
|
|
+ false
|
|
|
+ }
|
|
|
|
|
|
- // 异步准备音频
|
|
|
- prepareAsync()
|
|
|
- } catch (e: Exception) {
|
|
|
- Log.d(TAG, "loadSound fail, for ${e.message}", e)
|
|
|
+ setOnCompletionListener {
|
|
|
release()
|
|
|
}
|
|
|
+
|
|
|
+ // 异步准备音频
|
|
|
+ prepareAsync()
|
|
|
+ } catch (e: Exception) {
|
|
|
+ Log.d(TAG, "loadSound fail, for ${e.message}", e)
|
|
|
+ release()
|
|
|
}
|
|
|
}
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ downloadSound(
|
|
|
+ voiceData,
|
|
|
+ onFinish = { soundPath: String ->
|
|
|
+ onDownloadFinish(soundPath)
|
|
|
+ }
|
|
|
)
|
|
|
}
|
|
|
|
|
|
private fun downloadSound(
|
|
|
+ voiceData: VoiceData?,
|
|
|
onStartDownload: (() -> Unit)? = null,
|
|
|
onDownloadProgress: (() -> Unit)? = null,
|
|
|
onFinish: ((soundPath: String) -> Unit)? = null,
|
|
|
onError: (() -> Unit)? = null
|
|
|
) {
|
|
|
- val url = soundUrl
|
|
|
+ if (voiceData == null || voiceData.isNull()) {
|
|
|
+ onError?.invoke()
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ val path = voiceData.path
|
|
|
+ if (!path.isNullOrEmpty()) {
|
|
|
+ onFinish?.invoke(path)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ val url = voiceData.url
|
|
|
if (url.isNullOrEmpty()) {
|
|
|
Log.e(TAG, "downloadSound fail, url is null")
|
|
|
+ onError?.invoke()
|
|
|
return
|
|
|
}
|
|
|
val soundPath = url.getFilePathBy(audioPath, UploadFile.FileType.AUDIO)
|
|
|
@@ -222,7 +240,7 @@ class SoundView @JvmOverloads constructor(
|
|
|
Log.e(TAG, "downloadSound fail, can not getFilePath for $url")
|
|
|
return
|
|
|
}
|
|
|
- this.soundPath = soundPath
|
|
|
+ voiceData.path = soundPath
|
|
|
val soundFile = storageService.file.createWeFile(soundPath)
|
|
|
if (soundFile.exists()) {
|
|
|
Log.d(TAG, "downloadSound return, for sound exists, path:$soundPath")
|
|
|
@@ -270,7 +288,12 @@ class SoundView @JvmOverloads constructor(
|
|
|
}
|
|
|
|
|
|
fun playOrStop() {
|
|
|
+ if (AudioPlayer.getInstance().isPlaying) {
|
|
|
+ stopPlay()
|
|
|
+ return
|
|
|
+ }
|
|
|
downloadSound(
|
|
|
+ voiceData,
|
|
|
onFinish = { soundPath ->
|
|
|
if (AudioPlayer.getInstance().isPlaying && AudioPlayer.getInstance().path == soundPath) {
|
|
|
stopPlay()
|
|
|
@@ -322,7 +345,7 @@ class SoundView @JvmOverloads constructor(
|
|
|
AudioPlayer.getInstance().stopPlay()
|
|
|
AudioPlayer.getInstance().startPlay(soundPath, object : AudioPlayer.Callback {
|
|
|
override fun onCompletion(success: Boolean?) {
|
|
|
- if (isAttachedToWindow && soundPath == this@SoundView.soundPath) {
|
|
|
+ if (isAttachedToWindow && soundPath == this@SoundView.voiceData?.path) {
|
|
|
runOnUiThread {
|
|
|
onStopPlay()
|
|
|
}
|
|
|
@@ -352,11 +375,17 @@ class SoundView @JvmOverloads constructor(
|
|
|
|
|
|
override fun onAttachedToWindow() {
|
|
|
super.onAttachedToWindow()
|
|
|
+ if (isInEditMode) {
|
|
|
+ return
|
|
|
+ }
|
|
|
stopPlay()
|
|
|
}
|
|
|
|
|
|
override fun onDetachedFromWindow() {
|
|
|
super.onDetachedFromWindow()
|
|
|
+ if (isInEditMode) {
|
|
|
+ return
|
|
|
+ }
|
|
|
stopPlay()
|
|
|
}
|
|
|
|