Hack to support toggling of speakerphone in Andoid API 31+

This commit is contained in:
Juha Heinanen
2023-01-21 01:08:50 +02:00
parent c2cf2e5d69
commit 1608e6233a
3 changed files with 58 additions and 25 deletions
@@ -880,9 +880,9 @@ class BaresipService: Service() {
if (Call.calls().size == 0) { if (Call.calls().size == 0) {
resetCallVolume() resetCallVolume()
Utils.setSpeakerPhone(am, false) Utils.setSpeakerPhone(am, false)
am.mode = AudioManager.MODE_NORMAL
am.stopBluetoothSco() am.stopBluetoothSco()
abandonAudioFocus() abandonAudioFocus()
am.mode = AudioManager.MODE_NORMAL
proximitySensing(false) proximitySensing(false)
} }
val missed = call.startTime == null && call.dir == "in" && !call.rejected val missed = call.startTime == null && call.dir == "in" && !call.rejected
@@ -1144,12 +1144,12 @@ class MainActivity : AppCompatActivity() {
if (acc.missedCalls) if (acc.missedCalls)
callsButton.setImageResource(R.drawable.calls_missed) callsButton.setImageResource(R.drawable.calls_missed)
} }
if (speakerIcon != null) { Handler(Looper.getMainLooper()).postDelayed({
if (am.isSpeakerphoneOn) if (Utils.isSpeakerPhoneOn(am))
speakerIcon!!.setIcon(R.drawable.speaker_on) speakerIcon!!.setIcon(R.drawable.speaker_on)
else else
speakerIcon!!.setIcon(R.drawable.speaker_off) speakerIcon!!.setIcon(R.drawable.speaker_off)
} }, 750)
if ((Build.VERSION.SDK_INT >= 22 && kgm.isDeviceLocked) || if ((Build.VERSION.SDK_INT >= 22 && kgm.isDeviceLocked) ||
(Build.VERSION.SDK_INT < 22 && kgm.isKeyguardLocked && kgm.isKeyguardSecure)) (Build.VERSION.SDK_INT < 22 && kgm.isKeyguardLocked && kgm.isKeyguardSecure))
Utils.setShowWhenLocked(this, false) Utils.setShowWhenLocked(this, false)
@@ -1208,7 +1208,7 @@ class MainActivity : AppCompatActivity() {
menuInflater.inflate(R.menu.speaker_icon, menu) menuInflater.inflate(R.menu.speaker_icon, menu)
speakerIcon = menu.findItem(R.id.speakerIcon) speakerIcon = menu.findItem(R.id.speakerIcon)
if (am.isSpeakerphoneOn) if (Utils.isSpeakerPhoneOn(am))
speakerIcon!!.setIcon(R.drawable.speaker_on) speakerIcon!!.setIcon(R.drawable.speaker_on)
else else
speakerIcon!!.setIcon(R.drawable.speaker_off) speakerIcon!!.setIcon(R.drawable.speaker_off)
@@ -1234,11 +1234,13 @@ class MainActivity : AppCompatActivity() {
} }
R.id.speakerIcon -> { R.id.speakerIcon -> {
Utils.setSpeakerPhone(am, !am.isSpeakerphoneOn) Utils.toggleSpeakerPhone(am)
if (am.isSpeakerphoneOn) Handler(Looper.getMainLooper()).postDelayed({
item.setIcon(R.drawable.speaker_on) if (Utils.isSpeakerPhoneOn(am))
else item.setIcon(R.drawable.speaker_on)
item.setIcon(R.drawable.speaker_off) else
item.setIcon(R.drawable.speaker_off)
}, 750)
} }
R.id.config -> { R.id.config -> {
+46 -15
View File
@@ -12,9 +12,6 @@ import android.graphics.Canvas
import android.graphics.Color import android.graphics.Color
import android.net.Uri import android.net.Uri
import android.net.wifi.WifiManager import android.net.wifi.WifiManager
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.provider.DocumentsContract import android.provider.DocumentsContract
import android.provider.MediaStore import android.provider.MediaStore
import android.provider.OpenableColumns import android.provider.OpenableColumns
@@ -27,6 +24,7 @@ import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import android.media.AudioDeviceInfo import android.media.AudioDeviceInfo
import android.media.AudioManager import android.media.AudioManager
import android.os.*
import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.ActivityResultLauncher
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
@@ -892,11 +890,19 @@ object Utils {
return bitmap return bitmap
} }
fun setSpeakerPhone(am: AudioManager, state: Boolean) { fun isSpeakerPhoneOn(am: AudioManager): Boolean {
return if (Build.VERSION.SDK_INT >= 31)
am.communicationDevice!!.type == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER
else
am.isSpeakerphoneOn
}
fun setSpeakerPhone(am: AudioManager, enabled: Boolean) {
// Currently at API levels 31+, speakerphone cannot be turned on during call // Currently at API levels 31+, speakerphone cannot be turned on during call
Log.d(TAG, "Speakerphone is ${am.isSpeakerphoneOn}") if (enabled) {
if (state) { if (Build.VERSION.SDK_INT >= 31) {
if (Build.VERSION.SDK_INT >= 31 && am.mode != AudioManager.MODE_IN_COMMUNICATION) { Log.d(TAG, "Setting current device from ${am.communicationDevice!!.type} to " +
"${AudioDeviceInfo.TYPE_BUILTIN_SPEAKER} in mode ${am.mode}")
var speakerDevice: AudioDeviceInfo? = null var speakerDevice: AudioDeviceInfo? = null
for (device in am.availableCommunicationDevices) for (device in am.availableCommunicationDevices)
if (device.type == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER) { if (device.type == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER) {
@@ -904,20 +910,45 @@ object Utils {
break break
} }
if (speakerDevice != null) { if (speakerDevice != null) {
if (!am.setCommunicationDevice(speakerDevice)) am.mode = AudioManager.MODE_NORMAL
Log.e(TAG, "Could not turn on speaker device") Handler(Looper.getMainLooper()).postDelayed({
if (!am.setCommunicationDevice(speakerDevice))
Log.e(TAG, "Could not turn on speaker device")
Log.d(TAG, "Type of current device is ${am.communicationDevice!!.type}")
}, 500)
} }
} else { } else {
if (Build.VERSION.SDK_INT < 31) am.isSpeakerphoneOn = true
am.isSpeakerphoneOn = true Log.d(TAG, "Speakerphone is ${am.isSpeakerphoneOn}")
} }
} else { } else {
if (Build.VERSION.SDK_INT >= 31) if (Build.VERSION.SDK_INT >= 31) {
am.clearCommunicationDevice() Log.d(TAG, "Setting current device from type ${am.communicationDevice!!.type} to " +
else "${AudioDeviceInfo.TYPE_BUILTIN_EARPIECE} in mode ${am.mode}")
var earDevice: AudioDeviceInfo? = null
for (device in am.availableCommunicationDevices)
if (device.type == AudioDeviceInfo.TYPE_BUILTIN_EARPIECE) {
earDevice = device
break
}
if (earDevice != null) {
if (!am.setCommunicationDevice(earDevice))
Log.e(TAG, "Could not turn on earpiece device")
am.mode = AudioManager.MODE_IN_COMMUNICATION
}
Log.d(TAG, "Type of current device is ${am.communicationDevice!!.type}")
} else {
am.isSpeakerphoneOn = false am.isSpeakerphoneOn = false
Log.d(TAG, "Speakerphone is ${am.isSpeakerphoneOn}")
}
} }
Log.d(TAG, "Speakerphone is ${am.isSpeakerphoneOn}")
} }
fun toggleSpeakerPhone(am: AudioManager) {
if (Build.VERSION.SDK_INT >= 31)
setSpeakerPhone(am,
am.communicationDevice!!.type == AudioDeviceInfo.TYPE_BUILTIN_EARPIECE)
else
setSpeakerPhone(am, !am.isSpeakerphoneOn)
}
} }