播放视频的功能放在一个单独的Activity当中。我们将为它们设置横竖屏两种布局。
在竖屏的时候,上半部分播放视频,下半部分显示视频信息;
在设备旋转成横屏的时候,视频进行全屏播放;
当点击视频列表的视频项时,就启动播放器播放对应的视频。这里我们要创建一个名字叫做VideoPlayer
的Activity,用它来完成视频播放的任务。
另外,还要为ListView
添加一个数据项点击时的监听函数,
ListView
的OnItemClickListener
接口;Intent
;@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
VideoItem item = mVideoList.get(position);
Intent i = new Intent(this, VideoPlayer.class);
i.setData(Uri.parse(item.path));
startActivity(i);
}
这里使用的Intent
是安卓系统当中连接各个组件之间的桥梁,它可以,
播放视频可以使用Android SDK提供的现成的控件VideoView
。它是对media player
和surface
的封装,对于初次进行视频播放开发的我们,使用VideoView
是最简单和方便的,不用关注太多细节上的实现方式。
VideoView
的使用,非常简单,
在布局文件中放置一个VideoView
控件,
<VideoView
android:id="@+id/video_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
在Activity当中,获取布局文件中的VideoView
,让后设置要播放的视频地址,
mVideoView = (VideoView) findViewById(R.id.video_view);
mVideoView.setVideoPath(path);
使用VideoView
提供的接口,控制视频播放的流程,
//从头开始播放视频
mVideoView.start();
//暂停播放视频
mVideoView.pause();
//继续播放视频
mVideoView.resume()
//跳转到xxx毫秒处开始播放
mVideoView.seekTo(xxx);
还可以为VideoView
添加控制面板-MediaController
,这个面板集成了播放进度拖动、暂停、继续播放等功能,还可以自动隐藏或显示。如果VideoView
有父布局,那么为它添加的MediaController
是附着在父布局的底部的。因此为了界面美观,我们在布局文件中,将VideoView
单独放到一个FrameLayout
当中。
这里我们使用Android SDK自带的Media Controller
,
MediaController controller= new MediaController(context);
mVideoView.setMediaController(controller);
我们将竖屏的布局设计成上下两个部分,上面用VideoView
播放视频,下面用一个TableLayout
展示视频信息,
<?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:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical">
<FrameLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:layout_margin="10dp" android:background="@color/video_background_color">
<VideoView android:layout_gravity="center" android:id="@+id/video_view" android:layout_width="match_parent" android:layout_height="match_parent"/>
</FrameLayout>
<TableLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:layout_margin="10dp">
<TableRow>
<TextView android:text="@string/video_name"/>
<TextView android:id="@+id/video_title"/>
</TableRow>
<TableRow>
<TextView android:text="@string/video_width_height"/>
<TextView android:id="@+id/video_width_height"/>
</TableRow>
<TableRow>
<TextView android:text="@string/video_size"/>
<TextView android:id="@+id/video_size"/>
</TableRow>
<TableRow>
<TextView android:text="@string/created_time"/>
<TextView android:id="@+id/video_create_time"/>
</TableRow>
</TableLayout>
</LinearLayout>
这里把VideoView
当到了FrameLayout
当中,让播放的内容居中显示,并为这个区域设置了背景颜色。
通过启动VideoPlayer
的Intent
,获取视频播放的地址,
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Uri uri = getIntent().getData();
String path = uri.getPath();
......
}
通过播放地址,查询该视频相关的其他信息-视频标题、视频文件大小、视频尺寸、视频创建时间,
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
......
Uri path = uri.getPath();
String[] searchKey = new String[] {
MediaStore.Video.Media.TITLE,
MediaStore.Video.Media.WIDTH,
MediaStore.Video.Media.HEIGHT,
MediaStore.Images.Media.SIZE,
MediaStore.Images.Media.DATE_ADDED
};
String where = MediaStore.Video.Media.DATA + " = '" + path + "'";
String[] keywords = null;
String sortOrder = MediaStore.Video.Media.DEFAULT_SORT_ORDER;
Cursor cursor = getContentResolver().query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, searchKey, where, keywords, sortOrder);
if (cursor != null) {
if (cursor.getCount() > 0) {
cursor.moveToNext();
String createdTime = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATE_ADDED));
String name = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.TITLE));
int size = cursor.getInt(cursor.getColumnIndex(MediaStore.Video.Media.SIZE));
int width = cursor.getInt(cursor.getColumnIndex(MediaStore.Video.Media.WIDTH));
int height = cursor.getInt(cursor.getColumnIndex(MediaStore.Video.Media.HEIGHT));
VideoItem item = new VideoItem(path, name, createdTime);
TextView title = (TextView) findViewById(R.id.video_title);
title.setText(item.name);
TextView created = (TextView) findViewById(R.id.video_create_time);
created.setText(item.createdTime);
TextView screen = (TextView) findViewById(R.id.video_width_height);
screen.setText(width + "*" + height);
TextView fileSize = (TextView) findViewById(R.id.video_size);
fileSize.setText(String.valueOf(size / 1024 / 1024) + "M");
} else {
TextView title = (TextView) findViewById(R.id.video_title);
title.setText(R.string.unknown);
TextView created = (TextView) findViewById(R.id.video_create_time);
created.setText(R.string.unknown);
TextView screen = (TextView) findViewById(R.id.video_width_height);
screen.setText(R.string.unknown);
TextView fileSize = (TextView) findViewById(R.id.video_size);
fileSize.setText(R.string.unknown);
}
cursor.close();
}
......
}
获取VideoView
控件,并为VideoView
设置播放的视频。为播放界面添加了Android SDK自带的控制面板-MediaController
,
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
......
String path = uri.getPath();
mVideoView = (VideoView) findViewById(R.id.video_view);
mVideoView.setVideoPath(path);
MediaController controller = new MediaController(this);
mVideoView.setMediaController(controller);
}
有的时候,用户需要暂停播放的视频,可以通过控制面板上的按钮操作;但有的时候,正在播放的视频会被系统打断,例如来了一个电话,电话Activity优先级最高,会显示出来,让视频播放器暂停播放;或者用户在播放的时候,按下了Home
键,切换到了主屏幕,也需要暂停播放视频。当这些操作结束以后,再次把VideoPlayer
切换到前台的时候,我们会希望视频继续从刚才被打断的地方继续播放。
我们已经了解了Activity的生命周期,
从一个Activity创建出来,到显示,再到用户主动退出销毁这个Activity,它将经历:
onCreate()
->
onStart()
->
onResume()
->
用户可以与Activity交互->
onPause()
->
onStop()
->
onDestroy()
;
那么就可以选取其中的onResume()
与onPause()
,进行视频播放暂停和继续播放的操作。
在onPause()
中,暂停播放的视频,记录下当前播放的位置;在onResume()
中,从上次记录下中断的位置开始播放,
@Override
protected void onPause() {
super.onPause();
mVideoView.pause();
mLastPlayedTime = mVideoView.getCurrentPosition();
}
@Override
protected void onResume() {
super.onResume();
mVideoView.start();
if(mLastPlayedTime > 0) {
mVideoView.seekTo(mLastPlayedTime);
}
}