Android中的多媒体音频和视频播放

时间:2020-12-02 05:52:34

智能手机的出现使得手机成为一个便携式多媒体播放器。这种看起来随意、理所当然的强大功能在Android中是如何实现的呢?

1.音频播放MediaPlayer

装载音频文件:

(1)static MediaPlayer create(Content,Uri)

从指定Uri来装载音频文件,并返回新创建的MediaPlayer对象。

(2)static MediaPlayer create(Content,intresid)

从redid资源ID来装载音频文件,并返回新创建的MediaPlayer对象。

(3)MediaPlayerm = new MediaPlayer()创建一个MediaPlayer对象,三种不同方法加载不同位置的音频文件:

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

 

setDataSource(Context,Uri):指定装载Uri所代表的文件,该方法可以播放来自网络的音乐

 

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

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

操作音频文件:

之上三种装载文件方法第一、二种方法不需要调用prepare()方法,因为其方法中已经封装了该方法,第三种装载方式需要在装载完毕后调用prepare()方式使播放器进入就绪状态。而前两种装载方式存在明显的弊端:一个播放器对象只能播放一个音频文件。

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

stop():停止播放

pause():暂停播放

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

监听器

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

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

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

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

 

2. AudioManager用来完成对音量大小,声音模式(静音,震动,震动加声音等模式)的管理

获取对象AudioManager:getSystemService(AUDIO_SERVICE)

修改音量:

  adjustVolume(direction,flag)   修改音量

  adjustStreamVolume(streamType,direction,flag) 修改音频流和音量

  direction的值:

             AudioManager.ADJUST_LOWER(降低)

             AudioManager.ADJUST_RAISE(升高)

             AudioManager.ADJUST_SAME(维持原来的)

  flag的值:

          AudioManager.FLAG_SHOW_UI 会弹出调节音量的界面

          AudioManager.FLAG_ALLOW_RINGER_MODES:最低声音会振动

  streamType:的值:

     AudioManager.STREAM_VOICE_CALL(通话)

       AudioManager.STREAM_SYSTEM(系统声音)

     AudioManager.STREAM_RING(铃声)

       AudioManager.STREAM_MUSIC(音乐)

      AudioManager.STREAM_ALARM(闹铃)

   setStreamVolume(stream,vol,flag) 设置指定音频流的音量

   getStreamMaxVolume(stream) 获取指定音频流的最大音量

   getStreamVolume(stream)       获取指定音频流的当前音量

 

以下通过一个简单的音乐播放器对MediaPlayer做一个简单的实现,其中包括播放暂停及进度调整、音量调整。布局文件如下:

<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"
    tools:context="com.briup.musicplayer.MainActivity" >

    <ToggleButton
        android:id="@+id/play"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textOff="播放"
        android:textOn="暂停" />

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

    <TextView
        android:id="@+id/time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingLeft="10dp" />

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

</LinearLayout>

MainActivity类文件如下

import java.io.IOException;

import android.app.Activity;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;

public class MainActivity extends Activity {

	private ToggleButton player;
	private SeekBar music, sound;
	private TextView time;

	private MediaPlayer mediaPlayer;

	private AudioManager audioManager;

	private Handler handler = new Handler() {
		public void handleMessage(android.os.Message msg) {
			if (msg.what == 0x123) {
				time.setText(convertion(mediaPlayer.getCurrentPosition()) + "/"
						+ convertion(mediaPlayer.getDuration()));
				music.setProgress(mediaPlayer.getCurrentPosition());
			}
		};
	};

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

		player = (ToggleButton) findViewById(R.id.play);
		music = (SeekBar) findViewById(R.id.music_sb);
		sound = (SeekBar) findViewById(R.id.sound_sb);
		time = (TextView) findViewById(R.id.time);

		audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
<span style="white-space:pre">		</span>{
		mediaPlayer = MediaPlayer.create(this, R.raw.befor);
		// MediaPlayer创建及音频文件装载并准备就绪
<span style="white-space:pre">		</span>}//文件装载位置
		int stime = mediaPlayer.getDuration();// 获取当前音频总时长
		int ltime = mediaPlayer.getCurrentPosition();// 获取当前音频播放进度
		time.setText(convertion(ltime) + "/" + convertion(stime));// 转换为分秒

