(头注:Cocos2d-x3.2引擎已经集成了MP4播放功能了,本篇文章写于2.x版本)

游戏需要播放mp4文件展示游戏背景,在网上搜了好久,IOS平台比较容易实现,Android就不敢恭维了;

播放mp4需要分平台实现,悲催的是IOS和Android的原生开发都没有做过,所以只能从网上找资料;

目前实现的功能播放,跳过和播放完成之后回到游戏,IOS和Android一样都已经实现;

1、IOS实现:

首先,参考文章:点击打开链接,我是完全按照这篇文章的介绍做的,里面有源代码地址,相信各位了看了之后就回明白,至少也有方向了;

类说明:
LHVideoPlayerImplCpp.h/mm // cocos2dx中使用的播放MP4接口
LHVideoPlayerImpl.h/m // videoPlayer的oc接口
LHVideoPlayer.h/m // videoPlayer的实现,调用MPMoviePlayerController播放MP4
LHVideoOverlayView.h/m // videoPlayer的上层操作层,有跳过影片按钮。

我就功能点而言,介绍其中的两个类。
第一个是LHVideoPlayerImplCpp.h/mm文件,这个是负责给2dx调用的。该类有两个静态方法:

class LHVideoPlayerImplCpp {
public:/*** 开始播放MP4视频* name 视频名称,不要带后缀".mp4"。(比如文件是test.mp4, 那么name就传"test")* frameRect 视频显示的区域。全屏(Rect(0, 0, visibleSize.width, visibleSize.height))*/static void playMP4WithName(const char* name, cocos2d::Rect frameRect);/*** 设置跳过影片按钮title,默认无跳过影片功能*/static void setSkipTitle(const char* title);
};

第二个是LHVideoPlayer.h/m,这个是负责播放MP4。
a、这个方法是播放MP4。注释很清楚。

- (void)playMP4WithName: (NSString *)name VideoFrame:(CGRect)rect
{UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];// 获取视频文件的名称NSString *url = [[NSBundle mainBundle]pathForResource:name ofType:@"mp4"];// 初始化player_player = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL fileURLWithPath:url]];[keyWindow.rootViewController.view addSubview: [_player view]];// 设置player样式[_player setControlStyle: MPMovieControlStyleNone];[[_player view] setFrame: rect];// 当MP4完成播放的回调[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(movieFinishedCallback:)name:MPMoviePlayerPlaybackDidFinishNotification object:_player];// 开始播放影片[_player play];// 上层操作层_videoOverlayView = [ [LHVideoOverlayView alloc] initWithFrame: rect];[keyWindow.rootViewController.view addSubview: _videoOverlayView];
}

b、这个方法是播放结束之后,移除播放view。

- (void)removePlayer:(MPMoviePlayerController*)player
{[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:player];[player.view removeFromSuperview];[_player release];_player = nil;[_videoOverlayView removeFromSuperview];[_videoOverlayView release];_videoOverlayView = nil;
}

3、播放完成,通知外界。playerPlayFinished 这个方法是空的,没有通知外界。我看了下,感觉没什么需要,所以没加。(原作者没加,不过考虑到我播放的mp4是挂在一个layer里面实现的,所以还是希望在播放结束的时候该layer能知道;所以,我另外添加了一个函数):

bool LHVideoPlayerImplCpp::getFinshState() {return [LHVideoPlayerImpl getFinshState];
}

至于里面调用的函数就不写了,用于获取视频已经播放结束,然后在layer的visit里面处理:

void ShowMovieStart::visit() {GUILayer::visit();bool isfinish = false;
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)//
#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)isfinish = LHVideoPlayerImplCpp::getFinshState();
#endifif (isfinish) {CCLog("视频播放结束了");//做相关处理}
}

注意看ios实现的部分,当视频结束时,做相关处理;

使用方法:
a、导入头文件

#include “LHVideoPlayerImplCpp.h”

b、开始调用接口,假设你要播放的是“loading.mp4”

