背景
車載應(yīng)用開發(fā)中需要自己實(shí)現(xiàn)不同聲音的音量設(shè)置功能
目前有 媒體音量 電話音量 導(dǎo)航音量 語音音量 和 響鈴音量
車載系統(tǒng)與手機(jī)系統(tǒng)的區(qū)別
車載系統(tǒng)中使用的是 CarAudioManager 傳入 zoneid groupid 來進(jìn)行設(shè)置 其中 groupid 又通過usage來獲取
手機(jī)系統(tǒng)使用的是 AudioManager 傳入 streamtype 來進(jìn)行設(shè)置
groupid 的定義
如果有設(shè)備的話可以直接讀取 設(shè)備文件路徑 vendor/etc/car_audio_configuration.xml
也可以通關(guān)源碼定義文件查看各個(gè)usage對應(yīng)的groupID package/car/service/service/res/xml/car_volume_groups.xml
部分內(nèi)容如下 但是這里其實(shí)沒有明確指明groupid 是多少 一般按照第一個(gè)group id = 0 開始計(jì)算 第二個(gè)groupid = 1 依次類推
<volumeGroups>
<group>
<device address="BUS00_MEDIA">
<context context="music"/>
<context context="main_buffered_carplay"/>
<context context="zeekr_game"/>
<context context="game"/>
</device>
</group>
<group>
<device address="BUS01_SYS_NOTIFICATION">
<context context="notification"/>
<context context="system_sound"/>
<context context="vehicle_status"/>
</device>
</group>
<group>
<device address="BUS02_NAV_GUIDANCE">
<context context="navigation"/>
<context context="alarm"/>
</device>
</group>
<group>
<device address="BUS03_PHONE">
<context context="call"/>
<context context="conference_call"/>
<context context="satellite_call"/>
</device>
</group>
<group>
<device address="BUS04_CALL_RING">
<context context="call_ring"/>
<context context="conference_call_ring"/>
</device>
</group>
<group>
<device address="BUS05_ALERTS">
<context context="voice_command"/>
<context context="siri_carplay"/>
</device>
</group>
<group>
<device address="BUS11_OUTER_SPEAKER_PLAYBACK">
<context context="announcement"/>
</device>
</group>
<group>
<device address="BUS12_OUTER_NOTIFY">
<context context="safety"/>
</device>
</group>
<group>
<device address="BUS13_ICC">
<context context="icc"/>
</device>
</group>
<group>
<device address="BUS06_SOUND_BARRIER">
<context context="sound_barrier"/>
</device>
</group>
<group>
<device address="BUS07_ZEEKR_SOUNDSCENE">
<context context="zeekr_soundscene"/>
</device>
</group>
<group>
<device address="BUS10_DWM_TTS">
<context context="emergency"/>
</device>
</group>
<group>
<device address="BUS17_FDHU_REAR_NOTIFICATION">
<context context="system_sound_rear"/>
</device>
</group>
</volumeGroups>
工具類實(shí)現(xiàn)
這里先根據(jù)讀取的配置文件 初始指定了各個(gè)音量的groupid 和 最大音量
后續(xù)會根據(jù)對應(yīng)的api 獲取真正的groupid 和 最大音量
靜音部分邏輯暫未處理
private const val TAG = "CarVolumeManager"
object CarVolumeManager {
// 讀取設(shè)備文件路徑 vendor/etc/car_audio_configuration.xml
// 各個(gè)usage對應(yīng)的groupID 源碼定義文件為 package/car/service/service/res/xml/car_volume_groups.xml
var groupMedia = 0
var groupCall = 3
var groupNavigation = 2
var groupVoice = 5
var groupRing = 4
// 最大值
var mediaVolumeMax = 39
var callVolumeMax = 39
var naviVolumeMax = 39
var voiceVolumeMax = 39
var ringVolumeMax = 39
private var mCarAudioManager: CarAudioManager? = null
private var mCar: Car? = null
private var mMediaVolume = MutableLiveData<Int>(0)
private var mNaviVolume = MutableLiveData<Int>(0)
private var mVoiceVolume = MutableLiveData<Int>(0)
private var mCallVolume = MutableLiveData<Int>(0)
private var mRingVolume = MutableLiveData<Int>(0)
private var mAlarmVolume = MutableLiveData<Int>(0)
// 暴露給外部監(jiān)聽
val mediaVolume: LiveData<Int>
get() = mMediaVolume
val naviVolume: LiveData<Int>
get() = mNaviVolume
val voiceVolume: LiveData<Int>
get() = mVoiceVolume
val callVolume: LiveData<Int>
get() = mCallVolume
val ringVolume: LiveData<Int>
get() = mRingVolume
val alarmVolume: LiveData<Int>
get() = mAlarmVolume
fun init(context: Context) {
mCar = Car.createCar(context)
if (mCar != null) {
mCarAudioManager = mCar?.getCarManager(Car.AUDIO_SERVICE) as CarAudioManager
initGroupId()
initVolume()
mCarAudioManager?.registerCarVolumeCallback(object :
CarAudioManager.CarVolumeCallback() {
override fun onGroupMuteChanged(zoneId: Int, groupId: Int, flags: Int) {
super.onGroupMuteChanged(zoneId, groupId, flags)
}
override fun onGroupVolumeChanged(zoneId: Int, groupId: Int, flags: Int) {
super.onGroupVolumeChanged(zoneId, groupId, flags)
val volume = getVolume(groupId)
when (groupId) {
groupMedia -> {
mMediaVolume.postValue(volume)
}
groupCall -> {
mCallVolume.postValue(volume)
}
groupNavigation -> {
mNaviVolume.postValue(volume)
}
groupVoice -> {
mVoiceVolume.postValue(volume)
}
groupRing -> {
mRingVolume.postValue(volume)
}
}
}
override fun onMasterMuteChanged(zoneId: Int, flags: Int) {
super.onMasterMuteChanged(zoneId, flags)
}
})
}
}
// 初始化各個(gè)音源的groupID
fun initGroupId() {
mCarAudioManager?.apply {
groupMedia = getVolumeGroupIdForUsage(AudioAttributes.USAGE_MEDIA)
groupCall = getVolumeGroupIdForUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
groupNavigation =
getVolumeGroupIdForUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE)
groupRing = getVolumeGroupIdForUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
groupVoice = getVolumeGroupIdForUsage(AudioAttributes.USAGE_ASSISTANT)
Log.d(
TAG, """
initGroupId: groupMedia=$groupMedia groupCall=$groupCall
groupNavigation=$groupNavigation groupRing=$groupRing groupVoice=$groupVoice
""".trimIndent()
)
}
}
fun isFeatureAutoMotive(context: Context): Boolean {
val result =
context.packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)
Log.d(TAG, "isFeatureAutoMotive: $result")
return result
}
// 初始音量
fun initVolume() {
mMediaVolume.value = getVolume(groupMedia)
mCallVolume.value = getVolume(groupCall)
mNaviVolume.value = getVolume(groupNavigation)
mVoiceVolume.value = getVolume(groupVoice)
mRingVolume.value = getVolume(groupRing)
// 獲取每個(gè) Group 的最大音量
mediaVolumeMax = getGroupMaxVolume(groupMedia)
callVolumeMax = getGroupMaxVolume(groupNavigation)
naviVolumeMax = getGroupMaxVolume(groupVoice)
voiceVolumeMax = getGroupMaxVolume(groupCall)
ringVolumeMax = getGroupMaxVolume(groupRing)
}
// 獲取音量最大值
fun getGroupMaxVolume(groupId: Int): Int {
var volumeMax = 100
if (mCarAudioManager == null) {
Log.d(TAG, "getGroupMaxVolume: audioManager is null")
} else {
volumeMax = mCarAudioManager?.getGroupMaxVolume(groupId) ?: 100
}
Log.d(TAG, "getGroupMaxVolume: groupId:$groupId volumeMax:$volumeMax")
return volumeMax
}
// 獲取音量
fun getVolume(groupId: Int): Int {
var volume = 0
if (mCarAudioManager == null) {
Log.d(TAG, "getVolume: audioManager is null")
} else {
volume = mCarAudioManager?.getGroupVolume(groupId) ?: 0
}
Log.d(TAG, "getVolume: groupId:$groupId volume:$volume")
return volume
}
// 設(shè)置音量
fun setVolume(groupId: Int, volume: Int) {
Log.d(TAG, "setVolume: groupId:$groupId volume:$volume")
if (mCarAudioManager == null) {
Log.d(TAG, "setVolume: audioManager is null")
} else {
mCarAudioManager?.setGroupVolume(groupId, volume, 0)
}
}
}