		music.setMax(mediaPlayer.getDuration());// 设置进度条的最大值
		// 开关控制播放暂停
		player.setOnCheckedChangeListener(new OnCheckedChangeListener() {

			@Override
			public void onCheckedChanged(CompoundButton buttonView,
					boolean isChecked) {
				if (isChecked) {
					mediaPlayer.start();// 播放
					new Thread() {
						public void run() {
							while (mediaPlayer.isPlaying()) {
								try {
									handler.sendEmptyMessage(0x123);
									sleep(1000);
								} catch (InterruptedException e) {
									e.printStackTrace();
								}
							}
						};
					}.start();
				} else {
					mediaPlayer.pause();// 暂停
				}
			}
		});
		// 音频播放完成回调,但是如果设置为循环播放则不会回调
		mediaPlayer.setOnCompletionListener(new OnCompletionListener() {

			@Override
			public void onCompletion(MediaPlayer mp) {
				Toast.makeText(MainActivity.this, "播放结束", Toast.LENGTH_SHORT)
						.show();
			}
		});
		// 音频无法播放时回调
		mediaPlayer.setOnErrorListener(new OnErrorListener() {

			@Override
			public boolean onError(MediaPlayer mp, int what, int extra) {
				Toast.makeText(MainActivity.this, "音频无法播放", Toast.LENGTH_SHORT)
						.show();
				return false;
			}
		});
		// mediaPlayer.setLooping(true);//设置是否循环播放
		// 音乐进度调节
		music.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {

			@Override
			// 当拖动条拖动停止时调用
			public void onStopTrackingTouch(SeekBar seekBar) {
				mediaPlayer.seekTo(music.getProgress());
			}

			@Override
			public void onStartTrackingTouch(SeekBar seekBar) {
			}

			@Override
			public void onProgressChanged(SeekBar seekBar, int progress,
					boolean fromUser) {
			}
		});

		sound.setMax(audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC));// 获取设备播放音乐的最大音量
		sound.setProgress(audioManager
				.getStreamVolume(AudioManager.STREAM_MUSIC));// 设置默认音量为当前设备音量
		sound.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {

			@Override
			public void onStopTrackingTouch(SeekBar seekBar) {
			}

			@Override
			public void onStartTrackingTouch(SeekBar seekBar) {
			}

			@Override
			// 拖动条拖动的时候就要改变音量
			public void onProgressChanged(SeekBar seekBar, int progress,
					boolean fromUser) {
				audioManager.setStreamVolume(AudioManager.STREAM_MUSIC,
						progress, AudioManager.FLAG_SHOW_UI);// 拖动的时候显示系统调音窗
			}
		});
	}

	// 换算毫秒数为分秒,会有十分位误差
	private String convertion(int time) {
		int m = time / 1000 / 60;
		int s = time / 1000 % 60;
		return m + ":" + s;
	}
}

其他装载方法:

需要两项权限来读取SD卡

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

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

 

mediaPlayer = new MediaPlayer();
		try {
			// 音频文件是sd卡文件
			if (Environment.getExternalStorageState().equals(
					Environment.MEDIA_MOUNTED)) {
				String path = Environment.getExternalStorageDirectory()
						.getAbsolutePath();
				mediaPlayer.setDataSource(path + "/befor.mp3");
				// mediaPlayer.setDataSource("sdcard/befor.mp3");
				mediaPlayer.prepare();// 让MediaPlayer进入准备状态
			} else {
				Toast.makeText(MainActivity.this, "SD卡不可用", Toast.LENGTH_SHORT)
						.show();
			}
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalStateException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
mediaPlayer = new MediaPlayer();
		try {
			//音频文件是资源文件
			mediaPlayer.setDataSource(this,
			Uri.parse("android.resource://"+getPackageName()+"/"+R.raw.befor));
			mediaPlayer.setDataSource(this,
			Uri.parse("http://www.baidu.music"));
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalStateException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

效果如下

 Android中的多媒体音频和视频播放Android中的多媒体音频和视频播放Android中的多媒体音频和视频播放

3.视频播放VideoView

调用setVideoPath(path)指定要播放的资源或者调用setVideoURI(Uri uri)加载uri对应的视频

调用VideoView中的start,stop,pause方法控制视频播放

和MediaController类一起使用,它可以提供一个友好的图形控制界面,             

       MediaController mc = new MediaController(this);//设置播放控制器    

       video.setMediaController(mc);设置播放控制器来控制其播放

注意:VideoView需要标准mp4,3gp的视频,否则无法播放。

以下一个简单的视频播放器做一个简单的测试,布局文件如下

<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="com.briup.playvidio.MainActivity" >

    <ToggleButton
        android:id="@+id/tb"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textOff="播放"
        android:textOn="暂停" />

    <VideoView
        android:id="@+id/vv"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

MainActivity类文件如下

import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.MediaController;
import android.widget.Toast;
import android.widget.ToggleButton;
import android.widget.VideoView;

public class MainActivity extends Activity {
	private VideoView videoView;
	private ToggleButton player;

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

		videoView = (VideoView) findViewById(R.id.vv);
		player = (ToggleButton) findViewById(R.id.tb);

		// 获取视频地址
		if (Environment.getExternalStorageState().equals(
				Environment.MEDIA_MOUNTED)) {
			videoView.setVideoPath("sdcard/vvm.mp4");
		} else {
			Toast.makeText(this, "SD卡不可用", Toast.LENGTH_SHORT).show();
		}
		// 开关控制播放暂停
		player.setOnCheckedChangeListener(new OnCheckedChangeListener() {

			@Override
			public void onCheckedChanged(CompoundButton buttonView,
					boolean isChecked) {
				if (isChecked) {
					videoView.start();
				} else {
					videoView.pause();
				}
			}
		});

		// 视屏控制器控制播放暂停、快进退、进度
		MediaController mediaController = new MediaController(this);
		videoView.setMediaController(mediaController);

	}

}

需要两项权限来读取SD卡

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

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

效果如下

 Android中的多媒体音频和视频播放Android中的多媒体音频和视频播放