IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android MediaPlayer播放 听筒外放切换 -> 正文阅读

[移动开发]Android MediaPlayer播放 听筒外放切换

Android MediaPlayer播放 听筒外放切换,通过注册监听,来判断是否靠近听筒。

结合mediaplayer坐音频播放,Android hardware搞一个根据光感听筒外放切换。
MediaManager是播放器构建模式,维护了一个MediaPlayer,用来重新处理播放器。

MediaManager.builder()
                        .setContext(MainActivity.this)
                        .setDebugModel(true)
                        .setMediaListener(new MediaCallBack() {
                            @Override
                            public void progress(int i, int max) {

                            }

                            @Override
                            public void prepare(int duration, String time) {

                            }

                            @Override
                            public void start() {

                            }

                            @Override
                            public void end() {

                            }

                            @Override
                            public void stop() {

                            }
                        })
                        .setUrl("https://96.f.1ting.com/local_to_cube_202004121813/96kmp3/2020/09/21/21e_wc/01.mp3")
                        .build();

开始播放

                MediaManager.start();

停止

                MediaManager.stop();

是否正在播放

                MediaManager.isPlaying();

暂停

                MediaManager.pause();

继续

                MediaManager.resume();

销毁当前的mediaplayer destory时候调用

                MediaManager.removeAll();

AudioManager

Android为我们提供的(音量大小控制)的API: AudioManager(音频管理器)了,该类位于Android.Media包下,提供了音量控制与铃声模式相关操作。

获得AudioManager对象实例

AudioManager am = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);

PowerManager

Android系统为我们提供的电源管理的一个API,其相关接口与设备电池的续航能力有很大的关联, 官方也说了,除非是迫不得已吧,不然的话,应该尽量避免使用这个类,并且使用完以后一定要及时释放。所谓的电源管理包括:CPU运行,键盘或者屏幕亮起来!核心其实就是wakelock锁机制,只要我们拿着这个锁, 那么系统就无法进入休眠状态,可以给用户态程序或内核获取到。锁可以是:”有超时的“或者 “没有超时“,超时的锁到时间后会自动解锁,如果没有了锁或超时,内核会启动休眠机制来进入休眠。

添加权限

    <uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>

获取PowerManager对象实例

 powerManager = (PowerManager) getActivity().getSystemService(POWER_SERVICE);

整体的代码如下:


/**
 * Created by SHICHENG
 * <p>
 * Time on 2021/11/08
 */
public class AudioSensorBinder implements LifecycleObserver, SensorEventListener {

    public final String TAG = this.getClass().getSimpleName();

    private final AudioManager audioManager;
    private final PowerManager powerManager;

    @Nullable
    private WeakReference<AppCompatActivity> activity;
    private SensorManager sensorManager;
    private Sensor sensor;
    private PowerManager.WakeLock wakeLock;

    @RequiresApi(api = Build.VERSION_CODES.M)
    public AudioSensorBinder(@Nullable AppCompatActivity mActivity) {
        this.activity = new WeakReference<>(mActivity);
        //可以监听生命周期
        if (getActivity()!=null){
            getActivity().getLifecycle().addObserver(this);
        }
        audioManager = (AudioManager) getActivity().getSystemService(AUDIO_SERVICE);
        powerManager = (PowerManager) getActivity().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;
        activity = null;
    }
    /**
     * 注册距离感应器监听器,监测用户是否靠近手机听筒
     */
    @RequiresApi(api = Build.VERSION_CODES.M)
    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 (activity != null) {
            return activity.get();
        }
        return null;
    }


    @Override
    public void onSensorChanged(SensorEvent event) {
        if (audioManager == null) {
            return;
        }
        if (isHeadphonesPlugged()) {
            // 如果耳机已插入,设置距离传感器失效
            return;
        }
        if (true) {
            Log.i(TAG, "onSensorChanged: " + MediaManager.isPlaying() + " event.values[0]: " + event.values[0]);
        }
        if (MediaManager.isPlaying()) {
            // 如果音频正在播放
            float distance = event.values[0];
            if (distance >= sensor.getMaximumRange()) {
                // 用户远离听筒,音频外放,亮屏
                changeToSpeaker();
                if (true) {
                    Log.i(TAG, "onSensorChanged: 外放");
                }
            } else {
                MediaManager.resume();
                // 用户贴近听筒,切换音频到听筒输出,并且熄屏防误触
                changeToReceiver();
                if (true) {
                    Log.i(TAG, "onSensorChanged: 听筒");
                }
                audioManager.setSpeakerphoneOn(false);
            }
        } else {
            // 音频播放完了
            changeToSpeaker();
        }
    }

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

    }

    @SuppressLint("WrongConstant")
    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);
    }

    /**
     * 切换到耳机模式
     */
    public void changeToHeadset() {
        if (audioManager == null) {
            return;
        }
        audioManager.setSpeakerphoneOn(false);
    }

    /**
     * 切换到听筒
     */
    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 = powerManager.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;
        }
    }
}

MediaManager


/**
 * Created by SHICHENG
 * <p>
 * Time on 2021/11/08
 */
public class MediaManager {

    private static MediaManagerBuilder mediaManagerBuilder;

    public static MediaManagerBuilder builder() {
        mediaManagerBuilder = new MediaManagerBuilder();
        return mediaManagerBuilder;
    }

    public static void start(){
        mediaManagerBuilder.start();
    }

    public static boolean isPlaying(){
        if (mediaManagerBuilder!=null){
            return mediaManagerBuilder.isPlaying();
        }
        return false;
    }

    public static void stop(){
        if (mediaManagerBuilder!=null){
            mediaManagerBuilder.stop();
        }
    }

    public static void pause(){
        if (mediaManagerBuilder!=null){
            mediaManagerBuilder.pause();
        }
    }

    public static void resume(){
        if (mediaManagerBuilder!=null){
            mediaManagerBuilder.resume();
        }
    }
    public static void removeAll(){
        if (mediaManagerBuilder!=null){
            mediaManagerBuilder.removeAll();
        }
    }

    public static class MediaManagerBuilder{

        public final String TAG = this.getClass().getSimpleName();
        private Handler handler = new Handler();
        private boolean isSeekBarChanging;//互斥变量,防止进度条与定时器冲突。

        private Context context;
        private MediaConfig config;
        private MediaCallBack mediaListener;
        private MediaPlayer mediaPlayer;
        private boolean DEBUG = false;
        private SimpleDateFormat format;
        private Timer timer;
        private TimerTask timerTask;
        private SeekBar seekBar;

        private MediaManagerBuilder() {
            this.config = new MediaConfig();
            this.mediaPlayer = new MediaPlayer();
            this.format = new SimpleDateFormat("mm:ss");
        }

        /**
         * 当前Activity的上下文
         *
         * @param context
         * @return
         */

        public MediaManagerBuilder setContext(Context context){
            this.context = context;
            return this;
        }

        /**
         * 设置MediaPlayer Url链接
         *
         * @param url
         * @return
         */
        public MediaManagerBuilder setUrl(String url){
            this.config.url = url;
            return this;
        }

        /**
         * 设置播放进度监听回调
         *
         * @param mediaListener
         * @return
         */
        public MediaManagerBuilder setMediaListener(MediaCallBack mediaListener){
            this.mediaListener = mediaListener;
            return this;
        }

        /**
         * 设置是否是debug
         *
         * @param b
         * @return
         */
        public MediaManagerBuilder setDebugModel(boolean b){
            this.DEBUG = b;
            return this;
        }

        /**
         * 设置进度条
         */
        public MediaManagerBuilder setProgressSeek(SeekBar seek){
            this.seekBar = seek;
            return this;
        }


        /**
         * 初始化MediaPlayer
         */

        public MediaManagerBuilder build(){
            Uri uri = Uri.parse(config.url);
            //播放器不能为空
            if (mediaPlayer!=null){
                //如果是正在播放的状态 需要暂停上一个
                if (mediaPlayer.isPlaying()){
                    mediaPlayer.stop();
                }
                //重置播放器
                mediaPlayer.release();
            }
            //创建新的播放器
            mediaPlayer = new MediaPlayer();
            try {
                mediaPlayer.setDataSource(config.url); //指定音频文件的路径
                mediaPlayer.prepare();//让mediaplayer进入准备状态
                mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                    @Override
                    public void onPrepared(MediaPlayer mp) {
                        if (seekBar!=null){
                            seekBar.setMax(mediaPlayer.getDuration());
                        }
                        mediaListener.prepare(mediaPlayer.getDuration(),format.format(mediaPlayer.getDuration()) + "");
                    }
                });
                // 监听音频播放完的代码,实现音频的自动循环播放
                mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                    @Override
                    public void onCompletion(MediaPlayer arg0) {
                        mediaListener.end();
                    }
                });
            } catch (IOException e) {
                e.printStackTrace();
            }
            timerTask = new TimerTask() {

                Runnable updateUI = new Runnable() {
                    @Override
                    public void run() {
                        if (mediaPlayer != null && mediaPlayer.getCurrentPosition() != -1) {
                            mediaListener.progress(mediaPlayer.getCurrentPosition(), mediaPlayer.getDuration());
                        }
                    }
                };

                @Override
                public void run() {
                    if (!isSeekBarChanging) {
                        if (seekBar!=null){
                            seekBar.setProgress(mediaPlayer.getCurrentPosition());
                        }
                        handler.post(updateUI);
                    }

                }
            };
            if (seekBar!=null){
                seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
                    @Override
                    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {

                    }

                    @Override
                    public void onStartTrackingTouch(SeekBar seekBar) {
                        isSeekBarChanging = true;
                    }

                    @Override
                    public void onStopTrackingTouch(SeekBar seekBar) {
                        isSeekBarChanging = false;
                        mediaPlayer.seekTo(seekBar.getProgress());
                    }
                });
            }
            return this;
        }


        /**
         * 开始播放
         */
        private void start(){
            //开始播放
            mediaPlayer.start();
            if (seekBar!=null){
                mediaPlayer.seekTo(seekBar.getProgress());
            }
            if (DEBUG){
                Log.i(TAG, "start: media start");
            }
            //监听播放时回调函数
            timer = new Timer();
            timer.schedule(timerTask,0,50);
        }

        /**
         * 停止播放
         */
        private void stop(){
            //播放器不能为空  为空终止
            if (mediaPlayer == null){
                return;
            }
            mediaPlayer.stop();
            if (DEBUG){
                Log.i(TAG, "start: media stop");
            }
        }

        /**
         * 暂停播放
         */
        private void pause(){
            //播放器不能为空  为空终止
            if (mediaPlayer == null){
                return;
            }
            mediaPlayer.pause();
            if (DEBUG){
                Log.i(TAG, "start: media pause");
            }
        }

        /**
         * 继续播放
         */
        private void resume(){
            //播放器不能为空  为空终止
            if (mediaPlayer == null){
                return;
            }
            mediaPlayer.start();
            if (DEBUG){
                Log.i(TAG, "start: media resume");
            }
        }

        /**
         * 是否是播放中
         */
        private boolean isPlaying(){
            if (mediaPlayer!=null){
                return mediaPlayer.isPlaying();
            }
            return false;
        }

        /**
         * 移除所有 清除内存
         */
        public void removeAll(){
            isSeekBarChanging = true;
            if (timer != null) {
                timer.cancel();
                timer = null;
            }
            if (mediaPlayer != null) {
                mediaPlayer.stop();
                mediaPlayer.release();
                mediaPlayer = null;
            }
        }



    }




}

Demo gitee

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-11-09 19:40:29  更:2021-11-09 19:41:11 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 1:22:28-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码