|
|
@ -3,6 +3,7 @@ package com.yunqiinnovation.azure_speech.tools |
|
|
import android.content.Context |
|
|
import android.content.Context |
|
|
import android.media.AudioAttributes |
|
|
import android.media.AudioAttributes |
|
|
import android.media.AudioDeviceInfo |
|
|
import android.media.AudioDeviceInfo |
|
|
|
|
|
import android.media.AudioFocusRequest |
|
|
import android.media.AudioFormat |
|
|
import android.media.AudioFormat |
|
|
import android.media.AudioManager |
|
|
import android.media.AudioManager |
|
|
import android.media.AudioTrack |
|
|
import android.media.AudioTrack |
|
|
@ -49,6 +50,20 @@ class SimpleAudioPlayer(private val context: Context? = null) { |
|
|
|
|
|
|
|
|
// 推送流 |
|
|
// 推送流 |
|
|
private var pushOutputStream: PushAudioOutputStream? = null |
|
|
private var pushOutputStream: PushAudioOutputStream? = null |
|
|
|
|
|
|
|
|
|
|
|
// AudioFocus |
|
|
|
|
|
private var audioFocusRequest: AudioFocusRequest? = null |
|
|
|
|
|
private val audioFocusChangeListener = AudioManager.OnAudioFocusChangeListener { focusChange -> |
|
|
|
|
|
when (focusChange) { |
|
|
|
|
|
AudioManager.AUDIOFOCUS_LOSS, |
|
|
|
|
|
AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> { |
|
|
|
|
|
lock.withLock { audioTrack?.pause() } |
|
|
|
|
|
} |
|
|
|
|
|
AudioManager.AUDIOFOCUS_GAIN -> { |
|
|
|
|
|
lock.withLock { if (isPlaying) audioTrack?.play() } |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// 自定义推送流回调 |
|
|
// 自定义推送流回调 |
|
|
private inner class AudioOutputCallback : PushAudioOutputStreamCallback() { |
|
|
private inner class AudioOutputCallback : PushAudioOutputStreamCallback() { |
|
|
@ -235,10 +250,13 @@ class SimpleAudioPlayer(private val context: Context? = null) { |
|
|
configureAudioRouting(isBluetoothConnected) |
|
|
configureAudioRouting(isBluetoothConnected) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 请求 AudioFocus,让外部音乐暂停 |
|
|
|
|
|
requestAudioFocus() |
|
|
|
|
|
|
|
|
// 开始播放 |
|
|
// 开始播放 |
|
|
audioTrack?.play() |
|
|
audioTrack?.play() |
|
|
isPlaying = true |
|
|
isPlaying = true |
|
|
|
|
|
|
|
|
FileLogger.d(TAG, "AudioTrack开始播放") |
|
|
FileLogger.d(TAG, "AudioTrack开始播放") |
|
|
} |
|
|
} |
|
|
} catch (e: Exception) { |
|
|
} catch (e: Exception) { |
|
|
@ -257,7 +275,8 @@ class SimpleAudioPlayer(private val context: Context? = null) { |
|
|
audioTrack?.pause() |
|
|
audioTrack?.pause() |
|
|
audioTrack?.flush() |
|
|
audioTrack?.flush() |
|
|
isPlaying = false |
|
|
isPlaying = false |
|
|
|
|
|
abandonAudioFocus() |
|
|
|
|
|
|
|
|
FileLogger.d(TAG, "AudioTrack停止播放") |
|
|
FileLogger.d(TAG, "AudioTrack停止播放") |
|
|
} |
|
|
} |
|
|
} catch (e: Exception) { |
|
|
} catch (e: Exception) { |
|
|
@ -298,7 +317,10 @@ class SimpleAudioPlayer(private val context: Context? = null) { |
|
|
|
|
|
|
|
|
isPlaying = false |
|
|
isPlaying = false |
|
|
isReleased = true |
|
|
isReleased = true |
|
|
|
|
|
|
|
|
|
|
|
// 放弃 AudioFocus,让外部音乐恢复 |
|
|
|
|
|
abandonAudioFocus() |
|
|
|
|
|
|
|
|
FileLogger.d(TAG, "AudioTrack释放资源") |
|
|
FileLogger.d(TAG, "AudioTrack释放资源") |
|
|
} |
|
|
} |
|
|
} catch (e: Exception) { |
|
|
} catch (e: Exception) { |
|
|
@ -310,7 +332,41 @@ class SimpleAudioPlayer(private val context: Context? = null) { |
|
|
* 是否正在播放 |
|
|
* 是否正在播放 |
|
|
*/ |
|
|
*/ |
|
|
fun isPlaying(): Boolean = isPlaying |
|
|
fun isPlaying(): Boolean = isPlaying |
|
|
|
|
|
|
|
|
|
|
|
private fun requestAudioFocus() { |
|
|
|
|
|
val am = audioManager ?: return |
|
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { |
|
|
|
|
|
val attrs = AudioAttributes.Builder() |
|
|
|
|
|
.setUsage(AudioAttributes.USAGE_MEDIA) |
|
|
|
|
|
.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH) |
|
|
|
|
|
.build() |
|
|
|
|
|
val req = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK) |
|
|
|
|
|
.setAudioAttributes(attrs) |
|
|
|
|
|
.setOnAudioFocusChangeListener(audioFocusChangeListener) |
|
|
|
|
|
.build() |
|
|
|
|
|
audioFocusRequest = req |
|
|
|
|
|
am.requestAudioFocus(req) |
|
|
|
|
|
} else { |
|
|
|
|
|
@Suppress("DEPRECATION") |
|
|
|
|
|
am.requestAudioFocus( |
|
|
|
|
|
audioFocusChangeListener, |
|
|
|
|
|
AudioManager.STREAM_MUSIC, |
|
|
|
|
|
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK |
|
|
|
|
|
) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private fun abandonAudioFocus() { |
|
|
|
|
|
val am = audioManager ?: return |
|
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { |
|
|
|
|
|
audioFocusRequest?.let { am.abandonAudioFocusRequest(it) } |
|
|
|
|
|
audioFocusRequest = null |
|
|
|
|
|
} else { |
|
|
|
|
|
@Suppress("DEPRECATION") |
|
|
|
|
|
am.abandonAudioFocus(audioFocusChangeListener) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* 写入音频数据 |
|
|
* 写入音频数据 |
|
|
* 内部方法,由PushAudioOutputStreamCallback调用 |
|
|
* 内部方法,由PushAudioOutputStreamCallback调用 |
|
|
|