Android監(jiān)聽(tīng)靠近聽(tīng)筒,音頻播放切換聽(tīng)筒和外放

android.hardware提供了距離感應(yīng)器監(jiān)聽(tīng)器,通過(guò)注冊(cè)監(jiān)聽(tīng),來(lái)判斷是否靠近聽(tīng)筒。

private void registerProximitySensorListener() {
        if (getActivity() == null) {
            return;
        }
        sensorManager = (SensorManager) getActivity().getSystemService(SENSOR_SERVICE);
        if (sensorManager == null) {
            return;
        }
        sensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
        sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL);
    }
@Override
    public void onSensorChanged(SensorEvent event) {
        if (audioManager == null) {
            return;
        }
        if (isHeadphonesPlugged()) {
            // 如果耳機(jī)已插入,設(shè)置距離傳感器失效
            return;
        }
        if (DEBUG) {
            Log.i(TAG, "onSensorChanged: " + MediaManager.isPlaying() + " event.values[0]: " + event.values[0]);
        }
        if (MediaManager.isPlaying()) {
            // 如果音頻正在播放
            float distance = event.values[0];
            if (distance >= sensor.getMaximumRange()) {
                // 用戶遠(yuǎn)離聽(tīng)筒,音頻外放,亮屏
                changeToSpeaker();
                if (DEBUG) {
                    Log.i(TAG, "onSensorChanged: 外放");
                }
            } else {
                MediaManager.reStart();
                // 用戶貼近聽(tīng)筒,切換音頻到聽(tīng)筒輸出,并且熄屏防誤觸
                changeToReceiver();
                if (DEBUG) {
                    Log.i(TAG, "onSensorChanged: 聽(tīng)筒");
                }
                audioManager.setSpeakerphoneOn(false);
            }
        } else {
            // 音頻播放完了
            changeToSpeaker();
        }

    }

MediaManager是播放器單例,維護(hù)了一個(gè)MediaPlayer,用來(lái)重新處理播放器。

Android切換聽(tīng)筒時(shí),不同于IOS手機(jī),Android會(huì)有延時(shí),所以建議切換聽(tīng)筒
前,讓音頻重新播放。

public static void reStart() {
        if (mPlayer != null) {
            try {
                mPlayer.seekTo(0);
                mPlayer.start();
            } catch (Exception e) {
                if (DEBUG) {
                    Log.i(TAG, "reStart: " + e.getMessage());
                }
                e.printStackTrace();
            }

        }
    }

當(dāng)靠近聽(tīng)筒后,通過(guò)PowerManager來(lái)熄滅屏幕,以免誤觸


private PowerManager.WakeLock wakeLock;
private final PowerManager mPowerManager;


private void setScreenOff() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Log.i(TAG, "setScreenOff: 熄滅屏幕");
            if (wakeLock == null) {
                wakeLock = mPowerManager.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, TAG);
            }
            wakeLock.acquire(10 * 60 * 1000L /*10 minutes*/);
        }
    }

private void setScreenOn() {
        if (wakeLock != null) {
            wakeLock.setReferenceCounted(false);
            wakeLock.release();
            wakeLock = null;
        }
    }

切換聽(tīng)筒和外放

/**
     * 切換到外放
     */
    public void changeToSpeaker() {
        setScreenOn();
        if (audioManager == null) {
            return;
        }
        audioManager.setMode(AudioManager.MODE_NORMAL);
        audioManager.setSpeakerphoneOn(true);
    }

    /**
     * 切換到耳機(jī)模式
     */
    public void changeToHeadset() {
        if (audioManager == null) {
            return;
        }
        audioManager.setSpeakerphoneOn(false);
    }

    /**
     * 切換到聽(tīng)筒
     */
    public void changeToReceiver() {
        setScreenOff();
        if (audioManager == null) {
            return;
        }
        audioManager.setSpeakerphoneOn(false);
        audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
    }

當(dāng)手機(jī)插入耳機(jī),不做任何操作。

判斷是否插入耳機(jī),isWiredHeadsetOn()已過(guò)時(shí),根據(jù)版本采用最新的判斷方式

private boolean isHeadphonesPlugged() {
        if (audioManager == null) {
            return false;
        }
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
            AudioDeviceInfo[] audioDevices = audioManager.getDevices(AudioManager.GET_DEVICES_ALL);
            for (AudioDeviceInfo deviceInfo : audioDevices) {
                if (deviceInfo.getType() == AudioDeviceInfo.TYPE_WIRED_HEADPHONES
                        || deviceInfo.getType() == AudioDeviceInfo.TYPE_WIRED_HEADSET) {
                    return true;
                }
            }
            return false;
        } else {
            return audioManager.isWiredHeadsetOn();
        }
    }

通過(guò)LifecycleObserver綁定Activity的生命周期,釋放資源

//可以監(jiān)聽(tīng)生命周期
        if (getActivity() != null) {
            getActivity().getLifecycle().addObserver(this);
        }

@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    public void onResume() {

    }

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    public void onDestroy() {
        sensorManager.unregisterListener(this);
        sensorManager = null;
        wakeLock = null;
        mActivity = null;
    }

綜上,代碼如下

