Android Music Play Mode Switching - External Play, Hearing, Earphone

Android Music Play Mode Switching - External Play, Hearing, Earphonehttps://blog.csdn.net/u010936731/article/details/70599482/
Scenario requirements
In the chat scene, when receiving the voice of the other party, the user can choose to play outside or insert headphones to listen. More humanized, when the user is close to the ear, the screen closes and automatically switches to the receiver to play. After playing, the mobile screen automatically lights up. For example, Wechat.

Solve the problem
From the requirement analysis, we can conclude that the code control is needed:
Music Play Control
Switching between Output, Earphone and Hearing
Screen Screen and Bright Screen

Music Play Control
Music playback control is the simplest. MediaPlayer can be used directly. In order to better separate from the interface code and better control music, a control class is written here: Player Manager, as follows:

Switching between Output, Earphone and Hearing
In Android system, Audio Manager is used to manage the playback mode, which is implemented by Audio Manager. setMode ().
In the setMode() method, there are several corresponding playback modes:

MODE_NORMAL: Normal mode, neither ringtone mode nor call mode
MODE_RINGTONE: Ring mode
MODE_IN_CALL: Call Mode
MODE_IN_COMMUNICATION: Communication mode, including audio/video, VoIP calls. (3.0 added, similar to call mode)
Among them:
Playing music corresponds to MODE_NORMAL. If you use outcast, call audioManager.setSpeakerphoneOn(true).
If you use headphones and earphones, you need to set the mode to MODE_IN_CALL (before 3.0) or MODE_IN_COMMUNICATION (after 3.0).

Be careful:
Require permission android.permission.MODIFY_AUDIO_SETTINGS
Why set the mode to MODE_IN_COMMUNICATION after 3.0 instead of MODE_IN_CALL?
It has been proved that MODE_IN_CALL does not work at all in some Huawei models.
So hold an AudioManager variable in the PlayerManager class and add the following methods:

How to determine whether the user plugs in the headset?
When the earphone is inserted or pulled out, the system will issue an Action broadcast for Intent.ACTION_HEADSET_PLUG, and the broadcast can not be processed by a static receiver, so it is enough to write a broadcast receiver to handle the earphone event.

Screen Screen and Bright Screen
Screen screens and bright screens have a premise is to correctly judge whether the user is close to the receiver, how to judge?
Almost every cell phone now has a distance sensor, which is managed by Sensor Manager.

The last parameter of the method of registered monitoring is sensitivity. The higher the sensitivity, the more power consumption. Select general sensitivity here. In addition, Activity needs to implement Sensor EventListener interface to override its method:

In Android system, the control of the working state of hardware is controlled by PowerManager and WakeLock. PowerManager controls the working state of CPU, screen, keyboard and other hardware through different WakeLock.

Note: permissions android.Manifest.permission.DEVICE_POWER and android.permission.WAKE_LOCK are required
The first parameter represents the control level, and the optional values are:

PARTIAL_WAKE_LOCK: CPU running, screen and keyboard may be closed
SCREEN_DIM_WAKE_LOCK: The screen is on and the keyboard lamp may be off
SCREEN_BRIGHT_WAKE_LOCK: The screen is fully lit and the keyboard lamp may be turned off
FULL_WAKE_LOCK: Screen and keyboard lights are all on
PROXIMITY_SCREEN_OFF_WAKE_LOCK: Screen closed, keyboard lamp closed, CPU running
DOZE_WAKE_LOCK: Screen gray, CPU delayed work
Here we select 5.PROXIMITY_SCREEN_OFF_WAKE_LOCK.WakeLock to lock and unlock by acqui() and release().

Begin validation
Through the above three solutions, and then running the program, we can see that the basic functional requirements are met. But there are the following problems:

The hand-shielded distance sensor switches to the receiver in headphone mode
Samsung Note, Huawei P, Huawei Mate series will switch to the receiver, and the receiver will switch to the receiver, which will lead to the Karton phenomenon.
Loss of voice will occur when headphones are switched to external amplifiers
Samsung, Huawei Mobile Phone will call Activity's onPause(),onStop() method when the screen is turned off!
Solving new problems
The Problem of Hand Blocking Distance Sensor in Earphone Mode
This problem can only be solved by not responding to the distance sensor in the headset mode, and adding in Player Manager:

Samsung, Huawei Output Switching Cardon
This problem can only be compromised: replay
Why does this approach work?

Short voice is inherently short and handover replay is almost unaffected.
Music usually doesn't listen to on the receiver.
Not all mobile phones will have Carton.
So modify the method in Player Manager:

Loss of voice will occur when headphones are switched to external amplifiers
This problem is caused by the fact that it takes some time for the headset to switch to the external amplifier, so the solution to this problem is to suspend the replay first and then. When and when will the replay be suspended?
According to the information, when the headset is pulled out, the system will also issue an Action broadcast for Audio Manager. Action_AUDIO_BECOMING_NOISY, and this broadcast is earlier than Intent.ACTION_HEADSET_PLUG, so the solution comes out:

Pause play when AudioManager.ACTION_AUDIO_BECOMING_NOISY is received
Upon receipt of Intent.ACTION_HEADSET_PLUG with state=1

Samsung and Huawei phones call Activity's onPause(),onStop() methods when the screen is turned off.
It's not a problem, but it's worth noting. If you do some resource release operations in onStop(), you need to retrieve them in onStart() to prevent other problems.