cocos2d-x3.0 android播放视频
2014-07-11 19:27
495 查看
手游项目需要播放视频,首先需要在android下播放。
以下记录遇到的坑。
第一:在项目中需要调用java代码
#include "platform/android/jni/JniHelper.h"后报错,发现JniHelper里有一句
#include "Jni.h"而项目中找不到。
解决办法:找到jdk目录下的include,复制jni.h到VC目录下的include
复制jdk/include/win32下的jni_md.h到目录下的include
问题解决
第二个坑:System.Loadbiray传入什么参数?
static
{
System.loadLibrary("cocos2dcpp");
}
这里的cocos2dcpp是在cocos2d-x工程里proj.android/jni/Android.mk里LOCAL_MODULE_FILENAME := libcocos2dcpp指定的名字,而且不能要前面的lib
接下来说说具体实现
首先在proj.android\src\org\cocos2dx\cpp 目录下创建文件VideoView.java,代码如下
然后修改Cocos2dxActivity.java
Java的代码就是这些了。接下来是C++层
在需要播放视频的地方加入:
文件名随意,必须放到Resource目录,当然可以放到子文件夹下,那么文件名就改成
目录/文件名.后缀名
getStaticMethodInfo的参数:
第一个是JniMehodInfo类型,就是上面创建的
第二个是你要调用的Java文件类
第三个是要调用的静态函数名称
第四个是返回值和参数说明,这里的意思是返回值为void,参数有一个string
具体的可以百度搜索Jni和JniHelper
到这里,视频应该可以正常播放了,但还没研究如何控制视频的播放,不过对于项目来说够了。
以下记录遇到的坑。
第一:在项目中需要调用java代码
#include "platform/android/jni/JniHelper.h"后报错,发现JniHelper里有一句
#include "Jni.h"而项目中找不到。
解决办法:找到jdk目录下的include,复制jni.h到VC目录下的include
复制jdk/include/win32下的jni_md.h到目录下的include
问题解决
第二个坑:System.Loadbiray传入什么参数?
static
{
System.loadLibrary("cocos2dcpp");
}
这里的cocos2dcpp是在cocos2d-x工程里proj.android/jni/Android.mk里LOCAL_MODULE_FILENAME := libcocos2dcpp指定的名字,而且不能要前面的lib
接下来说说具体实现
首先在proj.android\src\org\cocos2dx\cpp 目录下创建文件VideoView.java,代码如下
package org.cocos2dx.cpp; import java.io.FileDescriptor; import java.io.IOException; import android.app.Activity; import android.content.res.AssetFileDescriptor; import android.media.MediaPlayer; import android.net.Uri; import android.util.Log; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; public class VideoView extends SurfaceView implements SurfaceHolder.Callback, View.OnTouchListener, MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener, MediaPlayer.OnInfoListener, MediaPlayer.OnCompletionListener { private static final String TAG = "VideoView"; private MediaPlayer mPlayer; // MediaPlayer对象 private Activity gameActivity; private Uri resUri; private AssetFileDescriptor fd; private boolean surfaceCreated; private OnFinishListener onFinishListener; public VideoView(Activity context) { super(context); this.gameActivity = context; final SurfaceHolder holder = getHolder(); holder.addCallback(this); // 设置回调接口 holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); // 设置为Buffer类型(播放视频&Camera预览) setOnTouchListener(this); mPlayer = new MediaPlayer(); // mPlayer.setDisplay(getHolder()); //此时holder并未创建,不能在此处设置 mPlayer.setScreenOnWhilePlaying(true); mPlayer.setOnPreparedListener(this); mPlayer.setOnCompletionListener(this); mPlayer.setOnErrorListener(this); mPlayer.setOnInfoListener(this); } public VideoView setOnFinishListener(OnFinishListener onFinishListener) { this.onFinishListener = onFinishListener; return this; } public void setVideo(Uri resUri) { this.resUri = resUri; try { mPlayer.setDataSource(gameActivity, resUri); } catch (Exception e) { } } public void setVideo(AssetFileDescriptor fd) { this.fd = fd; try { //直接调用 fd.getFileDescriptor() 是不行的 mPlayer.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength()); } catch (IOException e) { e.printStackTrace(); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceCreated(final SurfaceHolder holder) { Log.i(TAG, "surfaceCreated"); surfaceCreated = true; mPlayer.setDisplay(holder); // 指定SurfaceHolder try { mPlayer.prepare(); } catch (Exception e1) { } } @Override public void surfaceDestroyed(SurfaceHolder holder) { Log.i(TAG, "surfaceDestroyed"); surfaceCreated = false; if(mPlayer != null){ mPlayer.stop(); mPlayer.reset(); } } @Override public void onPrepared(MediaPlayer player) { Log.i(TAG, "onPrepared"); int wWidth = getWidth(); int wHeight = 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大小 getHolder().setFixedSize(vWidth, vHeight); mPlayer.seekTo(posttion); mPlayer.start(); } private void dispose() { mPlayer.release(); mPlayer = null; resUri = null; if (fd != null) { try { fd.close(); } catch (IOException e) { e.printStackTrace(); } fd = null; } } @Override public void onCompletion(MediaPlayer mp) { Log.i(TAG, "onCompletion"); dispose(); if(onFinishListener != null) onFinishListener.onVideoFinish(); } @Override public boolean onInfo(MediaPlayer mp, int what, int extra) { return true; } @Override public boolean onError(MediaPlayer mp, int what, int extra) { return true; } @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { stop(); } return true; } public void stop() { mPlayer.stop(); // 大概不会调用 MediaPlayer.onCompletion dispose(); if(onFinishListener != null) onFinishListener.onVideoFinish(); } int posttion; public void pause() { posttion = mPlayer.getCurrentPosition(); mPlayer.pause(); } /** * 暂停的时候,系统会销毁 SurfaceView ,所以在resume的时候相对于重新设置MediaPlayer */ public void resume() { if(surfaceCreated){ mPlayer.start(); }else { try { if(resUri != null) mPlayer.setDataSource(gameActivity, resUri); else if (fd != null) { mPlayer.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength()); } } catch (Exception e) { } } } public interface OnFinishListener { public void onVideoFinish(); } }
然后修改Cocos2dxActivity.java
package org.cocos2dx.cpp; import android.app.NativeActivity; import android.os.Bundle; import android.view.WindowManager; import java.io.FileDescriptor; import java.io.IOException; import android.content.res.AssetFileDescriptor; import android.net.Uri; import android.os.Bundle; import android.util.Log; import android.view.ViewGroup; import org.cocos2dx.cpp.VideoView.OnFinishListener; public class Cocos2dxActivity extends NativeActivity implements OnFinishListener { static Cocos2dxActivity instance; VideoView videoView; ViewGroup group; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); // 这一句是屏幕常亮 //For supports translucency //1.change "attribs" in cocos\2d\platform\android\nativeactivity.cpp /*const EGLint attribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, //EGL_BLUE_SIZE, 5, -->delete //EGL_GREEN_SIZE, 6, -->delete //EGL_RED_SIZE, 5, -->delete EGL_BUFFER_SIZE, 32, //-->new field EGL_DEPTH_SIZE, 16, EGL_STENCIL_SIZE, 8, EGL_NONE };*/ //2.Set the format of window // getWindow().setFormat(PixelFormat.TRANSLUCENT); instance = this; group = (ViewGroup)getWindow().getDecorView(); } static { System.loadLibrary("cocos2dcpp"); } private void play(String name) { Log.i("", "----- name=" + name); videoView = new VideoView(this); videoView.setOnFinishListener(this); // videoView.setVideo(uri); try { AssetFileDescriptor afd = getAssets().openFd(name); videoView.setVideo(afd); } catch (IOException e) { e.printStackTrace(); } group.addView(videoView); videoView.setZOrderMediaOverlay(true); } public static void playVideo(final String name) { if (instance != null) { instance.runOnUiThread(new Runnable() { @Override public void run() { instance.play(name); } }); } } @Override public void onVideoFinish() { group.removeView(videoView); videoView = null; } }
Java的代码就是这些了。接下来是C++层
在需要播放视频的地方加入:
#include "platform/android/jni/JniHelper.h" JniMethodInfo t; if (JniHelper::getStaticMethodInfo(t, "org/cocos2dx/cpp/Cocos2dxActivity", "playVideo", "(Ljava/lang/String;)V")) { t.env->CallStaticVoidMethod(t.classID, t.methodID, t.env->NewStringUTF("a.mp4")); }
文件名随意,必须放到Resource目录,当然可以放到子文件夹下,那么文件名就改成
目录/文件名.后缀名
getStaticMethodInfo的参数:
第一个是JniMehodInfo类型,就是上面创建的
第二个是你要调用的Java文件类
第三个是要调用的静态函数名称
第四个是返回值和参数说明,这里的意思是返回值为void,参数有一个string
具体的可以百度搜索Jni和JniHelper
到这里,视频应该可以正常播放了,但还没研究如何控制视频的播放,不过对于项目来说够了。
相关文章推荐
- cocos2d-x IOS 和Android播放视频(包括网络视频)
- cocos2d-x 播放视频 on Android
- cocos2d-x IOS 和Android播放视频(包括网络视频)
- cocos2d-x IOS 和Android播放视频(包括网络视频)
- cocos2d-x之Android播放视频c++代码
- cocos2d-x IOS,Android “一键式”播放视频
- cocos2d-x IOS 和Android播放视频(包括网络视频)
- Cocos2d-x v2.2.3 IOS,Android “一键式”播放视频
- cocos2d-x lua 播放视频,VideoPlayer在Android和IOS下的坑,
- cocos2d-x 播放视频(mp4)后 android手机音量按钮失效
- Cocos2d-3.x_视频播放(Android和iOS平台)
- cocos2d-x IOS 和Android播放视频(包括网络视频)
- cocos2d-x 在android下得视频播放
- cocos2d-x 播放视频 on Android
- android VideoView播放视频,MediaRecorder 录音
- Android提高第二十一篇之MediaPlayer播放网络视频
- 解决vlc-android播放http视频退出问题
- android 之MediaPlayer MP3播放,VideoView 视频播放,MediaRecorder 录音
- Android-WebKit视频播放原理之一 —— 界面呈现部分
- Android多媒体学习十四:播放网络上的视频