Android Question Speakerphone On SDK30

Philip Prins

Active Member
Licensed User
Longtime User
Hello everyone,

The old method of turning the speakerphone on during a call doesn.t work anymore:
B4X:
Dim rr As Reflector
    rr.Target = rr.GetContext
    rr.Target = rr.RunMethod2("getSystemService", "audio", "java.lang.String")
    rr.RunMethod2("setSpeakerphoneOn", value, "java.lang.boolean")

I found this link but how to integrate this in B4A?


https://developer.android.com/refer...nicationDevice(android.media.AudioDeviceInfo)

Any help is highly appreciated,

Philip
 
Solution
I made this code using java inline b4a, test it to see if it works correctly.

Speakerphone:
'Add Permisson MainFast
''AddPermission(android.permission.MODIFY_AUDIO_SETTINGS)

Sub Process_Globals
    '
End Sub

Sub Globals
    Dim btnToggle As Button
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Inicializa a interface
    Activity.LoadLayout("Layout")
  
    btnToggle.Initialize("btnToggle")
    btnToggle.Text = "Toggle Speakerphone"
    Activity.AddView(btnToggle, 10dip, 10dip, 200dip, 50dip)
End Sub

Sub Activity_Resume
    '
End Sub

Sub Activity_Pause (UserClosed As Boolean)
    '
End Sub

'Função para obter o nível da API do dispositivo
Sub GetDeviceApiLevel As Int
    Dim jo As JavaObject...

Flavio SOuza

Member
Licensed User
Longtime User
I made this code using java inline b4a, test it to see if it works correctly.

Speakerphone:
'Add Permisson MainFast
''AddPermission(android.permission.MODIFY_AUDIO_SETTINGS)

Sub Process_Globals
    '
End Sub

Sub Globals
    Dim btnToggle As Button
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Inicializa a interface
    Activity.LoadLayout("Layout")
  
    btnToggle.Initialize("btnToggle")
    btnToggle.Text = "Toggle Speakerphone"
    Activity.AddView(btnToggle, 10dip, 10dip, 200dip, 50dip)
End Sub

Sub Activity_Resume
    '
End Sub

Sub Activity_Pause (UserClosed As Boolean)
    '
End Sub

'Função para obter o nível da API do dispositivo
Sub GetDeviceApiLevel As Int
    Dim jo As JavaObject
    jo.InitializeStatic("android.os.Build$VERSION")
    Return jo.GetField("SDK_INT")
End Sub

'Função principal para ativar/desativar o viva-voz
Sub SetSpeakerphoneOn(value As Boolean)
    Dim jo As JavaObject
    jo.InitializeContext
    Dim audioManager As JavaObject = jo.RunMethod("getSystemService", Array("audio"))
  
    If audioManager.IsInitialized Then
        If GetDeviceApiLevel >= 31 Then
            'Android 12+ (API 31+): Usa setCommunicationDevice
            Dim devices As List = audioManager.RunMethod("getAvailableCommunicationDevices", Null)
            Dim audioDeviceInfo As JavaObject
            For Each device As JavaObject In devices
                If device.RunMethod("getType", Null) = 2 Then ' AudioDeviceInfo.TYPE_BUILTIN_SPEAKER = 2
                    audioDeviceInfo = device
                    Exit
                End If
            Next
            If value And audioDeviceInfo.IsInitialized Then
                Dim result As Boolean = audioManager.RunMethod("setCommunicationDevice", Array(audioDeviceInfo))
                Log("setCommunicationDevice result: " & result)
                If Not(result) Then Log("Falha ao ativar o viva-voz")
            Else If Not(value) Then
                audioManager.RunMethod("clearCommunicationDevice", Null)
            End If
        Else
            'Android < 12 (API < 31): Usa setSpeakerphoneOn
            audioManager.RunMethod("setMode", Array(2)) ' MODE_IN_CALL = 2
            audioManager.RunMethod("setSpeakerphoneOn", Array(value))
            Log("setSpeakerphoneOn chamado com valor: " & value)
        End If
    Else
        Log("AudioManager não inicializado")
    End If
End Sub

'Evento do botão para alternar o viva-voz
Sub btnToggle_Click
    Dim isOn As Boolean = Not(IsSpeakerphoneOn)
    SetSpeakerphoneOn(isOn)
    btnToggle.Text = "Toggle Speakerphone (" & IIf(isOn, "ON", "OFF") & ")"
End Sub

'Função para verificar o estado atual do viva-voz
Sub IsSpeakerphoneOn As Boolean
    Dim jo As JavaObject
    jo.InitializeContext
    Dim audioManager As JavaObject = jo.RunMethod("getSystemService", Array("audio"))
    If audioManager.IsInitialized Then
        Return audioManager.RunMethod("isSpeakerphoneOn", Null)
    Else
        Log("AudioManager não inicializado")
        Return False
    End If
