Android多媒体之MediaPlayer

 

     Android应用增加动画,视频,音乐等多媒体功能,因此为手机提供音频录制,播放,视频录制,播放的功能十分重要。Android提供了常见音频,视频的编码,解码机制,Android支持的音频格式有MP3,WAV和3GP等,支持的视频格式有MP4和3GP等                                            

         Android提供了这些多媒体的支持类,可以非常方便地在手机应用中播放音频,视频等。这些多媒体数据可以来自Android应用的资源文件,也可以来自外部存储器上的文件,也可以来自网络的文件流。

      不仅如此,Android也提供了对摄像头,麦克风的支持,因此也可以十分方便地从外部采集照片,视频,音频等多媒体信息。

 

——音频和视频的播放

——MediaPlayer播放音频

  1)MediaPalyer进行播放控制的方式:

     start():开始或者恢复播放

     stop():停止播放

     pause():暂停播放

  2)MediaPlayer装载指定音频文件的方式

      static MediaPlayer create(Content,Uri):从指定Uri来装载音频文件,并返回新创建的MediaPlayer对象。

     static MediaPlayer create(Content,int resid):从redid资源ID来装载音频文件,并返回新创建的MediaPlayer对象。

    上面这两个方法使用起来很简单,但这两个方法每次都会返回新的MediaPlayer.如果程序需要播放多个音频文件,使用该方法就不太合适了。此时可通过setDataSource方法装载指定的音频文件。

     MediaPlayer m = new MediaPlayer():只需要创建一个对象

     setDataSource(String path):指定装载path路径所代表的文件

     setDataSource(FileDescriptor fs,long offset,long length):指定装载fd所代表的文件中从offset开始,长度为length的文件内容。

     setDataSource(FileDescriptor fd):指定装载fd所代表的文件                   

 

    setDataSource(Context,Uri):指定装载Uri所代表的文件

    执行setDataSource方法之后,MediaPlayer并未真正装载那些音频文件,还需要调用prepare()方法准备装载音频。

 3)播放应用raw的资源文件

   MediaPlayer m=MediaPlayer.create(this,R.raw.apple);

   m.start();

 4)播放应用raw的资源文件

     MediaPlayer m=new  MediaPlayer();

     m.setDataSource(Context,Uri.parse(

      "android.resource://"+getPackageName()+"/"+R.raw.XXX"))

 5)播放应用的原生资源文件

    AssetManager assetManager = getAssets();

                                   AssetFileDescriptorassetFileDescriptor = assetManager

                                                          .openFd("music.mp3");

                                   FileDescriptorfileDescriptor = assetFileDescriptor

                                                          .getFileDescriptor();

                                   mediaPlayer.setDataSource(fileDescriptor);

 

    e)调用MediaPlayer的prepare()方法准备音频

    f)调用MediaPlayer的start(),stop(),pause()方法控制播放即可

  5)播放外部存储器上音频文件

   a)创建MediaPlayer对象,调用setDataSource("/sdcard/apple.mp3")

    b)调用MediaPlayer对象的prepare()方法

    c)调用MediaPlayer的start(),stop(),pause()方法控制播放即可

  6)播放来自网络的音频文件

    a)根据网络上的音频文件所在的位置创建Uri对象。

      Uri  uri =Uri.parse("http://www.baidu.com/song.mp3");

    b)创建MediaPlayer对象,调用setDataSource(Context,Uri);

    c)调用MediaPlayer对象的prepare()方法

    d)调用MediaPlayer的start(),stop(),pause()方法控制播放即可

 7)如播放下一首歌曲的代码:

  mPlayer.reset();//空闲状态

  mPlayer.setDataSource("/sdcard/gequ.mp3");

  mPlayer.prepare();

  mPlayer.start();

 8)MediaPlayer还提供了事件监听器的方法

    setOnCompletionListener():播放完成事件绑定事件监听器

    setOnErrorListener():播放错误事件绑定事件监听器

    setOnPreparedListener():调用prepare()方法时触发该监听器

    setOnSeekCompleteListener():调用seek()方法时触发该监听器

  9)Mediaplayer除了调用prepare()方法准备声音之外,

  还可以调用

     prepareAsync()来准备声音,他们的区别在于:

     prepareAsync()是异步的,它不会阻塞当前的UI线程。

 10)MediaPlayer的状态图

     reset():清空MediaPlayer中的数据

    setDataSource():设置音频数据

    prepare():准备装载音频数据

    prepareAsync():准备装载音频数据(异步)

     seekTo():重新定位到音频数据的什么位置,单位毫秒

     seekTo()是定位方法,可以让播放器从指定的位置开始播放,需要注意的是该方法是个异步方法,也就是说该方法返回时并不意味着定位完成,尤其是播放的网络文件,真正定位完成时会触发OnSeekComplete.onSeekComplete(),如果需要是可以调用setOnSeekCompleteListener(OnSeekCompleteListener)设置监听器来处理的。

     start():

     pause():

     stop():

    release():释放MediaPlayer资源

 

 11)其他的方法

     setLooping(true):是否重复播放

     setAudioStreamType() 设置使用的音频流