import android.arch.lifecycle.Lifecycle;
import android.arch.lifecycle.LifecycleObserver;
import android.arch.lifecycle.OnLifecycleEvent;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.AudioDeviceInfo;
import android.media.AudioManager;
import android.os.Build;
import android.os.PowerManager;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

import java.lang.ref.WeakReference;

import static android.content.Context.POWER_SERVICE;
import static android.content.Context.SENSOR_SERVICE;
/**
 * Created by walkingMen on 2018/12/24.
 */
public class AudioSensorBinder implements LifecycleObserver, SensorEventListener {
    private final AudioManager audioManager;
    private final PowerManager mPowerManager;
    @Nullable
    private WeakReference<AppCompatActivity> mActivity;
    private SensorManager sensorManager;
    private Sensor sensor;
    private PowerManager.WakeLock wakeLock;

    public AudioSensorBinder(@NonNull AppCompatActivity activity) {
        mActivity = new WeakReference<>(activity);
        //可以監(jiān)聽(tīng)生命周期
        if (getActivity() != null) {
            getActivity().getLifecycle().addObserver(this);
        }
        audioManager = (AudioManager) activity.getSystemService(Context.AUDIO_SERVICE);
        mPowerManager = (PowerManager) activity.getSystemService(POWER_SERVICE);
        registerProximitySensorListener();

    }

    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    public void onResume() {

    }

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    public void onDestroy() {
        sensorManager.unregisterListener(this);
        sensorManager = null;
        wakeLock = null;
        mActivity = null;
    }

    /**
     * 注冊(cè)距離感應(yīng)器監(jiān)聽(tīng)器,監(jiān)測(cè)用戶是否靠近手機(jī)聽(tīng)筒
     */
    private void registerProximitySensorListener() {
        if (getActivity() == null) {
            return;
        }
        sensorManager = (SensorManager) getActivity().getSystemService(SENSOR_SERVICE);
        if (sensorManager == null) {
            return;
        }
        sensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
        sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL);
    }

    private AppCompatActivity getActivity() {
        if (mActivity != null) {
            return mActivity.get();
        }
        return null;
    }

    private static final String TAG = "AudioSensorBinder";

    @Override
    public void onSensorChanged(SensorEvent event) {
        if (audioManager == null) {
            return;
        }
        if (isHeadphonesPlugged()) {
            // 如果耳機(jī)已插入,設(shè)置距離傳感器失效
            return;
        }
        if (DEBUG) {
            Log.i(TAG, "onSensorChanged: " + MediaManager.isPlaying() + " event.values[0]: " + event.values[0]);
        }
        if (MediaManager.isPlaying()) {
            // 如果音頻正在播放
            float distance = event.values[0];
            if (distance >= sensor.getMaximumRange()) {
                // 用戶遠(yuǎn)離聽(tīng)筒,音頻外放,亮屏
                changeToSpeaker();
                if (DEBUG) {
                    Log.i(TAG, "onSensorChanged: 外放");
                }
            } else {
                MediaManager.reStart();
                // 用戶貼近聽(tīng)筒,切換音頻到聽(tīng)筒輸出,并且熄屏防誤觸
                changeToReceiver();
                if (DEBUG) {
                    Log.i(TAG, "onSensorChanged: 聽(tīng)筒");
                }
                audioManager.setSpeakerphoneOn(false);
            }
        } else {
            // 音頻播放完了
            changeToSpeaker();
        }

    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }

    private boolean isHeadphonesPlugged() {
        if (audioManager == null) {
            return false;
        }
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
            AudioDeviceInfo[] audioDevices = audioManager.getDevices(AudioManager.GET_DEVICES_ALL);
            for (AudioDeviceInfo deviceInfo : audioDevices) {
                if (deviceInfo.getType() == AudioDeviceInfo.TYPE_WIRED_HEADPHONES
                        || deviceInfo.getType() == AudioDeviceInfo.TYPE_WIRED_HEADSET) {
                    return true;
                }
            }
            return false;
        } else {
            return audioManager.isWiredHeadsetOn();
        }
    }


    /**
     * 切換到外放
     */
    public void changeToSpeaker() {
        setScreenOn();
        if (audioManager == null) {
            return;
        }
        audioManager.setMode(AudioManager.MODE_NORMAL);
        audioManager.setSpeakerphoneOn(true);
    }

    /**
     * 切換到耳機(jī)模式
     */
    public void changeToHeadset() {
        if (audioManager == null) {
            return;
        }
        audioManager.setSpeakerphoneOn(false);
    }

    /**
     * 切換到聽(tīng)筒
     */
    public void changeToReceiver() {
        setScreenOff();
        if (audioManager == null) {
            return;
        }
        audioManager.setSpeakerphoneOn(false);
        audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
    }

    private void setScreenOff() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Log.i(TAG, "setScreenOff: 熄滅屏幕");
            if (wakeLock == null) {
                wakeLock = mPowerManager.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, TAG);
            }
            wakeLock.acquire(10 * 60 * 1000L /*10 minutes*/);
        }
    }

    private void setScreenOn() {
        if (wakeLock != null) {
            wakeLock.setReferenceCounted(false);
            wakeLock.release();
            wakeLock = null;
        }
    }

}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容