MediaPlayer与SoundPool播放声音

先上代码

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
    ><!--定义一个垂直的线性布局 -->
    <TextView
        android:id="@+id/textView"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="没有播放任何声音"
        /><!-- 向线性布局中添加一个TextView控件 -->
    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="使用MediaPlayer播放声音"
        /><!-- 向线性布局中添加一个Button控件 -->
    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="暂停MediaPlayer声音"
        /><!-- 向线性布局中添加一个Button控件 -->
    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="使用SoundPool播放声音"
        /><!-- 向线性布局中添加一个Button控件 -->
    <Button
        android:id="@+id/button4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="暂停SoundPool声音"
        /><!-- 向线性布局中添加一个Button控件 -->
</LinearLayout>

public class Main4Activity extends AppCompatActivity implements View.OnClickListener{
    Button button1;//四个按钮的引用
    Button button2;
    Button button3;
    Button button4;
    TextView textView;//TextView的引用
    MediaPlayer mMediaPlayer;
    SoundPool soundPool;//声音
    HashMap<Integer, Integer> soundPoolMap;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main4);
        textView = (TextView) this.findViewById(R.id.textView);//得到TextView的引用
        button1 = (Button) this.findViewById(R.id.button1);//得到button的引用
        button2 = (Button) this.findViewById(R.id.button2);
        button3 = (Button) this.findViewById(R.id.button3);
        button4 = (Button) this.findViewById(R.id.button4);
        button1.setOnClickListener(this);//为四个按钮添加监听
        button2.setOnClickListener(this);
        button3.setOnClickListener(this);
        button4.setOnClickListener(this);
        initSounds();
    }

    private void initSounds() {
        mMediaPlayer = MediaPlayer.create(this,R.raw.backsound);
        soundPool = new SoundPool(4, AudioManager.STREAM_MUSIC,100);
        soundPoolMap = new HashMap<>();
        soundPoolMap.put(1,soundPool.load(this,R.raw.dingdong,1));
    }
    public void playSound(int sound,int loop){
        //用SoundPoll播放声音的方法
        AudioManager mgr = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
        float streamVolumeCurrent = mgr.getStreamVolume(AudioManager.STREAM_MUSIC);
        float streamVolumeMax = mgr.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
        float volume = streamVolumeCurrent/streamVolumeMax;
        soundPool.play(soundPoolMap.get(sound), volume, volume, 1, loop, 1f);//播放声音
    }

    @Override
    public void onClick(View v) {
        if (v == button1) {//点击了使用MediaPlayer播放声音按钮
            textView.setText("使用MediaPlayer播放声音");
            if (!mMediaPlayer.isPlaying()) {
                mMediaPlayer.start();//播放声音
            }
        }
        else if (v == button2) {//点击了暂停MediaPlayer声音按钮
            textView.setText("暂停了MediaPlayer播放的声音");
            if (mMediaPlayer.isPlaying()) {
                mMediaPlayer.pause();//暂停声音
            }
        }
        else if (v == button3) {//点击了使用SoundPool播放声音按钮
            textView.setText("使用SoundPool播放声音");
            this.playSound(1, 0);
        }
        else if (v == button4) {//点击了暂停SoundPool声音按钮
            textView.setText("暂停了SoundPool播放的声音");
            soundPool.pause(1);//暂停SoundPool的声音

        }
    }
}

上面是demo,下面看一下SoundPool的用法

如果应用程序经常播放密集、急促而又短暂的音效(如游戏音效)那么使用MediaPlayer显得有些不太适合了。因为MediaPlayer存在如下缺点:

1) 延时时间较长,且资源占用率高。

2) 不支持多个音频同时播放。

Android中除了MediaPlayer播放音频之外还提供了SoundPool来播放音效,SoundPool使用音效池的概念来管理多个短促的音效,例如它可以开始就加载20个音效,以后在程序中按音效的ID进行播放。

SoundPool主要用于播放一些较短的声音片段,与MediaPlayer相比,SoundPool的优势在于CPU资源占用量低和反应延迟小。另外,SoundPool还支持自行设置声音的品质、音量、 播放比率等参数。

