There's putting mobile audio output (Speaker), Handset (Telephone Receiver), wired headset (WiredHeadset), Bluetooth Speaker (Bluetooth A2DP) and other output devices. In normal times, the hands-free telephone, headset plug, disconnecting a Bluetooth device like the operating system will automatically switch to the corresponding audio Audio output device. Such as hands-free phone is to switch from the handset to the loud speaker, insert the headset is switched from the loud speaker to the headset.
Scene demand
These strategies Android system automatically switches, and can not meet all the demand for our products, such as music App need to unplug the headphones when listening to music operation stop (pause playback), to prevent a sudden switch to putting lead to embarrassment.
Recent project needs hope 即使在连接蓝牙音箱的情况下,仍旧使用手机外放播放音频
. This requires forced to switch Audio output channels, to break the original strategy system.
Access to information, can be seen in Android AudioManager
query, switch the current channel Audio output, and when Audio output is changed, catch and handle this change.
First remind you that when using the following method, you need to add permission:
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
Audio output status query
AudioManager following methods may be used to provide the current status query Audio output:
-
isBluetoothA2dpOn()
: Check whether A2DPAudio audio output via Bluetooth headset; -
isSpeakerphoneOn()
: Check that the speaker is turned on; -
isWiredHeadsetOn()
: Check whether the headphone wire attached; note that this method is only used to determine whether the earphone is inserted state, it does not use the results to determine a current Audio output through the earphone, which also depends on other conditions. -
setSpeakerphoneOn(boolean on)
: Direct selection loud speaker sound; -
setBluetoothScoOn(boolean on)
: SCO requires the use of a Bluetooth headset to communicate;
Here According to the article briefly introduce two kinds of links Bluetooth headset, A2DP and SCO. The android api show:
- A2DP: a one-way data transmission of high quality audio link, typically for playing stereo music;
- SCO: it is a two-way audio data transmission link, the link only supports 8K and 16K mono audio data can only be used for transmission of ordinary speech, if it can only be used to play music Oh the .
The main difference between the two is: A2DP only play, is on by default, and the SCO can play both recordings, is off by default. If you want to record the matter will certainly be open sco, so call the above setBluetoothScoOn (boolean on) can, through a Bluetooth headset recording, audio playback, and finished recording, remember to turn off finished playing.
Further, by the Android system AudioManager.setMode()
for managing playback mode method. In setMode()
different playback modes correspond to the following method:
MODE_NORMAL
: Normal mode, neither ring pattern nor talk modeMODE_RINGTONE
: Ring patternsMODE_IN_CALL
: Talk modeMODE_IN_COMMUNICATION
: Mode of communication, including audio / video, VoIP calls (3.0 was added, the call mode and the like).
When setting up the play mode, you need to consider the type of flow, flow type here I am using STREAM_MUSIC
, so when you need to switch the playback device is set to MODE_IN_COMMUNICATION
mode instead of MODE_NORMAL
mode. You can refer to this issue .
Solve the problem
Following the method of switching audio Audio output, with reference to the Android: Switching Audio and the Bluetooth Phone Speaker BETWEEN Inconsistent IS :
= AudioManager AudioManager (AudioManager) context.getSystemService (Context.AUDIO_SERVICE); / ** * switch to loud * / public void changeToSpeaker () { // Note that here, instead of using MODE_IN_COMMUNICATION MODE_NORMAL Bluetooth is not disconnected mAudioManager.setMode (? bluetoothIsConnected AudioManager.MODE_IN_COMMUNICATION: AudioManager.MODE_NORMAL); mAudioManager.stopBluetoothSco (); mAudioManager.setBluetoothScoOn ( false ); mAudioManager.setSpeakerphoneOn ( to true ); } / ** * switch to Bluetooth speakers * / public void changeToHeadset () { mAudioManager.setMode (AudioManager.MODE_IN_COMMUNICATION); mAudioManager.startBluetoothSco (); mAudioManager.setBluetoothScoOn ( to true ); mAudioManager.setSpeakerphoneOn ( to false ); } / ** ******************************************************** **************************************** * / // Note: the following two methods not yet verification / ** **************************** ************* * / / ** * switched to the headset mode * / public void changeToHeadset () { mAudioManager.setMode (AudioManager.MODE_IN_COMMUNICATION); mAudioManager.stopBluetoothSco (); mAudioManager.setBluetoothScoOn ( false ); mAudioManager.setSpeakerphoneOn (false); } /** * 切换到听筒 */ public void changeToReceiver(){ audioManager.setSpeakerphoneOn(false); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){ audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); } else { audioManager.setMode(AudioManager.MODE_IN_CALL); } }
Direct method to switch the output channels we already know. The remaining problem to be solved is that when a Bluetooth device is disconnected, connection, we hope that can automatically switch to the user originally set output channels, such as when Bluetooth is not connected, set by the user is to broadcast via Bluetooth, so it should be after the Bluetooth Once connected, the audio switch to put on the Bluetooth device.
Here we look at how to monitor the connection status of the Bluetooth device.
First, note the use of the former requires the following permissions:
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.BLUETOOTH" />
According to the article , we found that you can use AudioManager.ACTION_AUDIO_BECOMING_NOISY
this to listen Intent Action Bluetooth off, plug the headset radio, but tests found that it can only receive Bluetooth radio off, unable to receive the broadcast with Bluetooth connectivity, so it is not we want.
Further found this article: About Bluetooth development, we must pay attention to the broadcast , the following summarizes the Bluetooth radio.
/ ** * annotated radio, Bluetooth connection will be used * / intentFilter.addAction (BluetoothDevice.ACTION_FOUND); // search blue voltage equipment, each search to a device sends a broadcast intentFilter.addAction (BluetoothDevice.ACTION_BOND_STATE_CHANGED); // when pairing start, when the pairing is successful intentFilter.addAction (BluetoothDevice.ACTION_ACL_CONNECTED); // pairing, initiate a connection intentFilter.addAction (BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED); intentFilter.addAction (BluetoothDevice.ACTION_ACL_DISCONNECTED); // paired end off open connection intentFilter.addAction (PAIRING_REQUEST); // pairing request (Android.bluetooth.device.action.PAIRING_REQUEST) intentFilter.addAction (BluetoothAdapter.ACTION_DISCOVERY_STARTED); //Start Search intentFilter.addAction (BluetoothAdapter.ACTION_DISCOVERY_FINISHED); // search ends. When re-search, a search will be terminated before intentFilter.addAction (BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); intentFilter.addAction (BluetoothAdapter.ACTION_STATE_CHANGED); // the machine is turned on, switch off Bluetooth intentFilter.addAction (BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); // Bluetooth devices or disconnect intentFilter.addAction (BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); // when you change the Bluetooth name, open the Bluetooth may be called multiple times intentFilter.addAction (BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); intentFilter.addAction (BluetoothAdapter.ACTION_REQUEST_ENABLE); intentFilter.addAction (BluetoothAdapter. ACTION_SCAN_MODE_CHANGED); //Search mode change
We found BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED
and BluetoothAdapter.ACTION_STATE_CHANGED
two Intent broadcast.
So what is the difference between these two broadcast Intent is it? Only one of which can do? View Google Documents found
-
BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED
: Refers to a change in connection state of the local Bluetooth adapter (such as no Bluetooth switch off the machine, the other paired devices themselves disconnected) -
BluetoothAdapter.ACTION_STATE_CHANGED
: Refers to the state of the local Bluetooth adapter has changed. For example, Bluetooth switch on or off.
In other words, a change is for connection state, a state change for other Bluetooth adapter itself. After the test found, if only BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED
to listen to broadcast less than "active Bluetooth switch to turn off the machine," the event will be broadcast reception. But only with BluetoothAdapter.ACTION_STATE_CHANGED
words, it is clear that time is not really paired Bluetooth devices.
Dynamic registration Bluetooth connection, disconnection broadcast as follows:
- Dynamic registration broadcast
public class BluetoothConnectionReceiver the extends the BroadcastReceiver { @Override public void the onReceive (the Context context, the Intent Intent) { IF (BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED.equals (intent.getAction ())) { // Bluetooth connection state int State = intent.getIntExtra (BluetoothAdapter.EXTRA_CONNECTION_STATE , -1 ); IF (State State == == BluetoothAdapter.STATE_CONNECTED || BluetoothAdapter.STATE_DISCONNECTED) { // connection or lost contact, switch the audio output (Bluetooth, or still forced loud speaker) } } the else IF(BluetoothAdapter.ACTION_STATE_CHANGED.equals (intent.getAction ())) { // local Bluetooth opened or closed int State = intent.getIntExtra (BluetoothAdapter.EXTRA_STATE, -1 ); IF (State State == == BluetoothAdapter.STATE_OFF || BluetoothAdapter.STATE_TURNING_OFF) { // OFF, switch the audio output } } } }
BluetoothConnectionReceiver audioNoisyReceiver = new BluetoothConnectionReceiver(); //蓝牙状态广播监听 IntentFilter audioFilter = new IntentFilter(); audioFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); audioFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); mContext.registerReceiver(audioNoisyReceiver, audioFilter);
After that, we can switch the audio output channels in accordance with the above code to achieve Bluetooth device connected later forced to break off the original operating system output channel switching strategy to achieve switching function of our own want.
This switched: Audio output audio channel switching - Bluetooth, putting