Reputation: 328
fun toggleSpeaker(context: Context) {
isSpeakerPhoneSelected.value?.let {
val audioManager: AudioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
audioManager.setSpeakerphoneOn = !it
isSpeakerPhoneSelected.value = !it
logDebug(context, it.toString().plus(audioManager.isSpeakerphoneOn.toString()))
}
}
The logger shows that the isSpeakerPhoneSelected value is toggling between true and false but isSpeakerphoneOn always returns false. This stopped working as of Android 12.
These are the versions in our build.gradle:
buildToolsVersion = "29.0.3"
minSdkVersion = 23
compileSdkVersion = 30
targetSdkVersion = 30
supportLibVersion = "28.0.0"
What is causing the isSpeakerphoneOn value not to change and how to fix this? I've been beating my head against the wall over this for some time now so I appreciate any suggestions :p Thanks!
Upvotes: 6
Views: 4669
Reputation: 508
I was really breaking my nerves on this Problem. I see it as a system bug that even setCommunicationDevice would return true BUT DID NOT CHANGE the device.
I only have a solution if you place an outgoing call. On the intent to do the call you can put an extra that will have the default call app activate the speakers for you when it starts the call:
val intent = Intent (Intent.ACTION_CALL)
intent.setData(Uri.parse("tel:$digits"))
intent.putExtra("android.telecom.extra.START_CALL_WITH_SPEAKERPHONE", true)
startActivity(intent)
As stated: this will NOT work for incoming calls and it will not work to switch speakers on or off on a button. But I was already considering to develop my own default dialer app just to have my out call on speakers without the user having to do anything (it is an alert app).
Upvotes: 0
Reputation: 947
Try setting Audio-route along with Communication Device
audioManager.setCommunicationDevice(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER);
connection.setAudioRoute(CallAudioState.ROUTE_SPEAKER);
Check this answer https://stackoverflow.com/a/78146013/9160591
Upvotes: -1
Reputation: 1066
Boiling it down to kotlin (since the question was asked in kotlin):
val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
audioManager.availableCommunicationDevices.firstOrNull { it.type == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER }
?.let {
audioManager.setCommunicationDevice(it)
}
} else {
audioManager.isSpeakerphoneOn = true
}
Upvotes: 0
Reputation: 1045
I've come across the same issue earlier when I set the targetSDKLevel to android 12. I'd a call screen over which I provided a speaker button through which user can turn on/off the speaker.
I used AudioDeviceInfo API for android 12 to set the communication device on audioManager.
public void switchSpeakerState() {
if (isSpeakerOn) {
isSpeakerOn = false;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
Utils.getInstance().setCommunicationDevice(getContext(), AudioDeviceInfo.TYPE_BUILTIN_EARPIECE);
} else {
audioManager.setSpeakerphoneOn(false);
}
ivSpeaker.setImageResource(R.drawable.speaker_outline);
} else {
isSpeakerOn = true;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
Utils.getInstance().setCommunicationDevice(getContext(), AudioDeviceInfo.TYPE_BUILTIN_SPEAKER);
} else {
audioManager.setSpeakerphoneOn(true);
}
ivSpeaker.setImageResource(R.drawable.speaker_filled);
}
}
Utils.java
@RequiresApi(api = Build.VERSION_CODES.S)
public void setCommunicationDevice(Context context, Integer targetDeviceType) {
AudioManager audioManager = (AudioManager) context.getSystemService(AUDIO_SERVICE);
List < AudioDeviceInfo > devices = audioManager.getAvailableCommunicationDevices();
for (AudioDeviceInfo device: devices) {
if (device.getType() == targetDeviceType) {
boolean result = audioManager.setCommunicationDevice(device);
Log.d("result: ", result);
}
}
}
Upvotes: 5