【Libgdx 原创】在 Libgdx 中播放视频实例
2012-10-23 22:03
351 查看
我现在做的一款游戏使用 Libgdx ,其中需要播放小段视频过度游戏场景,想到传统的办法是跳转 Activity ,显然这样做不是我会选择的!
我想直接在当前游戏 Activity 中插播视频。
播放视频其实只需要:MediaPlayer 和 SurfaceView
刚开始在网上找到了一段这样的实例代码,拿来用没问题
[/code]
这里最主要的就是: MediaPlayer.setDisplay(),新建一个SurfaceView,将 SurfaceView 的 SurfaceHolder 设置给 MediaPlayer 然后设置播放视频,prepare() 、 start() 就可以正常播放视频了,不过据说只支持 .mp4 .3gp,我没亲测。
起初这段源代码给我带来帮助,在感谢原作者之余他也在代码里设下了一个陷阱,作者当时估计没测试到就是!
如果你使用这段代码,在有些手机上是可以正常播放视频的,而有些手机就是不行(你只能听见声音、看不到画面),系统没给任何提示,只有2个警告信息,如下图:
于是百度“mediaPlayer错误信息”得知 35 在 native 层是这样定义的:const PVMFStatus PVMFInfoTrackDisable = 35;
于是 Google “PVMFInfoTrackDisable ” 果然有人跟我遇到同样的问题,在 stackoverflow 论坛有一篇这样的帖子:
http://stackoverflow.com/questions/7509818/android-mediaplayer-sometimes-no-video-is-played-even-though-audio-plays
这里不得不说下,stackoverflow 论坛能够找到你遇到的各种疑难杂症,嘿嘿!
这里面说法很多,但没找到根本原因,倒是在另外一篇帖子找到了答案:
这哥们才发现了问题的根本,大概意思就是:在 surfaceCreated 没被系统调用之前,SurfaceView 的 SurfaceHolder 是无效的,而我们一般习惯在 MediaPlayer 构造完后就给他设置数据,而我在 surfaceCreated 才调用了 mPlayer.setDisplay(holder); 这样 MediaPlayer 就没有设置显示器就开始播放了,这样自然看不到画面,而后来系统调用 surfaceCreated 的时候是于事无补的!
这也难怪看到有些人回复说第二次在播放视频的时候就可以,因为前面第一次设置了 holder 嘛!
知道了问题的根本就好办了, 在 surfaceCreated 里设置 holder,然后设置视频数据,然后调用 prepare,这样总是没问题了吧!
下面贴上我封装的一个 VideoPlayer :
[/code]
我想直接在当前游戏 Activity 中插播视频。
播放视频其实只需要:MediaPlayer 和 SurfaceView
刚开始在网上找到了一段这样的实例代码,拿来用没问题
[code] public class VideoPlayerActivity extends Activity implements
MediaPlayer.OnCompletionListener,
MediaPlayer.OnPreparedListener,
SurfaceHolder.Callback,
OnClickListener {
private SurfaceView surfaceView;
private MediaPlayer mPlayer; // MediaPlayer对象
private SurfaceHolder mSurfaceHolder; // SurfaceHolder对象
private Button mSkipVideoBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(0x400, 0x400);
setContentView(R.layout.video_player);
surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
/* 初始化mSurfaceHolder */
mSurfaceHolder = surfaceView.getHolder();
mSurfaceHolder.addCallback(this); // 设置回调接口
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); // 设置为Buffer类型(播放视频&Camera预览)
/* 初始化MediaPlayer */
mPlayer = MediaPlayer.create(this, getIntent().getIntExtra("resId", R.raw.video2));
mPlayer.setOnPreparedListener(this);
mPlayer.setOnCompletionListener(this);
mSkipVideoBtn = (Button) findViewById(R.id.button1);
mSkipVideoBtn.setOnClickListener(this);
}
@Override
protected void onDestroy() {
mPlayer.release();
super.onDestroy();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// TODO Auto-generated method stub
String s = "#E0D8C8";
int c = Integer.parseInt(s, 16);
surfaceView.setBackgroundColor(Color.rgb(c>>24, (c>>16)&0x0000ff00, c&0x000000ff));
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
mPlayer.setDisplay(holder); // 指定SurfaceHolder
// mPlayer.prepareAsync(); // 异步准备(将回调OnPreparedListener接口)
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
@Override
public void onPrepared(MediaPlayer player) {
/* 获得窗口宽长 */
Display display = getWindowManager().getDefaultDisplay();
int wWidth = display.getWidth();
int wHeight = display.getHeight();
/* 获得视频宽长 */
int vWidth = mPlayer.getVideoWidth();
int vHeight = mPlayer.getVideoHeight();
/* 最适屏幕 */
float wRatio = (float) vWidth / (float) wWidth; // 宽度比
float hRatio = (float) vHeight / (float) wHeight; // 高度比
float ratio = Math.max(wRatio, hRatio); // 较大的比
vWidth = (int) Math.ceil((float) vWidth / ratio); // 新视频宽度
vHeight = (int) Math.ceil((float) vHeight / ratio); // 新视频高度
// 改变SurfaceHolder大小
mSurfaceHolder.setFixedSize(vWidth, vHeight);
// 设置新布局参数(这在samsung i9088上出现stretch的错误==)
// surfaceView.setLayoutParams(new LinearLayout.LayoutParams(vWidth,
// vHeight));
// 启动播放
mPlayer.start();
}
@Override
public void onCompletion(MediaPlayer mp) {
// mSkipVideoBtn.setText("开始游戏");
// Toast.makeText(this, "播放完毕!", Toast.LENGTH_SHORT).show();
finish();
}
@Override
public void onClick(View v) {
mPlayer.stop();
finish();
}
}
[/code]
这里最主要的就是: MediaPlayer.setDisplay(),新建一个SurfaceView,将 SurfaceView 的 SurfaceHolder 设置给 MediaPlayer 然后设置播放视频,prepare() 、 start() 就可以正常播放视频了,不过据说只支持 .mp4 .3gp,我没亲测。
起初这段源代码给我带来帮助,在感谢原作者之余他也在代码里设下了一个陷阱,作者当时估计没测试到就是!
如果你使用这段代码,在有些手机上是可以正常播放视频的,而有些手机就是不行(你只能听见声音、看不到画面),系统没给任何提示,只有2个警告信息,如下图:
于是百度“mediaPlayer错误信息”得知 35 在 native 层是这样定义的:const PVMFStatus PVMFInfoTrackDisable = 35;
于是 Google “PVMFInfoTrackDisable ” 果然有人跟我遇到同样的问题,在 stackoverflow 论坛有一篇这样的帖子:
http://stackoverflow.com/questions/7509818/android-mediaplayer-sometimes-no-video-is-played-even-though-audio-plays
这里不得不说下,stackoverflow 论坛能够找到你遇到的各种疑难杂症,嘿嘿!
这里面说法很多,但没找到根本原因,倒是在另外一篇帖子找到了答案:
这哥们才发现了问题的根本,大概意思就是:在 surfaceCreated 没被系统调用之前,SurfaceView 的 SurfaceHolder 是无效的,而我们一般习惯在 MediaPlayer 构造完后就给他设置数据,而我在 surfaceCreated 才调用了 mPlayer.setDisplay(holder); 这样 MediaPlayer 就没有设置显示器就开始播放了,这样自然看不到画面,而后来系统调用 surfaceCreated 的时候是于事无补的!
这也难怪看到有些人回复说第二次在播放视频的时候就可以,因为前面第一次设置了 holder 嘛!
知道了问题的根本就好办了, 在 surfaceCreated 里设置 holder,然后设置视频数据,然后调用 prepare,这样总是没问题了吧!
下面贴上我封装的一个 VideoPlayer :
[code] public class VideoPlayer implements
MediaPlayer.OnCompletionListener,
SurfaceHolder.Callback,
OnClickListener,
OnErrorListener,
OnInfoListener,
OnTouchListener,
OnKeyListener,
MediaPlayer.OnPreparedListener {
private SurfaceView surfaceView;
private MediaPlayer mPlayer; // MediaPlayer对象
private SurfaceHolder mSurfaceHolder; // SurfaceHolder对象
private ViewGroup viewGroup;
private GameActivity gameActivity;
private ImageButton button;
private boolean surfaceCreated = false;
public VideoPlayer(GameActivity gameActivity) {
this.gameActivity = gameActivity;
LayoutInflater inflater = (LayoutInflater) gameActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//LayoutInflater inflater = context.getLayoutInflater();
viewGroup =(ViewGroup) inflater.inflate(R.layout.video_player, null);
button = (ImageButton) viewGroup.findViewById(R.id.button1);
button.setOnClickListener(this);
button.setVisibility(View.INVISIBLE);
surfaceView = (SurfaceView) viewGroup.findViewById(R.id.surfaceView);
surfaceView.setOnTouchListener(this);
surfaceView.setOnKeyListener(this);
surfaceView.setFocusableInTouchMode(true);
surfaceView.requestFocus();
mSurfaceHolder = surfaceView.getHolder();
mSurfaceHolder.addCallback(this); // 设置回调接口
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); // 设置为Buffer类型(播放视频&Camera预览)
mPlayer = new MediaPlayer();
mPlayer.setScreenOnWhilePlaying(true);
mPlayer.setOnPreparedListener(this);
mPlayer.setOnCompletionListener(this);
mPlayer.setOnErrorListener(this);
mPlayer.setOnInfoListener(this);
}
public void pause() {
mPlayer.pause();
}
public void resume() {
mPlayer.start();
}
private int resId;
public void setVideo(int resId) {
Log.i(PobabyGame.TAG, "== setVideo ! == ");
this.resId = resId;
Uri uri = Uri.parse("android.resource://"
+ gameActivity.getPackageName()
+ "/" + resId);
try {
mPlayer.setDataSource(gameActivity, uri);
//mPlayer.prepare();
} catch (IllegalArgumentException e) {
} catch (SecurityException e) {
} catch (IllegalStateException e) {
} catch (IOException e) {
}
}
public SurfaceView getSurfaceView() {
return surfaceView;
}
public ViewGroup getViewGroup() {
return viewGroup;
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceCreated(final SurfaceHolder holder) {
Log.i(PobabyGame.TAG, "== surfaceCreated ! == " + "holder" + holder.toString() + ", h2" + mSurfaceHolder);
gameActivity.handler.post(new Runnable() {
@Override
public void run() {
mPlayer.setDisplay(holder); // 指定SurfaceHolder
surfaceCreated = true;
//Uri uri = Uri.parse("android.resource://"
//+ gameActivity.getPackageName()
//+ "/" + resId);
try {
//mPlayer.setDataSource(gameActivity, uri);
mPlayer.prepare();
} catch (IllegalArgumentException e) {
} catch (SecurityException e) {
} catch (IllegalStateException e) {
} catch (IOException e) {
}
}
});
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
surfaceCreated = false;
}
@Override
public void onPrepared(MediaPlayer player) {
int wWidth = Gdx.graphics.getWidth();
int wHeight = Gdx.graphics.getHeight();
/* 获得视频宽长 */
int vWidth = mPlayer.getVideoWidth();
int vHeight = mPlayer.getVideoHeight();
/* 最适屏幕 */
float wRatio = (float) vWidth / (float) wWidth; // 宽度比
float hRatio = (float) vHeight / (float) wHeight; // 高度比
float ratio = Math.max(wRatio, hRatio); // 较大的比
vWidth = (int) Math.ceil((float) vWidth / ratio); // 新视频宽度
vHeight = (int) Math.ceil((float) vHeight / ratio); // 新视频高度
// 改变SurfaceHolder大小
mSurfaceHolder.setFixedSize(vWidth, vHeight);
mPlayer.start();
gameActivity.gameView.setVisibility(View.INVISIBLE);
}
@Override
public void onCompletion(MediaPlayer mp) {
gameActivity.videoFinish(resId);
}
@Override
public void onClick(View v) {
gameActivity.videoFinish(resId);
mPlayer.release();
}
@Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
Log.i(PobabyGame.TAG, String.format("onInfo(%d, %d)", what, extra));
return true;
}
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Log.e(PobabyGame.TAG, String.format("onError(%d, %d)", what, extra));
return true;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN){
button.setVisibility(View.VISIBLE);
return true;
}
return false;
}
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if(event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK){
gameActivity.videoFinish(resId);
mPlayer.release();
}
return true;
}
}
[/code]
相关文章推荐
- 【Libgdx 原创】在 Libgdx 中播放视频实例
- 【Libgdx原创】在Libgdx中播放视频2
- 【Libgdx原创】在Libgdx中播放视频2
- 视频播放程序实例
- 【技术原创】如何在Winform程序中播放视频及实现播放列表
- Android-视频播放实例之手势控制音乐、亮度
- nginx+tomcat+二级域名静态文件分离支持mp4视频播放配置实例
- 在 Libgdx 中播放视频(一)
- (原创)IOS播放视频
- opencv实例三:播放AVI格式视频
- [原创]视频播放控件!
- [音视频播放] 一个用SDL来播放视频的实例代码
- [原创]暴风影音播放视频没有声音的解决方法
- 音狐990 (YH990) 视频mp3中播放视频的解决方案(原创 by afxid)
- [Android实例] 视频播放三种设置全屏适应不同分辨率显示器
- IOS 视频播放实例
- 【OpenCV学习笔记】九、实例应用(二)鼠标截图程序及滑动条视频播放程序
- swift4.0实现视频播放、屏幕旋转、倍速播放、手势调节及锁屏面板等功能实例
- 【PythonDjango后台实例 第七章】Django使用Video.js视频播放插件
- IOS视频循环播放实例