您的位置:首页 > 移动开发 > Cocos引擎

cocos2d-x 在android下得视频播放

2013-05-22 12:08 337 查看
最近项目有需要在cocos2d-x android中播放一下视频,网上找了点资料最终成功播放。

在这里我也做下总结,方便以后查阅,留下学习的足迹,同时与大家共享。

下面是相关文章的内容:

我们来用强大的 SurfaceView 和 MediaPlayer 来组装一下

其原理就是:

MediaPlayer.setDisplay (SurfaceHolder sh)

sh 来自于SurfaceView,这样MediaPlayer就可以看到画面了。

不过这里面有几个细节需要注意:

1.何时调用 setDisplay :

  一般可能会在构造函数里面就调用,这样系统会报错即使没报错也可能会出现 闻其声而不见其画面 的现象(大多数人遇到过),告诉你 Holder 无效,SurfaceHolder 是有一组回调接口的,通过

  addCallback(SurfaceHolder.Callback callback)

设置,Callback 里面有个函数:

  surfaceCreated(final SurfaceHolder holder)

其参数是 SurfaceHolder 所以我们可以猜到这个接口用来告诉我们 SurfaceHolder 创建好啦,所以我们在这个回调里面调用 MediaPlayer.setDisplay 就没问题啦!

2.如何播放视频文件:

在 coco2d-x 中,资源文件肯定都在 assets 目录下,所以我们首先想到通过 URI 引用 assets 下文件,Like:

Uri uri = Uri.parse("file:///android_asset/" + name); //不可取

但是这样是不行的,播放不出来,于是我就上 StackOverFlow 上搜搜,还是有前辈解决了,所以我要说一句:StackOverFlow 是一个神奇的网站。

正确的做法是调用这个接口:

setDataSource (FileDescriptor fd, long offset, long length)

assets 下可以通过:AssetFileDescriptor afd = getAssets().openFd(name); 方法得到 AssetFileDescriptor 对象,然后这样调用就OK:

mPlayer.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());

你可能会想到:

//直接调用 fd.getFileDescriptor() 是不行的mPlayer.setDataSource(fd.getFileDescriptor());

这样也是不行的,具体原因没深入研究,此外再介绍用 res/raw 下资源的方法:

Uri uri = Uri.parse("android.resource://" + this.getPackageName() + "/" + R.raw.video2); //可取

这样一个 android 层视频播放器就封装好了,实现细节可以看源代码:




View
Code

下面介绍如何调用这个播放器:

1.native 层:native 调 java 我们肯定要用到 jni 技术,cocos2d-x 封装了一个 jni 帮助类在:cocos2dx/platform/android/jni/JniHelper.h ,我们需要在 Java 层定义一个静态方法,然后通过 jni->CallStaticVoidMethod 调用:




View
Code

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)        JniMethodInfo t;        if (JniHelper::getStaticMethodInfo(t,             "com/yichou/demo/video/VideoDemo",             "playVideo",             "(Ljava/lang/String;)V"))        {            t.env->CallStaticVoidMethod(t.classID, t.methodID,                 t.env->NewStringUTF("video2.mp4"));        }#endif


2.这样重点还是来到 Java 层:




View
Code

VideoView videoView;        private void a(String name) {        Log.i("", "name=" + name);        //        Uri uri = Uri.parse("file:///android_asset/" + name); //不可取//        Uri uri = Uri.parse("android.resource://" + this.getPackageName() + "/" + R.raw.video2); //可取        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.a(name);                 }            });        }    }

为了方便起见,我们把方法定义为 static 这样我们就需要一个当前 activity 的实例,这里用了一个 instance 静态全局变量,类似于单例设计模式。

完整代码:




View
Code

1 public class VideoDemo extends Cocos2dxActivity implements OnFinishListener { 2     ViewGroup group; 3     static VideoDemo instance; 4      5  6     protected void onCreate(Bundle savedInstanceState){ 7         super.onCreate(savedInstanceState); 8         instance = this; 9         10         group = (ViewGroup)getWindow().getDecorView();11     }12     13     14     VideoView videoView;15     16     private void a(String name) {17         Log.i("", "name=" + name);18         19 //        Uri uri = Uri.parse("file:///android_asset/" + name); //不可取20 //        Uri uri = Uri.parse("android.resource://" + this.getPackageName() + "/" + R.raw.video2); //可取21         videoView = new VideoView(this);22         videoView.setOnFinishListener(this);23 //        videoView.setVideo(uri);24         try {25             AssetFileDescriptor afd = getAssets().openFd(name);26             videoView.setVideo(afd);27         } catch (IOException e) {28             e.printStackTrace();29         }30         group.addView(videoView);31         videoView.setZOrderMediaOverlay(true);32     }33     34     public static void playVideo(final String name) {35         if (instance != null) {36             instance.runOnUiThread(new Runnable() {37                 @Override38                 public void run() {39                     instance.a(name); 40                 }41             });42         }43     }44     45     static {46          System.loadLibrary("game");47     }48 49     @Override50     public void onVideoFinish() {51         group.removeView(videoView);52         videoView = null;53     }54 }

OK,核心方法介绍完毕,具体实现细节可以看我提供的 Demo 源码

demo下载地址

http://pan.baidu.com/share/link?shareid=474938&uk=1543627784
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: