zoukankan      html  css  js  c++  java
  • Android MediaPlayer 播放音频

    本文链接: Android MediaPlayer 播放音频

    主要介绍使用MediaPlayer播放音频的方式。关于MediaPlayer的基础知识,比如状态,可以参考Android MediaPlayer 基础简介

    为了方便表达,定义变量名为mediaPlayer。

    MediaPlayer的使用方式

    创建MediaPlayer

    可以直接 new MediaPlayer,也可以用MediaPlayer提供的create方法创建。

    mediaPlayer = new MediaPlayer();
    

    使用create方法创建成功后,mediaPlayer处于Prepared状态。可以直接start播放。

        mediaPlayer = MediaPlayer.create(getApplicationContext(), Uri.fromFile(file));
        mediaPlayer.start();
    

    设置音源 - setDataSource

    通过调用setDataSource来设置音源。setDataSource有多个重载方法,我们来看常用的几种。

    例如设置使用assets里的资源。实际情况可能需要try catch。

        AssetFileDescriptor fd = null;
        MediaPlayer mediaPlayer = new MediaPlayer();
        fd = context.getApplicationContext().getAssets().openFd(name);
        mediaPlayer.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
    

    本地文件,需要文件的绝对路径。

    mediaPlayer.setDataSource(file.getAbsolutePath());
    

    或者获取文件的Uri来创建mediaPlayer。

    mediaPlayer = MediaPlayer.create(getApplicationContext(), Uri.fromFile(file));
    

    设置网络音频,也是用setDataSource方法,设置url。

    mediaPlayer.setDataSource("https://demo.com/sample.mp3"));
    

    播放网络音频时,如果使用的是http,有可能会报错

    java.io.IOException: Cleartext HTTP traffic to demo.com not permitted
    

    可以简单地设置一下manifest,设置usesCleartextTraffic="true"

    <application
            android:usesCleartextTraffic="true">
    

    准备 - prepare

    同步和异步准备音频资源。prepareAsync()是异步的方式,prepare是同步的。注意线程调度问题,同时不要阻塞UI线程。

    使用异步方式准备音频,经常与MediaPlayer.OnPreparedListener监听器配合使用。异步准备时,也可以进行其他的设置。

        mediaPlayer.prepareAsync();
        mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mediaPlayer) {
                mediaPlayer.start(); // 准备好了就播放
            }
        });
    

    循环播放 - Looping

    设置循环播放setLooping。

    mediaPlayer.setLooping(true);
    

    播放完毕后,不会回调OnCompletionListener,而是从头播放当前音频。

    播放 - start

    播放音频,调用start方法。

    mediaPlayer.start();
    

    处于Prepared,Pause和PlaybackComplete状态时,可以调用start方法,进入Started状态。

    暂停 - pause

    暂停播放,使用pause方法。在暂停前先判断一下mediaPlayer的是否在播放。

        if (mediaPlayer.isPlaying()) {
            mediaPlayer.pause();
        }
    

    暂停成功则处于Paused状态。

    停止 - stop

    回顾一下MediaPlayer状态切换的图示,我们可以得知在播放中,暂停,播放完成这3个状态下,可以调用stop方法,进入Stopped状态。

    mediaPlayer.stop();
    

    调进度 - seekTo

    调整播放进度。我们平时使用音乐播放软件一般都会有这个功能。
    seekTo方法接受一个毫秒参数。

        int targetMS = (int) (percent * mediaPlayer.getDuration());
        mediaPlayer.seekTo(targetMS);
    

    seekTo并不会改变MediaPlayer的状态。

    重置 - reset

    reset后的mediaPlayer进入Idle状态。需要重新设置音源与准备。

    释放 - release

    不再使用这个mediaPlayer时,应当尽快释放掉,以释放相关的资源。
    调用release后,mediaPlayer进入End状态。此时这个mediaPlayer就不能再使用了。

    常用监听器

    缓冲监听器 OnBufferingUpdateListener

    比如我们加载网络音频的时候,常用这个监听器来监听缓冲进度。显示缓冲进度,也可以提高用户体验。

        mMediaPlayer.prepareAsync();
        mMediaPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
            @Override
            public void onBufferingUpdate(MediaPlayer mp, int percent) {
                // percent代表缓冲百分比
            }
        });
    

    错误监听器 OnErrorListener

    mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
        @Override
        public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
            return true; // 返回true表示在此处理错误,不会回调onCompletion
        }
    });
    

    注意onError的返回值。可以选择自己处理error。

             * @return True if the method handled the error, false if it didn't.
             * Returning false, or not having an OnErrorListener at all, will
             * cause the OnCompletionListener to be called.
             */
            boolean onError(MediaPlayer mp, int what, int extra);
    

    播放完毕监听器 OnCompletionListener

    mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
        @Override
        public void onCompletion(MediaPlayer mediaPlayer) {
            // 播放完毕
        }
    });
    

    使用示例

    播放assets里的音频

    播放assets里的音频文件,使用到AssetFileDescriptor类。使用后记得关闭AssetFileDescriptor。

        private void playAssetsAudio(final String name, Context context) {
            Log.d(TAG, "playAssetWordSound: try to play assets sound file. -> " + name);
            AssetFileDescriptor fd = null;
            try {
                MediaPlayer mediaPlayer;
                Log.v(TAG, "Looking in assets.");
                fd = context.getApplicationContext().getAssets().openFd(name);
                mediaPlayer = new MediaPlayer();
                mediaPlayer.reset();
                mediaPlayer.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
                mediaPlayer.prepareAsync();
                mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                    @Override
                    public void onPrepared(MediaPlayer mediaPlayer) {
                        Log.d(TAG, "onPrepared: " + name);
                        mediaPlayer.start();
                    }
                });
                mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                    @Override
                    public void onCompletion(MediaPlayer mp) {
                        mp.release();
                        Log.d(TAG, "onCompletion: " + name);
                    }
                });
                mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
                    @Override
                    public boolean onError(MediaPlayer mp, int i, int i1) {
                        mp.release();
                        return true;
                    }
                });
            } catch (Exception e) {
                try {
                    if (fd != null) {
                        fd.close();
                    }
                } catch (Exception e1) {
                    Log.e(TAG, "Exception close fd: ", e1);
                }
            } finally {
                if (fd != null) {
                    try {
                        fd.close();
                    } catch (IOException e) {
                        Log.e(TAG, "Finally, close fd ", e);
                    }
                }
            }
        }
    
    

    播放本地音频文件

    尝试播放音频文件。仅播放一次。

        private void playAudioFile(final File file) {
            Log.d(TAG, "playAudioFile: " + file.getAbsolutePath());
            MediaPlayer mediaPlayer;
            try {
                mediaPlayer = new MediaPlayer();
                mediaPlayer.setLooping(false);
                mediaPlayer.setDataSource(file.getAbsolutePath());
                mediaPlayer.prepare();
                mediaPlayer.start();
                mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                    @Override
                    public void onCompletion(MediaPlayer mp) {
                        mp.release();
                    }
                });
                mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
                    @Override
                    public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
                        Log.d(TAG, "Play local sound onError: " + i + ", " + i1);
                        return true;
                    }
                });
            } catch (Exception e) {
                Log.e(TAG, "playAudioFile: ", e);
            }
        }
    

    播放在线音频

    设置url,播放在线音频

        private void playOnlineSound(String soundUrlDict) {
            try {
                MediaPlayer mediaPlayer = new MediaPlayer();
                mediaPlayer.setDataSource(soundUrlDict);
                mediaPlayer.prepareAsync();
                mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                    @Override
                    public void onPrepared(MediaPlayer mediaPlayer) {
                        mediaPlayer.start();
                    }
                });
                mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                    @Override
                    public void onCompletion(MediaPlayer mp) {
                        if (mp != null) {
                            mp.release();
                        }
                        Log.d(TAG, "onCompletion: play sound.");
                    }
                });
                mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
                    @Override
                    public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
                        Log.d(TAG, "Play online sound onError: " + i + ", " + i1);
                        return false;
                    }
                });
            } catch (IOException e1) {
                Log.e(TAG, "url: ", e1);
            }
        }
    

    代码可以参考示例工程: https://github.com/RustFisher/android-MediaPlayer

  • 相关阅读:
    《程序员代码面试指南》第七章 位运算 在其他数都出现k 次的数组中找到只出现一次的数
    《程序员代码面试指南》第七章 位运算 在其他数都出现偶数次的数组中找到出现奇数次的数
    《程序员代码面试指南》第七章 位运算 整数的二进制表达中有多少个1
    《程序员代码面试指南》第七章 位运算 只用位运算不用算术运算实现整数的加减乘除运算
    Java基础 TreeSet()来实现数组的【定制排序】 : Comparable接口(自然排序) 或者 Comparator接口 (定制排序)
    Java 基础
    Java 基础
    【Java基础-实验7】Banking_7 -添加银行透支扣款系统的 thorw异常机制
    Java基础-异常处理机制 及异常处理的五个关键字:try/catch/finally/throw /throws
    Java 基础 面向对象: 接口(interface )概念 以及接口之练习3 -定义一个接口用来实现两个对象的比较并 判断instanceof是否为同类
  • 原文地址:https://www.cnblogs.com/rustfisher/p/11568524.html
Copyright © 2011-2022 走看看