Android 聽筒揚聲器切換(多機型相容、相容5.0以上)
阿新 • • 發佈:2019-02-17
目錄
本以為是個很簡單的切換,沒想到搞了快一天。網路上各種答案,各種坑,浪費了大量的時間。
親測有效機型(案例有限、僅供參考)
三星系:SM-A9000、SM-S5
魅族系:魅藍E(yun os)、魅藍note5
小米系:紅米1s、小米note
Vivo系:忘了什麼型號了
程式碼
/**
* ================================================
* 作 者:JayGoo
* 版 本:1.1.0
* 建立日期:2016/11/24
* 描 述:音訊聽筒揚聲器切換控制器
* ================================================
*/
public class AudioModeManger {
private AudioManager audioManager;
private SensorManager sensorManager;
private Sensor mProximiny;
private onSpeakerListener mOnSpeakerListener;
/**
* 揚聲器狀態監聽器
* 如果要做成類似微信那種切換後重新播放音訊的效果,需要這個監聽回撥
* isSpeakerOn 揚聲器是否開啟
*/
public interface onSpeakerListener{
void onSpeakerChanged(boolean isSpeakerOn);
}
public void setOnSpeakerListener(onSpeakerListener listener){
if (listener != null){
mOnSpeakerListener = listener;
}
}
public AudioModeManger(){
}
/**
* 距離感測器監聽者
*/
private SensorEventListener mDistanceSensorListener = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event) {
float f_proximiny = event.values[0];
//揚聲器模式
//魅藍E感測器得到的值竟然比最大值都要大?what fuck ?
if (f_proximiny >= mProximiny.getMaximumRange()) {
setSpeakerPhoneOn(true);
if (mOnSpeakerListener != null){
mOnSpeakerListener.onSpeakerChanged(true);
}
} else {//聽筒模式
setSpeakerPhoneOn(false);
if (mOnSpeakerListener != null){
mOnSpeakerListener.onSpeakerChanged(false);
}
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
/**
* 註冊距離感測器監聽
*/
public void register(){
audioManager = (AudioManager) SMApp.getInstance()
.getSystemService(Context.AUDIO_SERVICE);
sensorManager = (SensorManager) SMApp.getInstance()
.getSystemService(Context.SENSOR_SERVICE);
if (sensorManager != null && mDistanceSensorListener != null) {
mProximiny = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
sensorManager.registerListener(mDistanceSensorListener, mProximiny,
SensorManager.SENSOR_DELAY_NORMAL);
}
}
/**
* 取消註冊距離感測器監聽
*/
public void unregister(){
if (sensorManager != null &&mDistanceSensorListener != null ) {
sensorManager.unregisterListener(mDistanceSensorListener);
}
}
/**
* 聽筒、揚聲器切換
*
* 註釋: 敬那些年踩過的坑和那些網上各種千奇百怪坑比方案!!
*
* AudioManager設定聲音型別有以下幾種型別(調節音量用的是這個):
*
* STREAM_ALARM 警報
* STREAM_MUSIC 音樂回放即媒體音量
* STREAM_NOTIFICATION 視窗頂部狀態列Notification,
* STREAM_RING 鈴聲
* STREAM_SYSTEM 系統
* STREAM_VOICE_CALL 通話
* STREAM_DTMF 雙音多頻,不是很明白什麼東西
*
* ------------------------------------------
*
* AudioManager設定聲音模式有以下幾個模式(切換聽筒和揚聲器時setMode用的是這個)
*
* MODE_NORMAL 正常模式,即在沒有鈴音與電話的情況
* MODE_RINGTONE 鈴響模式
* MODE_IN_CALL 接通電話模式 5.0以下
* MODE_IN_COMMUNICATION 通話模式 5.0及其以上
*
* @param on
*/
private void setSpeakerPhoneOn(boolean on) {
if (on) {
audioManager.setSpeakerphoneOn(true);
audioManager.setMode(AudioManager.MODE_NORMAL);
//設定音量,解決有些機型切換後沒聲音或者聲音突然變大的問題
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC,
audioManager.getStreamVolume(AudioManager.STREAM_MUSIC), AudioManager.FX_KEY_CLICK);
} else {
audioManager.setSpeakerphoneOn(false);
//5.0以上
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
//設定音量,解決有些機型切換後沒聲音或者聲音突然變大的問題
audioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL,
audioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL), AudioManager.FX_KEY_CLICK);
} else {
audioManager.setMode(AudioManager.MODE_IN_CALL);
audioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL,
audioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL), AudioManager.FX_KEY_CLICK);
}
}
}
}
用法
第一步:註冊監聽器
*可以放到Activity的onCreate中或者封裝到音訊管理器中(建議)*
if (audioModeManger == null) {
audioModeManger = new AudioModeManger();
}
audioModeManger.register();
第二步:釋放監聽器
*可以放到Activity的onDestory中或者封裝到音訊管理器中(建議)*
if (audioModeManger != null)
audioModeManger.unregister();
第三步:許可權
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
Demo
Feature
1、插入耳機監聽
2、某些機型可能存在切換時卡頓、丟音的情況,建議採取微信的方案,重新播放音訊,最佳