import android.app.Activity;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.view.View;
import android.widget.SeekBar;
import android.widget.Toast;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;

public class MainActivity extends Activity {

	private MediaPlayer mediaPlayer;
	private SeekBar position_Sb, volume_Sb;
	private TextView position_Tv, total_Tv;

	private Handler handler = new Handler() {
		public void handleMessage(android.os.Message msg) {
			if (msg.what == 0x123) {
				updateTextView(total_Tv, mediaPlayer.getDuration());
				updateTextView(position_Tv, mediaPlayer.getCurrentPosition());
				position_Sb.setProgress(mediaPlayer.getCurrentPosition());
				handler.sendEmptyMessageDelayed(0x123, 1000);
			}
		};
	};

	/**
	 * 初始化控件
	 */
	private void initView() {
//		第二步
		position_Sb = (SeekBar) findViewById(R.id.position_sb);
		position_Sb.setMax(mediaPlayer.getDuration());
		//volume_Sb = (SeekBar) findViewById(R.id.volume_sb);
		position_Tv = (TextView) findViewById(R.id.position_tv);
		total_Tv = (TextView) findViewById(R.id.total_tv);
		viewEvent();
	}

	/**
	 * 为控件添加事件监听
	 */
	private void viewEvent() {
		//第三步
		position_Sb.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {

			@Override
			public void onStopTrackingTouch(SeekBar seekBar) {
				// TODO Auto-generated method stub
				mediaPlayer.seekTo(seekBar.getProgress());
				handler.sendEmptyMessage(0x123);
			}

			@Override
			public void onStartTrackingTouch(SeekBar seekBar) {
				// TODO Auto-generated method stub
				handler.removeMessages(0x123);
			}

			@Override
			public void onProgressChanged(SeekBar seekBar, int progress,
					boolean fromUser) {
				// TODO Auto-generated method stub
				updateTextView(position_Tv, seekBar.getProgress());

			}
		});
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		// 第一步  简单,但是若果要播放多首歌曲,就不适用了
		// mediaPlayer = MediaPlayer.create(this, R.raw.music);
		mediaPlayer = new MediaPlayer();
		try {
			String path = Environment.getExternalStorageDirectory()
					.getAbsolutePath() + "/DownLoad/music.mp3";
			mediaPlayer.setDataSource(path);

			// 执行setDataSource方法之后,MediaPlayer并未真正装载那些音频文件,还需要调用prepare()方法准备装载音频。
			mediaPlayer.prepare();
			//设置是否循环
			mediaPlayer.setLooping(false);
			//当一首歌播放完成后的监听的事件
			mediaPlayer.setOnCompletionListener(new OnCompletionListener() {

				@Override
				public void onCompletion(MediaPlayer mp) {
					// TODO Auto-generated method stub
					Toast.makeText(MainActivity.this, "完成", Toast.LENGTH_SHORT)
							.show();
				}
			});
			
			initView();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	public void start(View view) {
		mediaPlayer.start();
		handler.sendEmptyMessage(0x123);

	}

	public void pause(View view) {
		mediaPlayer.pause();
		handler.removeMessages(0x123);
	}

	/**
	 * 换算时间
	 * 
	 * @param textView
	 * @param millissecond
	 */
	private void updateTextView(TextView textView, int millissecond) {
		int second = millissecond / 1000;
		int hh = second / 3600;
		int mm = second % 3600 / 60;
		int ss = second % 60;

		String time = null;
		if (hh != 0) {
			time = String.format("%02d:%02d:%02d", hh, mm, ss);
		} else {
			time = String.format("%02d:%02d", mm, ss);
		}

		textView.setText(time);

	}

	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub

		if (mediaPlayer.isPlaying()) {
			mediaPlayer.stop();
			mediaPlayer.reset();
			mediaPlayer = null;
		}

		super.onDestroy();
	}
}



<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <SeekBar
        android:id="@+id/position_sb"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <TextView
            android:id="@+id/position_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="00:48" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="/" />

        <TextView
            android:id="@+id/total_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="04:40" />
    </LinearLayout>

    <SeekBar
        android:id="@+id/volume_sb"
        android:layout_width="200dp"
        android:layout_height="wrap_content" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="start"
        android:text="播放" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="pause"
        android:text="暂停" />

</LinearLayout>