CaitlynCodr
CaitlynCodr

Reputation: 328

setSpeakerphoneOn from AudioManager is not changing speakerphone value on android 12, it always remains false. Why?

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

Answers (4)

FrankKrumnow
FrankKrumnow

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

kunal khedkar
kunal khedkar

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

notmystyle
notmystyle

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

Shivam Sharma
Shivam Sharma

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

Related Questions