Size visibleSize = Director::getInstance()->getVisibleSize();
LHVideoPlayerImplCpp::playMP4WithName(“loading”, Rect(0, 0, visibleSize.width, visibleSize.height));
LHVideoPlayerImplCpp::setSkipTitle(“Skip”);

c、影片结束之后,会自动移除视图;
git地址: 点击打开链接

IOS实现相对于Android来说比较容易,而且上诉源代码还提供了跳过功能,非常不错;

2、Android部分,这个比较复杂,一开始我根本不知道从何下手,只能从网上找,但是相关资料也不是很多,而且大多数不容易解决问题,有些可能是写给Android老手看的,像我Android开发只见皮毛者完全云里雾里,不过,看得资料多了,代码还是可以理解的,虽然有时候一知半解,但还是一步步实现了;之前只用过C++和脚本,lua Js什么的,java代码也没写过,不过语言从来不是问题,主要的是原理。

a、首先,如何把mp4播放出来;

视频播放Veiw实现VideoView.java文件:

package org.cocos2dx.common;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 = null;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);setOnTouchListener(this);if (mPlayer != null) {  mPlayer.reset();  mPlayer.release();  mPlayer = null;  } mPlayer = new MediaPlayer();mPlayer = new MediaPlayer();mPlayer.setScreenOnWhilePlaying(true);mPlayer.setOnPreparedListener(this);mPlayer.setOnCompletionListener(this);mPlayer.setOnErrorListener(this);mPlayer.setOnInfoListener(this);//不应该在这里设置holder//mPlayer.setDisplay(holder);//mPlayer.prepareAsync();}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 {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);try {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); ////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(); //dispose();if(onFinishListener != null) {onFinishListener.onVideoFinish();}}int posttion;public void pause() {posttion = mPlayer.getCurrentPosition();mPlayer.pause();}/*** */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();}
}

主要用到MediaPlayer来实现,至于MediaPlayer怎么用,我刚开始也不大懂,从网上找资料,很多,有兴趣google之,这里实现了一个视频播放的主要功能,另外有停止(跳过)的功能;

下面是PlayeVideo文件:

package org.cocos2dx.common;import java.io.*;import org.cocos2dx.lib.Cocos2dxActivity;import org.cocos2dx.common.VideoView.OnFinishListener;import android.content.res.AssetFileDescriptor;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Toast;
import android.content.Context;
import android.view.LayoutInflater;public class playvideo implements OnFinishListener {ViewGroup viewgroup = null;private static playvideo pv = null;private static XXXX instance = null;VideoView videoView;boolean isvideofinished = false;//跳过按钮的viewprivate View layout = null;//跳过按钮private Button skipbtn = null;public static playvideo shareInstance() {if(null == pv) {pv = new playvideo();}return pv;}public void ShowVideo(String name) {System.out.println("Android ShowVideo 111111");if (null == instance) {return;}Log.i("", "name=" + name);videoView = new VideoView(instance);videoView.setOnFinishListener(this);viewgroup = (ViewGroup)instance.getWindow().getDecorView();try {AssetFileDescriptor afd = instance.getAssets().openFd(name);videoView.setVideo(afd);} catch (IOException e) {e.printStackTrace();}viewgroup.addView(videoView);videoView.setZOrderMediaOverlay(true);//加一个新的界面Context mContext = ShenMoJie.getContext();//LAYOUT_INFLATER_SERVICE表示从xml文件中加载布局LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);layout = inflater.inflate(R.layout.video, null);//添加一层viewgroup.addView(layout);//找到对应的按钮skipbtn = (Button)layout.findViewById(R.id.skipbutton);skipbtn.setOnClickListener(listener);//用相对布局定义控件的位置int width = instance.getWindowManager().getDefaultDisplay().getWidth(); int height = instance.getWindowManager().getDefaultDisplay().getHeight();System.out.println("width: "+width+"height: "+height);LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)skipbtn.getLayoutParams();//left, top, right, bottomparams.setMargins(width*5/6, 10, 0, 0);// 通过自定义坐标来放置你的控件skipbtn.setLayoutParams(params);}private OnClickListener listener = new OnClickListener() {@Overridepublic void onClick(View v) {Button btn=(Button)v;System.out.println("Android listener");switch (btn.getId()) {case R.id.skipbutton:System.out.println("Android listener->skipbutton");skipVideo();break;default:break;}}};public static void playVideo(final String name) {System.out.println("Android playVideo 111111");if (instance != null ) {System.out.println("Android playVideo 22222");instance.runOnUiThread(new Runnable() {@Overridepublic void run() {System.out.println("Android playVideo 333333");playvideo.shareInstance().ShowVideo(name);}});}}public static boolean isVideoFinished() {//System.out.println("Android isVideoFinished");return playvideo.shareInstance().isvideofinished;}public static void skipVideo() {playvideo.shareInstance().videoView.stop();}@Overridepublic void onVideoFinish() {viewgroup.removeView(videoView);viewgroup.removeView(layout);videoView = null;layout = null;isvideofinished = true;System.out.println("Android onVideoFinish");}public static void SetActivity(XXXX ptActivity) {instance = ptActivity;}
}

