简体   繁体   中英

Android - How to turn on speakerphone and max volume for phone call

I thought that I could turn on speakerphone and set the volume to maximum within PhoneStateListener , but I can't get it to work when I test it. I am using AudioManager to try to turn on the speakerphone and set the volume. Is this not the correct way to do it? Why does the following code fail to enable speakerphone?

class PlaceCall : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        val telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
        telephonyManager.listen(CallListener(this), PhoneStateListener.LISTEN_CALL_STATE)
        val callIntent = Intent(Intent.ACTION_CALL, Uri.parse("tel:" + phoneNumber))
        startActivity(callIntent)
        ...
    }
}
class CallListener(cont: Context) : PhoneStateListener() {
    private var context: Context = cont

    override fun onCallStateChanged(state: Int, phoneNumber: String?) {
        val audioManager: AudioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
        audioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL, audioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL), 0) //I believe this should set call volume to max?
        audioManager.isSpeakerphoneOn = true //I believe this should enable speakerphone, but it doesn't during my tests
    }
}
AndroidManifest.xml
...
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
...

Edit: I tried adding a BroadcastReceiver as well but it didn't change the outcome. Speakerphone is still not enabled. This doesn't make sense and I don't know what I am doing wrong. Below is updated code with the new BroadcastReciever added (above code is still the same).

AndroidManifest.xml (updated)
...
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<application>
    <receiver android:name=".ServiceReceiver"
            android:enabled="true"
            android:exported="false">
            <intent-filter>
                <action android:name="android.intent.action.PHONE_STATE" />
            </intent-filter>
        </receiver>
</application>
...
class ServiceReceiver : BroadcastReceiver() {
    lateinit var telephonyManager: TelephonyManager

    override fun onReceive(context: Context, intent: Intent) {
        telephonyManager = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
        telephonyManager.listen(CallListener(context), PhoneStateListener.LISTEN_CALL_STATE)
        val audioManager: AudioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
        audioManager.mode = AudioManager.MODE_IN_CALL
        audioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL, audioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL), 0)
        audioManager.isSpeakerphoneOn = true
    }
}

a PhoneStateListener as its name suggests is just a listener, it can't perform actions on the current call, that's the responsibility of the default Phone app.

The good news is that you can have the user set your app as the default Phone app, but it forces you to implement certain activities and services which might be out of scope for your app.

You'll need to implement your own dialpad activity for making calls, your own InCallService for handling active calls, and your own in-call UI for allowing the user to mute, put on speaker, connect to bluetooth, put a call on call-waiting, send dialtones while in a call, etc.

You can check out this series of medium posts on how to make your app the default Phone app.

Once you've made your app the default phone app, and your app controls the current app, you can use setAudioRoute to turn on speaker phone.

EDIT:

You can try using setSpeakerphoneOn in AudioManager ( isX is always used to check a value, setX is used to modify a value), however the docs say:

This method should only be used by applications that replace the platform-wide management of audio settings or the main telephony application.

I'm not sure if Android enforces that by preventing apps from calling this method, and if so, on which Android platform, but you can try it out.

There is also a way to use java reflection to access hidden API, see here , but using reflection will almost definitely break on recent version of Android, and might block your app from getting into Google Play. Even still, might worth playing around with.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM