之前写的那篇帖子采用的方法是将 Libgdx 的 GLSurfaceView 隐藏,再将 MediaPlayer 绑定的 SurfaceView添加到 Activity 的 ContentView,后来测试这种方法虽然可以播放视频,然用户按下Home或电源键时,Activity 会收到 onPause 事件,再次返回的时候 系统没有调用 onResume() 游戏就卡死了,没有响应,这样显然不行!
后来在 StackOverflow 上看到有人这样解决的:
SurfaceView.setZOrderMediaOverlay(boolean isMediaOverlay)
官方文档的大概意思是:将该 SurfaceView 作为一个浮动的View显示在其他窗口的上面,而不改变该窗口的 Zorder,
试了一下果然管用,还有另外一个方法是:
SurfaceView.setZOrderOnTop(boolean onTop);
这个方法是直接改变 SurfaceView 的 ZOrder,会覆盖掉在他上面的控件,有些地方不方便。
下面附上我封装的一个 VideoView 源码:
1: package com.pobaby.shot;
2:
3: import java.io.IOException;
4:
5: import android.media.MediaPlayer;
6: import android.net.Uri;
7: import android.util.Log;
8: import android.view.MotionEvent;
9: import android.view.SurfaceHolder;
10: import android.view.SurfaceView;
11: import android.view.View;
12:
13: import com.badlogic.gdx.Gdx;
14:
15: public class VideoView extends SurfaceView implements SurfaceHolder.Callback, View.OnTouchListener, MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener, MediaPlayer.OnInfoListener,
16: MediaPlayer.OnCompletionListener {
17: private MediaPlayer mPlayer; // MediaPlayer对象
18: private GameActivity gameActivity;
19: private int resId;
20: private boolean surfaceCreated;
21:
22: public VideoView(GameActivity context) {
23: super(context);
24:
25: this.gameActivity = context;
26:
27: final SurfaceHolder holder = getHolder();
28: holder.addCallback(this); // 设置回调接口
29: holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); // 设置为Buffer类型(播放视频&Camera预览)
30: setOnTouchListener(this);
31:
32: mPlayer = new MediaPlayer();
33: mPlayer.setScreenOnWhilePlaying(true);
34:
35: mPlayer.setOnPreparedListener(this);
36: mPlayer.setOnCompletionListener(this);
37: mPlayer.setOnErrorListener(this);
38: mPlayer.setOnInfoListener(this);
39: }
40:
41: public void setVideo(int resId) {
42: // Log.i(PobabyGame.TAG, "== setVideo ! == ");
43:
44: this.resId = resId;
45: Uri uri = Uri.parse("android.resource://" + gameActivity.getPackageName() + "/" + resId);
46:
47: try {
48: mPlayer.setDataSource(gameActivity, uri);
49: } catch (IllegalArgumentException e) {
50: } catch (SecurityException e) {
51: } catch (IllegalStateException e) {
52: } catch (IOException e) {
53: }
54: }
55:
56: @Override
57: public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
58: }
59:
60: @Override
61: public void surfaceCreated(final SurfaceHolder holder) {
62: surfaceCreated = true;
63:
64: mPlayer.setDisplay(holder); // 指定SurfaceHolder
65:
66: gameActivity.handler.post(new Runnable() {
67: @Override
68: public void run() {
69: try {
70: mPlayer.prepare();
71: } catch (IllegalStateException e1) {
72: } catch (IOException e1) {
73: }
74: }
75: });
76: }
77:
78: @Override
79: public void surfaceDestroyed(SurfaceHolder holder) {
80: surfaceCreated = false;
81:
82: mPlayer.stop();
83: mPlayer.reset();
84: }
85:
86: @Override
87: public void onPrepared(MediaPlayer player) {
88: int wWidth = Gdx.graphics.getWidth();
89: int wHeight = Gdx.graphics.getHeight();
90:
91: /* 获得视频宽长 */
92: int vWidth = mPlayer.getVideoWidth();
93: int vHeight = mPlayer.getVideoHeight();
94:
95: /* 最适屏幕 */
96: float wRatio = (float) vWidth / (float) wWidth; // 宽度比
97: float hRatio = (float) vHeight / (float) wHeight; // 高度比
98: float ratio = Math.max(wRatio, hRatio); // 较大的比
99: vWidth = (int) Math.ceil((float) vWidth / ratio); // 新视频宽度
100: vHeight = (int) Math.ceil((float) vHeight / ratio); // 新视频高度
101:
102: // 改变SurfaceHolder大小
103: getHolder().setFixedSize(vWidth, vHeight);
104: mPlayer.seekTo(posttion);
105: mPlayer.start();
106: }
107:
108: @Override
109: public void onCompletion(MediaPlayer mp) {
110: // Toast.makeText(gameActivity, "video finished!", Toast.LENGTH_SHORT).show();
111:
112: mPlayer.release();
113: gameActivity.videoFinish(resId);
114: }
115:
116: @Override
117: public boolean onInfo(MediaPlayer mp, int what, int extra) {
118: Log.i(PobabyGame.TAG, String.format("onInfo(%d, %d)", what, extra));
119: return true;
120: }
121:
122: @Override
123: public boolean onError(MediaPlayer mp, int what, int extra) {
124: Log.e(PobabyGame.TAG, String.format("onError(%d, %d)", what, extra));
125: return true;
126: }
127:
128: @Override
129: public boolean onTouch(View v, MotionEvent event) {
130: if (event.getAction() == MotionEvent.ACTION_DOWN) {
131: if (gameActivity.button.getVisibility() == View.VISIBLE) {
132: gameActivity.button.setVisibility(View.GONE);
133: } else {
134: gameActivity.button.setVisibility(View.VISIBLE);
135: }
136: }
137:
138: return true;
139: }
140:
141: public void finish() {
142: mPlayer.stop(); // 大概不会调用 MediaPlayer.onCompletion
143: mPlayer.release();
144: gameActivity.videoFinish(resId);
145: }
146:
147:
148: int posttion;
149: public void pause() {
150: // Log.i(PobabyGame.TAG, "pause");
151:
152: posttion = mPlayer.getCurrentPosition();
153: mPlayer.pause();
154: }
155:
156: /**
157: * 暂停的时候,系统会销毁 SurfaceView ,所以在resume的时候相对于重新设置MediaPlayer
158: */
159: public void resume() {
160: // Log.i(PobabyGame.TAG, "resume");
161:
162: if(surfaceCreated){
163: mPlayer.start();
164: }else {
165: Uri uri = Uri.parse("android.resource://" + gameActivity.getPackageName() + "/" + resId);
166: try {
167: mPlayer.setDataSource(gameActivity, uri);
168: } catch (IllegalArgumentException e) {
169: } catch (IllegalStateException e) {
170: } catch (IOException e) {
171: }
172: }
173: }
174: }