其中XXXX是继承之Cocos2dxActivity的实例,用SetActivity方法,将之传进来,播放PlayVideo,传一个视频文件名,这里需要用到JNI,C++调用java函数,网上也是一大堆的资料,知之为知之,不知百度之,再不知谷歌之,然后就可以实现实现游戏的播放了,注意在VideoView中实现了,播放完成之后会将试图从viewgourp中移除;

到这一步还比较简单,由于之前没有做过Android原生开发,所以连怎么添加一个button都不知道(跳过按钮),不过了解了一下之后,还是实现了,虽然代码不知道写得合不合理;

//加一个新的界面Context mContext = ShenMoJie.getContext();//LAYOUT_INFLATER_SERVICE表示从xml文件中加载布局LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);layout = inflater.inflate(R.layout.video, null);//添加一层viewgroup.addView(layout);//找到对应的按钮skipbtn = (Button)layout.findViewById(R.id.skipbutton);skipbtn.setOnClickListener(listener);//用相对布局定义控件的位置int width = instance.getWindowManager().getDefaultDisplay().getWidth(); int height = instance.getWindowManager().getDefaultDisplay().getHeight();System.out.println("width: "+width+"height: "+height);LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)skipbtn.getLayoutParams();//left, top, right, bottomparams.setMargins(width*5/6, 10, 0, 0);// 通过自定义坐标来放置你的控件skipbtn.setLayoutParams(params);

详情请看PlayVideo文件,下面是vidio.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent"><Button android:text="@string/video_skip" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/skipbutton" />
</LinearLayout>

就这样,Android版也实现了播放跳过功能;

