cocos2d-x3.0 android播放视频

来源:互联网 发布:science域名 编辑:程序博客网 时间:2024/05/16 15:00

手游项目需要播放视频,首先需要在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,代码如下

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();}}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}@Overridepublic void surfaceCreated(final SurfaceHolder holder) {Log.i(TAG, "surfaceCreated");surfaceCreated = true;mPlayer.setDisplay(holder); // 指定SurfaceHoldertry {mPlayer.prepare();} catch (Exception e1) {}}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {Log.i(TAG, "surfaceDestroyed");surfaceCreated = false;if(mPlayer != null){mPlayer.stop();mPlayer.reset();}}@Overridepublic 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;}}@Overridepublic void onCompletion(MediaPlayer mp) {Log.i(TAG, "onCompletion");dispose();if(onFinishListener != null)onFinishListener.onVideoFinish();}@Overridepublic boolean onInfo(MediaPlayer mp, int what, int extra) {return true;}@Overridepublic boolean onError(MediaPlayer mp, int what, int extra) {return true;}@Overridepublic boolean onTouch(View v, MotionEvent event) {if (event.getAction() == MotionEvent.ACTION_DOWN) {stop();}return true;}public void stop() {mPlayer.stop(); // 大概不会调用 MediaPlayer.onCompletiondispose();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;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.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() {@Overridepublic void run() {instance.play(name); }});}}@Overridepublic 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


到这里,视频应该可以正常播放了,但还没研究如何控制视频的播放,不过对于项目来说够了。

0 0
原创粉丝点击