SoundPool提供了一个构造器,该构造器可以指定它总共支持多少个声音(也就是池的大小)、声音的品质等。构造器如下:

SoundPool(int maxStreams, int streamType, int srcQuality):第一个参数指定支持多少个声音;第二个参数指定声音类型:第三个参数指定声音品质。

一旦得到了SoundPool对象之后,接下来就可调用SoundPool的多个重载的load方法来加载声音了。

SoundPool提供了如下4个load方法:

int load(Context context, int resld, int priority):从 resld 所对应的资源加载声音。

int load(FileDescriptor fd, long offset, long length, int priority):加载 fd 所对应的文件的offset开始、长度为length的声音。

int load(AssetFileDescriptor afd, int priority):从afd 所对应的文件中加载声音。

int load(String path, int priority):从path 对应的文件去加载声音。

上面4个方法中都有一个priority参数,该参数目前还没有任何作用,Android建议将该 参数设为1,保持和未来的兼容性。

上面4个方法加载声音之后,都会返回该声音的的ID,以后程序就可以通过该声音的ID 来播放指定声音。

SoundPool提供的播放指定声音的方法:

int play(int soundID, float leftVolume, float rightVolume, int priority, int loop, float rate):该方法的第一个参数指定播放哪个声音;leftVolume、rightVolume指定左、右的音量:priority指定播放声音的优先级,数值越大,优先级越高;loop指定是否循环,0为不循环,-1为循环;rate指定播放的比率,数值可从0.5到2, 1为正常比率。

为了更好地管理SoundPool所加载的每个声音的1D,程序一般会使用一个HashMap对象来管理声音。

归纳起来,使用SoundPool播放声音的步骤如下:

1) 调用SoundPool的构造器创建SoundPool的对象。

2) 调用SoundPool对象的load()方法从指定资源、文件中加载声音。最好使用HashMap< Integer, Integer>来管理所加载的声音。

3) 调用SoundPool的play方法播放声音。

下面的程序示范了如何使用SoundPool来播放音效。



MediaPlayer

静态构造方法

方法名称

描述

public static MediaPlayer create(Context context, Uri uri, SurfaceHolder holder)

指定从资源ID对应的资源文件中来装载音乐文件,同时指定了SurfaceHolder对象并返回MediaPlyaer对象

public static MediaPlayer create(Context context, int resid)

指定从资源ID对应的资源文件中来装载音乐文件,并返回MediaPlyaer对象

public static MediaPlayer create(Context context, Uri uri)

指定从Uri对应的资源文件中来装载音乐文件,并返回MediaPlyaer对象

 

常用方法

方法名称

描述

public void start ()

开始或恢复播放

public void stop()

停止播放

public void pause()

暂停播放

public void setDataSource (String path)

从指定的装载path路径所代表的文件

public void setDataSource (FileDescriptor fd, long offset, long length)

指定装载fd所代表的文件中从offset开始、长度为length的文件内容

public void setDataSource (FileDescriptor fd)

指定装载fd所代表的文件

public void setDataSource (Context context, Uri uri)

指定装载uri所代表的文件

public void setDataSource (Context context, Uri uri, Map<String, String> headers)

指定装载uri所代表的文件

public void prepare()

预期准备,因为setDataSource()方法之后,MediaPlayer并未真正的去装载那些音频文件,需要调用prepare()这个方法去准备音频

public void setLooping(boolean looping)

设置是否循环播放这个音乐文件

public void setSurface(Surface surface)

设置Surface

public void setVolume(float leftVolume,float rightVolume)

设置音量

public void setDisplay(SurfaceHolder sh)

设置显示方式

public void seekTo(int mses)

寻求指定的时间位置。

public void isLooping()

判断是否循环播放

public void isPlaying()

判断是否正在播放

public void release()

释放相关该MediaPlayer对象的资源。

 

绑定事件监听器

监听器

描述

public void setOnCompletionListener (MediaPlayer.OnCompletionListener listener)

为MediaPlayer的播放完成事件绑定事件监听器

public void setOnErrorListener (MediaPlayer.OnErrorListener listener)