Cocos2dx播放mp4文件(IOS和Android)相关推荐

  1. view_video.php,android,_Android开发,使用ViewVideo无法播放mp4文件?,android - phpStudy

    Android开发,使用ViewVideo无法播放mp4文件? 新手学习Android开发,参考书为<第一行代码>,关于视频播放那一段一直调试不过去.播放视频一直有个错误,在google里 ...

  2. jw player解决网页播放mp4文件的问题

    工作需要,在网页上播放.mp4文件.节约时间可之间看 「成功」部分. 失败1. 最先想到的是使用<embed>标签(在其他网站上看到过嵌入代码),网上搜索后找到如下代码: <embe ...

  3. 解决Ubuntu 18.04中无法播放MP4文件的问题

    遇到的问题 在Ubuntu 18.04中无法播放MP4文件,提示播放该文件需要H.264(主配置文件)解码器. 测试机型:联想邵阳E42 测试时间:2020年9月5日 测试系统:18.04 解决方法 ...

  4. android.process.media已停止 三星,android – 在三星设备上播放mp4文件时出现...

    我正在使用经典的VideoView实现在Android上播放视频. 相同的mp4文件网址在HTC Desire上运行正常.但它不适用于三星设备. 三星Galaxy S1和三星Galaxy Tab说:& ...

  5. Android 用MediaCodec ,MediaExtractor解码播放MP4文件

    上一篇讲了如何采集摄像头画面并且进行编码,再进行封装成MP4格式文件,如需了解可以看 安卓采集摄像头画面生成MP4文件 本篇博客,主要讲解如何对MP4文件进行解封装,再进行解H264码流,进行画面显示 ...

  6. Android拷贝U盘中的文件到指定目录,拷贝完成后自动播放MP4文件

    先要监听到U盘插入的广播并获取U盘的文件路径,一般使用动态注册. UsbStateReceiver receiver = new UsbStateReceiver(); //new一个广播接收器Int ...

  7. android html5播放器,用 HTML5 播放器在 iOS 或 Android 等移动设备上播放视频

    如果你想把自己网站上的视频弄得能在 iOS 或者 Android 设备上播放,你需要想两个事儿,一个是你网站上的视频播放器要支持 HTML5,还有你的视频得支持在这些设备上看. 网站的视频播放器我们可 ...

  8. 服务器设置播放mp4文件,服务器设置播放mp4视频

    服务器设置播放mp4视频 内容精选 换一换 华为云面向企业市场推出音视频转码解决方案,可以根据用户业务需要,提供云端音视频转码服务,以满足用户业务在OTT.PC以及移动终端上播放的诉求 来自:解决方案 ...

  9. 浏览器没办法播放html文件,ie浏览器使用video标签无法播放mp4文件

    ie11浏览器,使用bottle.py提供文件浏览服务,html5浏览mp4视频,测试ie浏览器上无法播放,显示无效的视频源. 从网上下载了一个好的mp4文件,可以在ie浏览器上播放,问题应该在2个地 ...

最新文章

  1. 当前linux环境做出镜像,把当前ubuntu系统做成镜像
  2. 亿级流量系统架构之如何设计承载百亿流量的高性能架构【石杉的架构笔记】...
  3. php 报错乱码,thinkphp3 phpexcel 导出报错乱码清除ob
  4. Java 技术篇 - 连接oracle数据库执行sql使用close()关闭createStatement()无效无法清除游标缓存问题解决,报“ORA-01000: 超出打开游标的最大数“错误解决方法
  5. CSS属性选择器温故-4
  6. python写一段脚本代码自动完成输入(目录下的所有)文件的数据替换(修改数据和替换数据都是输入的)【转】...
  7. -bash:fork:Resource temporarily unavailable
  8. mysql简单的命令centos版
  9. 启动go服务_go微服务框架go-micro深度学习 rpc方法调用过程详解
  10. Linkedin Camus,从Kafka到HDFS的数据传输管道
  11. 《Android游戏编程入门经典》——14.4节问与答
  12. html字体版权,字体在网站中的版权问题
  13. 有手就行:零基础渗透网站步骤
  14. 7-3 学生成绩录入及查询 (20分)__C++
  15. 28388-连接管理器 (CM)
  16. java excel生成_java操作excel表,包括创建、读取、以及修改【via 度娘】
  17. 【Matlab】自定义函数的几种方法
  18. 修复This is probably not a problem with npm. There is likely additional logging output above.依赖问题
  19. 计算机Excel怎么弄迷你图,【迷你图excel在哪里】Excel如何绘制迷你图
  20. Revi开发 - 构件过滤(FilteredElementCollector)

热门文章

  1. python爬取流浪地球_Scrapy爬取猫眼流浪地球影评2----- 获取数据
  2. 【Linux】设备树详解dts
  3. Golang搭建并行版爬虫信息采集框架
  4. Satwe楼板能用弹性模计算吗_密肋楼盖在PKPM计算中如何实现
  5. TSlint注释忽略错误和RESTful理解
  6. mysql视图中可以删除数据吗_sql問題 删除视图中的数据,表中的数据会删除吗?
  7. 2021年度训练联盟热身训练赛第二场
  8. BMVC 2022 (东京大学)仅需90K参数!实时完成低光增强, 曝光矫正的超轻量级Transformer网络IAT,已开源...
  9. vscode代码格式排列_Visual Studio code 代码格式化整理
  10. W10系统JDK8环境变量好简单