在上一篇写完使用MediaPlayer播放音乐之后,布局中有个可以播放视频文件的按钮,这一篇来把它完成。在这里说明一下:使用VideoView的好处是:如果你只是想要从手机中拿出视频文件来播放,VideoView自带快进快退,播放暂停的功能(它也可以用来播放音乐),还可以直接加入MediaController对象作为播放控制接口。虽然MediaPlayer也可以用来播放视频,但是必须自己准备视频的组件、播放进度条以及控制按钮。这一点,对于只需要播放视频文件来说,很麻烦。
首先我们还是来看布局文件(虽然基本没怎么改...):
activity布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.myapplication.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btnPickAudio"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="onPick"
android:text="选取音乐" />
<Button
android:id="@+id/btnPickVideo"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="onPick"
android:text="选取视频" />
</LinearLayout>
<TextView
android:id="@+id/txvName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="文件名" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btnPlay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onMpPlay"
android:text="播放"
/>
<Button
android:id="@+id/btnStop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onMpStop"
android:text="停止" />
<CheckBox
android:id="@+id/ckbLoop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="false"
android:onClick="onMpLoop"
android:text="重复播放" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="right"
android:orientation="horizontal">
<Button
android:id="@+id/lgbInfo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onMpInfo"
android:text="当前播放位置" />
<Button
android:id="@+id/lgbBackForward"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onMpBackWard"
android:text="后退" />
<Button
android:id="@+id/lgbForward"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onMpForward"
android:text="前进" />
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/txvUri"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="路径" />
</LinearLayout>
这里新建了一个VideoActivity,用来控制视频文件的播放
video布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_video"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
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.example.myapplication.Video">
<VideoView
android:id="@+id/videoView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:onClick="onMpStop" />
</LinearLayout>
万年不变的MainActivity
public class MainActivity extends AppCompatActivity implements MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener, MediaPlayer.OnCompletionListener {
Uri uri;
TextView txvName, txvUri;
boolean isVideo = false;
Button btnPlay, btnStop;
CheckBox ckbLoop;
MediaPlayer mper;
Toast tos;
String uri2="";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txvName = (TextView) findViewById(R.id.txvName);
txvUri = (TextView) findViewById(R.id.txvUri);
btnPlay = (Button) findViewById(R.id.btnPlay);
btnStop = (Button) findViewById(R.id.btnStop);
ckbLoop = (CheckBox) findViewById(R.id.ckbLoop);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);//屏幕不随手机旋转
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);//屏幕竖屏
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);//保持屏幕不休眠
uri = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.diantaiqingge);
txvName.setText("电台情歌");
txvUri.setText("程序内曲目:" + uri.toString());
mper = new MediaPlayer();
mper.setOnPreparedListener(this);
mper.setOnErrorListener(this);
mper.setOnCompletionListener(this);
tos = Toast.makeText(this, "", Toast.LENGTH_SHORT);
prepareMusic();
}
private void prepareMusic() {
btnPlay.setText("播放");
btnPlay.setEnabled(false);
btnStop.setEnabled(false);
try {
mper.reset();
mper.setDataSource(this, uri);
mper.setLooping(ckbLoop.isChecked());
mper.prepareAsync();
} catch (IOException e) {
tos.setText("指定音乐文件错误!" + e.toString());
tos.show();
}
}
public void onPick(View view) {
Intent it = new Intent(Intent.ACTION_GET_CONTENT);
if (view.getId() == R.id.btnPickAudio) {
it.setType("audio/*");
startActivityForResult(it, 100);
} else {
it.setType("video/*");
startActivityForResult(it, 101);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
if (requestCode == 100) {
isVideo = false;
uri = convertUri(data.getData());
txvName.setText(isVideo ? "视频" : "音频" + uri.getLastPathSegment());
txvUri.setText("文件位置:" + uri.getPath());
if (!isVideo) {
prepareMusic();
}
} else {
isVideo = true;
uri2=UriUtils.getPath(this,data.getData());
uri2="file://"+uri2;
//uri = convertUri(data.getData());
txvName.setText(isVideo ? "视频" : "音频" + uri2.toString());
txvUri.setText("文件位置:" + uri2.toString());
}
}
}
Uri convertUri(Uri uri) {
if (uri.toString().substring(0, 7).equals("content")) {//以content开头的图像文件需要转换成file开头的文件路径
String[] colName = {MediaStore.MediaColumns.DATA};//声明要查询的字段
Cursor cursor = getContentResolver().query(uri, colName, null, null, null);
cursor.moveToFirst();//移到查询结果的第一个记录
uri = Uri.parse("file://" + cursor.getString(0));//将路径转化为uri
cursor.close();
}
return uri;
}
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
//当准备好时,让播放按钮起作用
btnPlay.setEnabled(true);
}
@Override
public void onCompletion(MediaPlayer mediaPlayer) {
//当播放完毕时
mper.seekTo(0);//播放位置归0
btnPlay.setText("播放");
btnStop.setEnabled(false);
}
@Override
public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
tos.setText("发生错误,停止播放");
tos.show();
return true;
}
public void onMpPlay(View v) {
//视频播放
if (isVideo) {
Intent it = new Intent(this, Video.class);
it.putExtra("uri", uri2);
startActivity(it);
return;
}
//音乐播放
if (mper.isPlaying()) {//正在播放就暂停
mper.pause();
btnPlay.setText("继续");
} else {
mper.start();
btnPlay.setText("暂停");
btnStop.setEnabled(true);
}
}
public void onMpStop(View v) {
//音乐停止
mper.pause();
mper.seekTo(0);
btnPlay.setText("播放");
btnStop.setEnabled(false);
}
public void onMpLoop(View v) {
//是否循环
if (ckbLoop.isChecked()) {
mper.setLooping(true);
} else {
mper.setLooping(false);
}
}
public void onMpBackWard(View v) {
//前进
if (!btnPlay.isEnabled()) {
return;
}
int len = mper.getDuration();
int pos = mper.getCurrentPosition();
pos -= 10000;
if (pos < 0) {
pos = 0;
}
mper.seekTo(pos);
tos.setText("倒退10秒:" + pos / 1000 + "/" + len / 1000);
tos.show();
}
public void onMpForward(View v) {
//后退
if (!btnPlay.isEnabled()) {
return;
}
int len = mper.getDuration();
int pos = mper.getCurrentPosition();
pos += 10000;
if (pos > len) {//不可大于音频长度
pos = len;
}
mper.seekTo(pos);
tos.setText("前进10秒:" + pos / 1000 + "/" + len / 1000);
tos.show();
}
public void onMpInfo(View v) {
//当前播放位置
if (!btnPlay.isEnabled()) {//
return;
}
int len = mper.getDuration();
int pos = mper.getCurrentPosition();
mper.seekTo(pos);
tos.setText("当前位置:" + pos / 1000 + "/" + len / 1000);
tos.show();
}
@Override
protected void onPause() {
super.onPause();
if (mper.isPlaying()) {
btnPlay.setText("继续");
mper.pause();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
mper.release();
}
}
本例中新建的VideoActivity
public class Video extends AppCompatActivity implements MediaPlayer.OnCompletionListener {
VideoView vdv;
int pos = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);//隐藏系统状态栏
getSupportActionBar().hide();//隐藏Activity标题栏
setContentView(R.layout.activity_video);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
Intent it = getIntent();
Uri uri = Uri.parse(it.getStringExtra("uri"));
if (savedInstanceState != null) {
//如果因为旋转启动了activity
pos = savedInstanceState.getInt("pos", 0);//获取旋转钱的位置
}
vdv = (VideoView) findViewById(R.id.videoView);
MediaController mediaCtrl = new MediaController(this); //建立播放控制对象
vdv.setMediaController(mediaCtrl);//设置播放控制对象
vdv.setVideoURI(uri);
vdv.setOnCompletionListener(this);
}
@Override
protected void onResume() {
super.onResume();
//重启或者暂停后启动
vdv.seekTo(pos);
vdv.start();
}
@Override
protected void onPause() {
super.onPause();
//暂停时
pos = vdv.getCurrentPosition();//获取当前的位置
vdv.stopPlayback();//停止播放
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
//当屏幕旋转时,会销毁当前的activity再重启一个activity,可在此方法中存储销毁之前的视频播放位置
outState.putInt("pos", pos);
}
@Override
public void onCompletion(MediaPlayer mediaPlayer) {
finish();
}
}
大家可以看到,在这一篇中获取文件的uri我选用了一个工具类UriUtils,这个方法取自Jenly_Yu的http://blog.csdn.net/jenly121/article/details/48373861的博客,大家可以去看看。至于使用这个方法的原因:在我获取视频、音频文件的uri的时候,我使用360手机和华为手机隐式调用获取uri,同样的方法,在360N4手机下的视频(或音频)分类中可以获取到完整uri,而使用华为Mate7手机一直返回null,但是如果同样在系统管理器中打开,都可以获取uri。刚开始怀疑手机的问题,后来使用了上述那位朋友的方式,就都可以获取到,这个工具类还是蛮好用的,推荐给大家。
音频、视频我分别采用了不同的获取uri的方式,大家可以好好看看,自己选择想使用的方式。就到这里。
转载注明出处http://blog.csdn.net/u011771800/article/details/54091027。