Fim Sub[/CÓDIGO]

-----
  1. Replacement of Reflector with JavaObject:
    • The use of Reflector was replaced with JavaObject, which is more accurate and resolved the reflection error (method not found in the wrong object like File$InputStreamWrapper).
  2. Correct context initialization:
    • In the old code, rr.GetContext was unstable; in the new version, jo.InitializeContext was used to ensure a valid context from the activity.
  3. Compatibility with Android versions:
    • Added an API Level check (GetDeviceApiLevel) to switch between setSpeakerphoneOn (API < 31) and setCommunicationDevice (API >= 31), since the old method was deprecated in Android 12.
  4. Implementation of conditional logic:
    • For API < 31, added setMode(MODE_IN_CALL) for call context.
    • For API >= 31, included a search for TYPE_BUILTIN_SPEAKER and the use of setCommunicationDevice or clearCommunicationDevice.
  5. Robustness and debugging:
    • Added initialization checks (IsInitialized) and logs to track successes or failures.

These changes fixed the error and adapted the code to work across different Android versions.
 
Last edited:
Upvote 0
Solution

Philip Prins

Active Member
Licensed User
Longtime User
I made this code using java inline b4a, test it to see if it works correctly.

Speakerphone:
'Add Permisson MainFast
''AddPermission(android.permission.MODIFY_AUDIO_SETTINGS)

Sub Process_Globals
    '
End Sub

Sub Globals
    Dim btnToggle As Button
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Inicializa a interface
    Activity.LoadLayout("Layout")
   
    btnToggle.Initialize("btnToggle")
    btnToggle.Text = "Toggle Speakerphone"
    Activity.AddView(btnToggle, 10dip, 10dip, 200dip, 50dip)
End Sub

Sub Activity_Resume
    '
End Sub

Sub Activity_Pause (UserClosed As Boolean)
    '
End Sub

'Função para obter o nível da API do dispositivo
Sub GetDeviceApiLevel As Int
    Dim jo As JavaObject
    jo.InitializeStatic("android.os.Build$VERSION")
    Return jo.GetField("SDK_INT")
End Sub

'Função principal para ativar/desativar o viva-voz
Sub SetSpeakerphoneOn(value As Boolean)
    Dim jo As JavaObject
    jo.InitializeContext
    Dim audioManager As JavaObject = jo.RunMethod("getSystemService", Array("audio"))
   
    If audioManager.IsInitialized Then
        If GetDeviceApiLevel >= 31 Then
            'Android 12+ (API 31+): Usa setCommunicationDevice
            Dim devices As List = audioManager.RunMethod("getAvailableCommunicationDevices", Null)
            Dim audioDeviceInfo As JavaObject
            For Each device As JavaObject In devices
                If device.RunMethod("getType", Null) = 2 Then ' AudioDeviceInfo.TYPE_BUILTIN_SPEAKER = 2
                    audioDeviceInfo = device
                    Exit
                End If
            Next
            If value And audioDeviceInfo.IsInitialized Then
                Dim result As Boolean = audioManager.RunMethod("setCommunicationDevice", Array(audioDeviceInfo))
                Log("setCommunicationDevice result: " & result)
                If Not(result) Then Log("Falha ao ativar o viva-voz")
            Else If Not(value) Then
                audioManager.RunMethod("clearCommunicationDevice", Null)
            End If
        Else
            'Android < 12 (API < 31): Usa setSpeakerphoneOn
            audioManager.RunMethod("setMode", Array(2)) ' MODE_IN_CALL = 2
            audioManager.RunMethod("setSpeakerphoneOn", Array(value))
            Log("setSpeakerphoneOn chamado com valor: " & value)
        End If
    Else
        Log("AudioManager não inicializado")
    End If
End Sub

'Evento do botão para alternar o viva-voz
Sub btnToggle_Click
    Dim isOn As Boolean = Not(IsSpeakerphoneOn)
    SetSpeakerphoneOn(isOn)
    btnToggle.Text = "Toggle Speakerphone (" & IIf(isOn, "ON", "OFF") & ")"
End Sub

'Função para verificar o estado atual do viva-voz
Sub IsSpeakerphoneOn As Boolean
    Dim jo As JavaObject
    jo.InitializeContext
    Dim audioManager As JavaObject = jo.RunMethod("getSystemService", Array("audio"))
    If audioManager.IsInitialized Then
        Return audioManager.RunMethod("isSpeakerphoneOn", Null)
    Else
        Log("AudioManager não inicializado")
        Return False
    End If
End Sub
This works,

Gracias
 
Upvote 0
Top