Android SurfaceView的生命周期
本文利用SurfaceView来实现视频的播放
本文地址:http://www.cnblogs.com/wuyudong/p/5851156.html,转载请注明源地址。
在main.xml布局文件添加用于视频画面绘制的SurfaceView 控件:
<SurfaceView android:layout_width="fill_parent" android:layout_height="240dip" android:id="@+id/surfaceView" />
项目布局设计:
<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=".MainActivity" > <EditText
android:id="@+id/et_path"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="请输入视频文件的路径" /> <LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" > <Button
android:id="@+id/bt_play"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="播放" /> <Button
android:id="@+id/bt_pause"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="暂停" /> <Button
android:id="@+id/bt_replay"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="重播" /> <Button
android:id="@+id/bt_stop"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="停止" />
</LinearLayout> <SurfaceView
android:id="@+id/sv"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/> </LinearLayout>
大部分代码和《Android 多媒体播放API简介》中的完全一样,修改一点点代码即可:
public class MainActivity extends Activity implements OnClickListener {
private EditText et_path;
private Button bt_play, bt_replay, bt_pause, bt_stop;
private SurfaceView sv;
private MediaPlayer mediaPlayer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sv = (SurfaceView)findViewById(R.id.sv);
et_path = (EditText) findViewById(R.id.et_path);
bt_play = (Button) findViewById(R.id.bt_play);
bt_replay = (Button) findViewById(R.id.bt_replay);
bt_pause = (Button) findViewById(R.id.bt_pause);
bt_stop = (Button) findViewById(R.id.bt_stop);
bt_pause.setOnClickListener(this);
bt_play.setOnClickListener(this);
bt_replay.setOnClickListener(this);
bt_stop.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt_play:
play();
break;
case R.id.bt_replay:
replay();
break;
case R.id.bt_stop:
stop();
break;
case R.id.bt_pause:
pause();
break;
default:
break;
}
}
/**
* 暂停音乐
*/
private void pause() {
if ("继续".equals(bt_pause.getText().toString().trim())) {
mediaPlayer.start();
bt_pause.setText("暂停");
return;
}
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.pause();
bt_pause.setText("继续");
return;
}
}
/**
* 重新播放
*/
private void replay() {
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.seekTo(0);
return;
}
play();
}
/**
* 停止播放音乐
*/
private void stop() {
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer.release(); // 记得释放资源
mediaPlayer = null;
bt_play.setEnabled(true);
}
}
/**
* 播放音乐
*/
private void play() {
String path = et_path.getText().toString().trim();
File file = new File(path);
if (file.exists() && file.length() > 0) {
try {
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
/* 设置Video影片以SurfaceHolder播放 */
mediaPlayer.setDisplay(sv.getHolder());
mediaPlayer.setDataSource(path);
mediaPlayer.prepare(); // might take long! (for buffering, etc)
mediaPlayer.start();
mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
bt_play.setEnabled(true);
}
} );
bt_play.setEnabled(false);
} catch (Exception e) {
Toast.makeText(this, "播放失败", 0).show();
e.printStackTrace();
}
} else {
Toast.makeText(this, "文件不存在", 0).show();
}
}
}
运行项目效果如下:

但是上面的代码有点问题,那就是当点击home或返回屏幕主界面后,在回到播放页面,视频黑屏
原因:
SurfaceView内部维护双缓冲,消耗内存资源
如果发现当前SurfaceView 用户可见的时候,创建SurfaceView的holder
如果SurfaceView变成用户不可见的时候 销毁SurfaceView的holder
为了观察SurfaceView的生命周期,可以添加下面的代码进行打印追踪:
sv.getHolder().addCallback(new Callback() {
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
System.out.println("holder被销毁了");
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
System.out.println("holder被创建了");
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
System.out.println("holder的大小变化了");
}
});
}
logcat中打印下面的信息:
09-07 11:36:34.613: I/System.out(28858): holder被创建了
09-07 11:36:34.623: I/System.out(28858): holder的大小变化了
返回主界面
09-07 11:39:08.245: I/System.out(28858): holder被销毁了
再次回到视频界面
09-07 11:39:39.405: I/System.out(28858): holder被创建了
09-07 11:39:39.405: I/System.out(28858): holder的大小变化了
可以看到,每次回到视频界面,holder都会被重新创建
修改后的代码如下:
public class MainActivity extends Activity implements OnClickListener {
private EditText et_path;
private Button bt_play, bt_replay, bt_pause, bt_stop;
private SurfaceView sv;
private MediaPlayer mediaPlayer;
private int currentPosition;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sv = (SurfaceView) findViewById(R.id.sv);
et_path = (EditText) findViewById(R.id.et_path);
bt_play = (Button) findViewById(R.id.bt_play);
bt_replay = (Button) findViewById(R.id.bt_replay);
bt_pause = (Button) findViewById(R.id.bt_pause);
bt_stop = (Button) findViewById(R.id.bt_stop);
bt_pause.setOnClickListener(this);
bt_play.setOnClickListener(this);
bt_replay.setOnClickListener(this);
bt_stop.setOnClickListener(this);
sv.getHolder().addCallback(new Callback() {
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
System.out.println("holder被销毁了");
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
currentPosition = mediaPlayer.getCurrentPosition();
stop();
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
System.out.println("holder被创建了");
if (currentPosition > 0) {
play(currentPosition);
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
System.out.println("holder的大小变化了");
}
});
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt_play:
play(0);
break;
case R.id.bt_replay:
replay();
break;
case R.id.bt_stop:
stop();
break;
case R.id.bt_pause:
pause();
break;
default:
break;
}
}
/**
* 暂停音乐
*/
private void pause() {
if ("继续".equals(bt_pause.getText().toString().trim())) {
mediaPlayer.start();
bt_pause.setText("暂停");
return;
}
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.pause();
bt_pause.setText("继续");
return;
}
}
/**
* 重新播放
*/
private void replay() {
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.seekTo(0);
return;
}
play(0);
}
/**
* 停止播放音乐
*/
private void stop() {
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer.release(); // 记得释放资源
mediaPlayer = null;
bt_play.setEnabled(true);
}
}
/**
* 播放音乐
*/
private void play(final int currentPosition) {
String path = et_path.getText().toString().trim();
File file = new File(path);
if (file.exists() && file.length() > 0) {
try {
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
/* 设置Video影片以SurfaceHolder播放 */
mediaPlayer.setDisplay(sv.getHolder());
mediaPlayer.setDataSource(path);
mediaPlayer.prepare(); // might take long! (for buffering, etc)
mediaPlayer.start();
mediaPlayer.setOnPreparedListener(new OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mediaPlayer.seekTo(currentPosition);
}
});
mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
bt_play.setEnabled(true);
}
});
bt_play.setEnabled(false);
} catch (Exception e) {
Toast.makeText(this, "播放失败", 0).show();
e.printStackTrace();
}
} else {
Toast.makeText(this, "文件不存在", 0).show();
}
}
}
Android SurfaceView的生命周期的更多相关文章
- Android Activity的生命周期简单总结
Android Activity的生命周期简单总结 这里的内容参考官方的文档,这篇文章的目的不是去总结Activity是如何启动,如何创造,以及暂停和销毁的,而是从实际开发中分析在Activity各个 ...
- android开发之生命周期
android开发之生命周期 一:Activity的生命周期: 这几天了了解了安卓Activity的生命周期,对于生命周期有了大概的理解: 一个Activity的生命周期也就是Activity从生成到 ...
- Android内的生命周期整理
1. Android App的生命周期: 2. Application的生命周期: 3. Activity的生命周期: 3.1 Fragment的生命周期: 4. Service的生命周期:5. Br ...
- Android开发——Activity生命周期
Android开发--Activity生命周期 Activity作为四大组件之首,也是使用最频繁的一种组件.本文将主要讲解Activity生命周期,包括正常情况下的Activity生命周期和异常情况下 ...
- 重温Android和Fragment生命周期
重温下Android和Fragment生命周期,理解生命周期方法的作用,什么时候调用,可以做一些什么操作. 1.Android生命周期 1.1 生命周期图 1.2 生命周期函数说明 onCreate: ...
- Xamarin.Android活动的生命周期
一.前言 用过Android手机的人一定会发现一种现象,当你把一个应用置于后台后,一段时间之后在打开就会发现应用重新打开了,但是之前的相关的数据却没有丢失.可以看出app的“生命”是掌握在系统手上的, ...
- Android:Activity生命周期
Android是使用任务(Task)来管理活动的,一个任务就是一组存放在栈里的活动的集合,这个栈也被称作返回栈(Back Stack). 栈是一种后进先出的数据结构,在默认情况下,每当我们启动了一个新 ...
- Android targetSdkVersion 对生命周期的影响
一直都认为当手机进入休眠时,Activity的生命周期会进入onPause()-->onStop()状态,但是今天偶然遇到了一个百思不得其解的问题,如果在AndroidMainfest.xml文 ...
- Android MediaPlayer的生命周期
MediaPlayer的状态转换图也表征了它的生命周期,如下: 这张状态转换图清晰的描述了MediaPlayer的各个状态,也列举了主要的方法的调用时序,每种方法只能在一些特定的状态下使用,如果使用时 ...
随机推荐
- CentOS7上让Jexus开机自启动
昨天刚用了一下CentOS7,很自然的就安装了mono和Jexus,用的都是目前最新版mono4.2.2.10和jexus5.8.0 mono和jexus的具体安装方法,园子里已经有了很多教程,这里就 ...
- TFS 2012 在IE11和Chrome (Windows 8.1) 显示英文的解决方案
1.如果使用IE11浏览TFS Web显示英文,请执行以下操作: 控制面板——>语言——>高级设置 将“替代Windows显示语言”改为“中文(中华人民共和国)”,同时勾选“Web语言”下 ...
- QQ--模拟发表带图说说
发表说说之前,必须登录. 模拟QQ登录 >> http://www.cnblogs.com/deeround/p/4386629.html 发表带图说说,自然少不了上传图片,我这使用的PC ...
- 新浪微博.Net SDK第三版源代码和示例【最后一次更新了】
时间过得飞快,距离上次SDK更新已经3年有余.随着官方的不断跟新,老版SDK的部分接口已经不能正常使用.因此在QQ群里来吐槽的.来谩骂的朋友也开始多了起来.随着时代的发展,微博已经彻底的被微信甩开,因 ...
- php.ini 配置详细选项
php.ini 或 php3.ini 是 PHP 在启动时会读取的配置文件.该文件的存放路径为 /usr/local/lib/.在 PHP 3.x 版的配置文件为 php3.ini:而在 PHP 4. ...
- win10下vs2015创建asp,net core项目并运行在ubuntu14.04下
上文说了.net core程序在win10与ubuntu下运行,用的是示例程序(https://github.com/aspnet/cli-samples),今天用vs2015 构建asp.net c ...
- jquery选择器(综合)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Firemonkey TEdit 切换不同 KeyboardType 样式
用代码切换 Edit 不同的键盘样式: procedure TForm1.Button1Click(Sender: TObject); begin Edit1.KeyboardType := TVir ...
- ==与equals()
java中的比较有很多种 1.== 2.equals() 3.< 或 >或 != 4.instanceof 5.compareTo 1.什么时候用"==" 什么时候用& ...
- 2016 年青岛网络赛---Sort(k叉哈夫曼)
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5884 Problem Description Recently, Bob has just learn ...