AudioManager: android is still used to plug in headphones to play audio speaker

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 AudioManagerquery, 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 mode
  • MODE_RINGTONE : Ring patterns
  • MODE_IN_CALL : Talk mode
  • MODE_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

 

Guess you like

Origin www.cnblogs.com/yongdaimi/p/11898816.html