为MediaPlayer的播放错误事件绑定事件监听器

public void setOnPreparedListener (MediaPlayer.OnPreparedListener listener)

当MediaPlayer调用prepare()方法时触发该监听器

public void setOnSeekCompleteListener (MediaPlayer.OnSeekCompleteListener listener)

当MediaPlayer调用seek()方法的时候触发该监听器

 

播放音频

1、播放应用的资源文件(res/raw/)

通过我们上面介绍的几个静态构造函数创建MediaPlayer对象

[java]  view plain  copy
 print ?
  1. MediaPlayer  mediaPlayer = MediaPlayer.create(MediaPlayerDemoActivity.this,  
  2.   
  3.               R.raw.a1);  


 

2、播放应用的原始资源文件(assets)

1)        通过Context.getAssets()方法获得AssetManager对象

2)        通过AssetManager对象的openFd(String name)方法打开指定的原生资源文件夹,返回一个AssetFileDescriptor对象

3)        通过AssetFileDescriptor的getFileDescriptor()得到一个FileDescriptor对象

4)        通过public void setDataSource (FileDescriptor fd, long offset, long length)来创建MediaPlayer对象

5)        调用MediaPlayer.prepare()方法准备音频

6)        调用MediaPlayer的start()、pause()、stop()等方法控制

[java]  view plain  copy
 print ?
  1. AssetFileDescriptor fileDescriptor = assetManager  
  2.   
  3.                  .openFd("a2.mp3");  
  4.   
  5.             mediaPlayer = new MediaPlayer();  
  6.            mediaPlayer.setDataSource(fileDescriptor.getFileDescriptor(),  
  7.                  fileDescriptor.getStartOffset(),  
  8.                  fileDescriptor.getLength());  
  9.             mediaPlayer.prepare();<p>                  mediaPlayer.start();</p>  

3、播放外部存储上的音频资源文件(sdcard)

1)        创建MediaPlayer对象,通过MediaPlayer对象的setDataSource(String path)方法装载预定的音频文件

2)        调用MediaPlayer对象的prepare()方法准备音频

3)        调用MediaPlayer的start()、pause()、stop()等方法控制

[java]  view plain  copy
 print ?
  1.     mediaPlayer = new MediaPlayer();  
  2.            mediaPlayer.setDataSource("/mnt/sdcard/a3.mp3");  
  3.            mediaPlayer.prepare();  
  4.            mediaPlayer.start();  
  5.   
  6.   
  7.    

4、播放网络上的音频文件

1)        根据网络上的地址创建Uri对象

2)        通过public void setDataSource (Context context, Uri uri)设置音频来源装载音频文件

3)        调用MediaPlayer对象的prepare()方法准备音频

4)        调用MediaPlayer的start()、pause()、stop()等方法控制

[java]  view plain  copy
 print ?
  1. mediaPlayer = new MediaPlayer();  
  2.   
  3.            // 通过Uri解析一个网络地址  
  4.   
  5.            Uri uri = Uri  
  6.   
  7.                  .parse("http://zhangmenshiting2.baidu.com/data2/music/9138619/9138619.mp3?xcode=dd0d0d0df7218eb9a79c7fd72cefb648&mid=0.18926789458694");  
  8.   
  9.            mediaPlayer.setDataSource(MediaPlayerDemoActivity.this, uri);  
  10.   
  11.    
  12.   
  13.            mediaPlayer.prepare();  
  14.   
  15. mediaPlayer.start();  


 

当然也可以通过我们的另一种静态构造方法直接创建一个MediaPlayer对象

[java]  view plain  copy
 print ?
  1. Uri uri = Uri  
  2.   
  3.               .parse("http://zhangmenshiting2.baidu.com/data2/music/9138619/9138619.mp3?xcode=dd0d0d0df7218eb9a79c7fd72cefb648&mid=0.18926789458694");  
  4.   
  5.   
  6.   
  7. mediaPlayer = MediaPlayer.create(MediaPlayerDemoActivity.this,  
  8.   
  9.               uri);  
  10.   
  11.         mediaPlayer.start();  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值