1. 程式人生 > >Android 聽筒揚聲器切換(多機型相容、相容5.0以上)

Android 聽筒揚聲器切換(多機型相容、相容5.0以上)

目錄

本以為是個很簡單的切換,沒想到搞了快一天。網路上各種答案,各種坑,浪費了大量的時間。

親測有效機型(案例有限、僅供參考)

三星系: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、某些機型可能存在切換時卡頓、丟音的情況,建議採取微信的方案,重新播放音訊,最佳