软件世界网 购物 网址 三丰软件 | 小说 美女秀 图库大全 游戏 笑话 | 下载 开发知识库 新闻 开发 图片素材
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
移动开发 架构设计 编程语言 Web前端 互联网
开发杂谈 系统运维 研发管理 数据库 云计算 Android开发资料
  软件世界网 -> 移动开发 -> 使用Vitamio开发iOS平台上的万能播放器 -> 正文阅读

[移动开发]使用Vitamio开发iOS平台上的万能播放器


迅速了解


    Vitamio是干什么的?看官方怎么说:
   “Vitamio SDK for iOS是Yixia Ltd官方推出的 iOS 平台上使用的软件开发工具包(SDK),为iOS开发者提供简单、快捷的接口,帮助开发者实现 iOS 平台上的媒体播放应用。”
    说白了,就是可以帮助你便捷地开发自己的iOS播放器。

本文目标


    从0开始建工程,使用VitamioSDK开发一个最简单的播放器:打开app之后,能看到一个播放按钮,点击按钮,就开始播放事先放在Documents目录下的视频文件,再按一下按钮可以暂停。
    就这么简单。

准备工作


    下载Vitamio SDK:
    https://github.com/yixia/Vitamio-iOS
    当前版本是4.2.0。上个版本是1.1.3,这跳跃也太大了吧?估计是为了和安卓的Vitamio SDK保持同步。
    压缩包解压后内容如下:
 
[img]http://img.blog.csdn.net/20140106224410500?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzM5NTM3MA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
    Doc放文档,用浏览器打开Doc/html/index.html可查看Vitamio官方文档(还是苹果官方文档的风格哦)。各种接口什么的貌似齐全,但全英文看着有点眼花啊。
    Demo放了一个直接编译就能运行的工程,可以播放多个在线视频。你要是乐意,完全可以照着这个demo改造成自己想要的app。
    Vitamio放的就是我们将要用到的SDK。
 

具体步骤


 
    本文用于调试的真机是ipod touch5,系统是iOS7.0.4。

新建工程


    新建一个Single View工程
[img]http://img.blog.csdn.net/20140106224856625?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzM5NTM3MA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
    起个名字叫myPlayer
[img]http://img.blog.csdn.net/20140106225014796?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzM5NTM3MA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
 

简单UI


在storyboard中拖放三个控件,分别是UILabel,用于展示视频名称;UIView用于承载播放画面,UIButton用于播放或暂停。
[img]http://img.blog.csdn.net/20140106225138796?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzM5NTM3MA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
    按钮的default状态显示“播放”,selected状态显示“暂停”:
[img]http://img.blog.csdn.net/20140106225422828?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzM5NTM3MA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
    建立控件与变量的连接:
[img]http://img.blog.csdn.net/20140106225559109?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzM5NTM3MA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

UILabel是lblTitle
UIView是playerView
UIButton是btnPlayOrPause,点击事件是btnPlayOrPauseClick
再加一个NSString变量存视频地址
目前看起来这样:
 
[objc] view plaincopy[img]http://blog.csdn.net/meiwenjie110/article/details/51037424/https:/code.csdn.net/assets/CODE_ico.png[img]http://blog.csdn.net/meiwenjie110/article/details/51037424/https:/code.csdn.net/assets/ico_fork.svg
 
  1. @interface iTechBlueViewController : UIViewController  
  2. {  
  3.      NSString* videoPath;  
  4. }  
  5. @property (weak, nonatomic) IBOutlet UILabel *lblTitle;  
  6. @property (weak, nonatomic) IBOutlet UIView *playerView;  
  7. @property (weak, nonatomic) IBOutlet UIButton *btnPlayOrPause;  
  8. - (IBAction)btnPlayOrPauseClick:(id)sender;  
  9. @end  

 

检测视频文件


我们要遍历Documents文件夹下的文件,将找到的第一个视频文件的地址记住,并将其名称显示在UILabel上。
 
[objc] view plaincopy[img]http://blog.csdn.net/meiwenjie110/article/details/51037424/https:/code.csdn.net/assets/CODE_ico.png[img]http://blog.csdn.net/meiwenjie110/article/details/51037424/https:/code.csdn.net/assets/ico_fork.svg
 
  1. -(NSString*)findVideoInDocuments  
  2. {  
  3.     NSString *documentsDirectory = [NSString stringWithFormat:@"%@/Documents", NSHomeDirectory()];  
  4.     NSFileManager *fileMg = [[NSFileManager alloc] init];  
  5.   
  6.     //遍历Documents下的文件,找到视频文件就返回它的全路径  
  7.     NSArray *subPaths = [fileMg contentsOfDirectoryAtPath:documentsDirectory error:nil];  
  8.     if (subPaths) {  
  9.         for (NSString *subPath in subPaths) {  
  10.             if ( [self isMediaFile:[subPath pathExtension]]) {  
  11.                 NSString *path = [documentsDirectory stringByAppendingPathComponent:subPath];  
  12.                 return path;  
  13.             }  
  14.         }  
  15.     }  
  16.     return nil;  
  17. }  

[objc] view plaincopy[img]http://blog.csdn.net/meiwenjie110/article/details/51037424/https:/code.csdn.net/assets/CODE_ico.png[img]http://blog.csdn.net/meiwenjie110/article/details/51037424/https:/code.csdn.net/assets/ico_fork.svg
 
  1. -(BOOL)isMediaFile:(NSString*)pathExtension  
  2. {  
  3.     //可用格式  
  4.     /* 
  5.      ".M1V", ".MP2", ".MPE", ".MPG", ".WMAA", 
  6.      ".MPEG", ".MP4", ".M4V", ".3GP", ".3GPP", ".3G2", ".3GPP2", ".MKV", 
  7.      ".WEBM", ".MTS", ".TS", ".TP", ".WMV", ".ASF", ".ASX", ".FLV", 
  8.      ".MOV", ".QT", ".RM", ".RMVB", ".VOB", ".DAT", ".AVI", ".OGV", 
  9.      ".OGG", ".VIV", ".VIVO", ".WTV", ".AVS", ".SWF", ".YUV" 
  10.      */  
  11.       
  12.     //简单粗暴地判断是否为视频格式,这里先试6个  
  13.     NSString*ext = [pathExtension uppercaseString];  
  14.     if([ext isEqualToString:@"MP4"])  
  15.     {  
  16.         return YES;  
  17.     }  
  18.     else if([ext isEqualToString:@"MOV"])  
  19.     {  
  20.         return YES;  
  21.     }  
  22.     else if([ext isEqualToString:@"RMVB"])  
  23.     {  
  24.         return YES;  
  25.     }  
  26.     else if([ext isEqualToString:@"MKV"])  
  27.     {  
  28.         return YES;  
  29.     }  
  30.     else if([ext isEqualToString:@"FLV"])  
  31.     {  
  32.         return YES;  
  33.     }  
  34.     else if([ext isEqualToString:@"TS"])  
  35.     {  
  36.         return YES;  
  37.     }  
  38.   
  39.     return NO;  
  40. }  

[objc] view plaincopy[img]http://blog.csdn.net/meiwenjie110/article/details/51037424/https:/code.csdn.net/assets/CODE_ico.png[img]http://blog.csdn.net/meiwenjie110/article/details/51037424/https:/code.csdn.net/assets/ico_fork.svg
 
  1. - (void)viewDidLoad  
  2. {  
  3.     [super viewDidLoad];  
  4.   
  5.     videoPath = [self findVideoInDocuments];  
  6.     if(videoPath)  
  7.     {  
  8.         _lblTitle.text = [videoPath lastPathComponent];  
  9.     }  
  10. }  

 
现在编译一下看看有没有问题吧!
好,虽然没问题,但也只是我们拖出来的那个界面而已。
咱们现在用iFunBox往Documents文件夹下放一个视频吧。
什么!?你还没用过iFunBox?赶紧去下载一个试试,确实能给开发带来便利哦。
我放了一个特小的文件0.ts进去。
[img]http://img.blog.csdn.net/20140106230522296?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzM5NTM3MA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

再编译试试,这回题目就出来啦!

[img]http://img.blog.csdn.net/20140106230650656?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzM5NTM3MA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
 

添加Vitamio并配置工程(or not?)



现在我们已经有了视频文件并且获得了它的具体路径,接着就是要播放它了。开始使用Vitamio!
将上文解压后获得的Vitamio文件夹添加至工程:

[img]http://img.blog.csdn.net/20140106230928453?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzM5NTM3MA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
[img]http://img.blog.csdn.net/20140106231108984?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzM5NTM3MA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

添加后如果你手痒编译,竟然发现是能编译成功的!
难道VitamioSDK这么强悍,不需要任何配置就能用了?且往下看。

写播放器代码


引入Vitamio头文件

 
[objc] view plaincopy[img]http://blog.csdn.net/meiwenjie110/article/details/51037424/https:/code.csdn.net/assets/CODE_ico.png[img]http://blog.csdn.net/meiwenjie110/article/details/51037424/https:/code.csdn.net/assets/ico_fork.svg
 
  1. #import "Vitamio.h"  

 

声明一个播放器变量
 
[objc] view plaincopy[img]http://blog.csdn.net/meiwenjie110/article/details/51037424/https:/code.csdn.net/assets/CODE_ico.png[img]http://blog.csdn.net/meiwenjie110/article/details/51037424/https:/code.csdn.net/assets/ico_fork.svg
 
  1. VMediaPlayer       *mMPayer;  

声明使用播放器协议
 

 
[objc] view plaincopy[img]http://blog.csdn.net/meiwenjie110/article/details/51037424/https:/code.csdn.net/assets/CODE_ico.png[img]http://blog.csdn.net/meiwenjie110/article/details/51037424/https:/code.csdn.net/assets/ico_fork.svg
 

  1. <VMediaPlayerDelegate>  
     

 
以上三行代码写好,Vitamio SDK的各种接口就可以任你调遣了。这是最精简的配置。
VMediaPlayerVMediaPlayerDelegate都藏了什么好东西?我们只能边学变探索。
现在咱们的头文件看起来是这样的:
 
[objc] view plaincopy[img]http://blog.csdn.net/meiwenjie110/article/details/51037424/https:/code.csdn.net/assets/CODE_ico.png[img]http://blog.csdn.net/meiwenjie110/article/details/51037424/https:/code.csdn.net/assets/ico_fork.svg
 
  1. #import   
  2. #import "Vitamio.h"  
  3.   
  4. @interface iTechBlueViewController : UIViewController  
  5. {  
  6.     NSString* videoPath;  
  7.     VMediaPlayer       *mMPayer;  
  8. }  
  9. @property (weak, nonatomic) IBOutlet UILabel *lblTitle;  
  10. @property (weak, nonatomic) IBOutlet UIView *playerView;  
  11. @property (weak, nonatomic) IBOutlet UIButton *btnPlayOrPause;  
  12. - (IBAction)btnPlayOrPauseClick:(id)sender;  
  13. @end  

初始化播放器,以下代码是初始化播放器的最精简写法。
 
 
[objc] view plaincopy[img]http://blog.csdn.net/meiwenjie110/article/details/51037424/https:/code.csdn.net/assets/CODE_ico.png[img]http://blog.csdn.net/meiwenjie110/article/details/51037424/https:/code.csdn.net/assets/ico_fork.svg
 
  1. -(void)initPlayer  
  2. {  
  3.     if (!mMPayer) {  
  4.         mMPayer = [VMediaPlayer sharedInstance];  
  5.         [mMPayer setupPlayerWithCarrierView:self.playerView withDelegate:self];  
  6.     }  
  7. }  

 
可以看到,我们将自己拖到界面上的playerView传了过去,表示要用它来承载视频画面。
准备播放视频,同样,下面代码是准备播放视频最精简的写法:
 
[objc] view plaincopy[img]http://blog.csdn.net/meiwenjie110/article/details/51037424/https:/code.csdn.net/assets/CODE_ico.png[img]http://blog.csdn.net/meiwenjie110/article/details/51037424/https:/code.csdn.net/assets/ico_fork.svg
 
  1. -(void)prepareVideo  
  2. {  
  3.     if(videoPath)  
  4.     {  
  5.           //播放时不要锁屏  
  6.         [UIApplication sharedApplication].idleTimerDisabled = YES;   
  7.         NSURL* videoURL = [NSURL fileURLWithPath:videoPath];  
  8.         [mMPayer setDataSource:videoURL];  
  9.         [mMPayer prepareAsync];  
  10.     }  
  11. }  

 
我们的代码写到prepareAsync,就把工作丢给Vitamio了。它会在准备好后在协议方法中通知我们的。
如果这时候你是一副“啥意思”的表情,请看工程的这个地方:
[img]http://img.blog.csdn.net/20140106231847109?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzM5NTM3MA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
 
它在警告你:有些method没有实现,那是因为我们引用了VMediaPlayerDelegate之后还没去实现它需要的几个方法:
[img]http://img.blog.csdn.net/20140106231943468?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzM5NTM3MA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
 
@required表示,以上三个方法是必须的,我们一一实现之。
首先添加一个布尔变量BOOL didPrepared,它非常重要,是我们的代码首次介入播放器的逻辑。
didPrepared是在Vitamio准备好播放视频后被调用的,我们可以在这时候记录下布尔值——播放准备好了,同时让播放器开始播放:
 
[objc] view plaincopy[img]http://blog.csdn.net/meiwenjie110/article/details/51037424/https:/code.csdn.net/assets/CODE_ico.png[img]http://blog.csdn.net/meiwenjie110/article/details/51037424/https:/code.csdn.net/assets/ico_fork.svg
 
  1. - (void)mediaPlayer:(VMediaPlayer *)player didPrepared:(id)arg  
  2. {  
  3.      //显示“暂停”两字  
  4.     _btnPlayOrPause.selected = YES;  
  5.     didPrepared = YES;  
  6.      [player start];  
  7. }  

playbackComplete会在视频播放结束后被调用,这时可以记录播放历史、退出播放器什么的,但这里我们要的是最简,所以将播放器重置,从而要再播放的话,就得调用我们写的prepareVideo,这时didPrepared设为NO。
 
 
[objc] view plaincopy[img]http://blog.csdn.net/meiwenjie110/article/details/51037424/https:/code.csdn.net/assets/CODE_ico.png[img]http://blog.csdn.net/meiwenjie110/article/details/51037424/https:/code.csdn.net/assets/ico_fork.svg
 
  1. - (void)mediaPlayer:(VMediaPlayer *)player playbackComplete:(id)arg  
  2. {  
  3.     _btnPlayOrPause.selected = NO;  
  4.     [player reset];  
  5.     didPrepared = NO;  
  6. }  

error会在Vitamio处理视频出错时被调用,让你有机会提醒用户或做其他处理,这里我们只是默默得打一个log:
 
 
[objc] view plaincopy[img]http://blog.csdn.net/meiwenjie110/article/details/51037424/https:/code.csdn.net/assets/CODE_ico.png[img]http://blog.csdn.net/meiwenjie110/article/details/51037424/https:/code.csdn.net/assets/ico_fork.svg
 
  1. - (void)mediaPlayer:(VMediaPlayer *)player error:(id)arg  
  2. {  
  3.     NSLog(@"VMediaPlayer Error: %@", arg);  
  4. }  

记得在ViewDidLoad中调用initPlayer进行初始化,变这样:
 
 
[objc] view plaincopy[img]http://blog.csdn.net/meiwenjie110/article/details/51037424/https:/code.csdn.net/assets/CODE_ico.png[img]http://blog.csdn.net/meiwenjie110/article/details/51037424/https:/code.csdn.net/assets/ico_fork.svg
 
  1. - (void)viewDidLoad  
  2. {  
  3.     [super viewDidLoad];  
  4.   
  5.     videoPath = [self findVideoInDocuments];  
  6.     if(videoPath)  
  7.     {  
  8.         _lblTitle.text = [videoPath lastPathComponent];  
  9.         [self initPlayer];  
  10.     }  
  11. }  

如果你想一打开app就播放视频,可以将第一次prepareVideo放在ViewDidAppear中。
在按钮点击中控制播放还是暂停:
 
[objc] view plaincopy[img]http://blog.csdn.net/meiwenjie110/article/details/51037424/https:/code.csdn.net/assets/CODE_ico.png[img]http://blog.csdn.net/meiwenjie110/article/details/51037424/https:/code.csdn.net/assets/ico_fork.svg
 
  1. - (IBAction)btnPlayOrPauseClick:(id)sender {  
  2.     if(videoPath)  
  3.     {  
  4.         BOOL isPlaying = [mMPayer isPlaying];  
  5.         if (isPlaying) {  
  6.             [mMPayer pause];  
  7.             _btnPlayOrPause.selected = NO;  
  8.         } else {  
  9.             if(didPrepared)  
  10.                 [mMPayer start];  
  11.             else  
  12.                 [self prepareVideo];  
  13.             _btnPlayOrPause.selected = YES;  
  14.         }  
  15.     }  
  16. }  

 
这里用Vitamio接口isPlaying来判断是否正在播放是最准确的,比我们自己维护一个播放状态要好。
但视频是否准备好这个状态由我们记录(didPrepared)。
点击播放时比想象中复杂,是因为要判断视频是否已经准备好,如果是的话继续播放,如果没有的话得调用做准备的方法。
写到这,代码好像就完成啦!去编译吧!去启动你写的第一个播放器吧少年!
 

配置Vitamio


你当时就震惊了。代码写得好顺利,现在一编译,为什么直接就failed了呢?出来50个error!
不用着急这调试,你该记起在VitamioSDK 添加进来后还没有配置吧?
原来还是得配置的,刚才开心得太早。。。
首先需要去Build Phases添加些framework和dylib,如下所示:
[img]http://img.blog.csdn.net/20140106232522703?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzM5NTM3MA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

文字版如下:
如果你有强迫症,倒序添加下面的库,得到的就是按首字母从小到大排列的顺序
[plain] view plaincopy[img]http://blog.csdn.net/meiwenjie110/article/details/51037424/https:/code.csdn.net/assets/CODE_ico.png[img]http://blog.csdn.net/meiwenjie110/article/details/51037424/https:/code.csdn.net/assets/ico_fork.svg
 
  1. libbz2.dylib  
  2. libiconv.dylib  
  3. libstdc++.dylib  
  4. libz.dylib  
  5.   
  6. AVFoundation.framework  
  7. AudioToolbox.framework  
  8. CoreMedia.framework  
  9. CoreVideo.framework  
  10. MediaPlayer.framework  
  11. OpenGLES.framework  
  12. QuartzCore.framework  

添加后再编译。
欧耶,编译通过啦!
但是点击播放后会崩溃,有一条log是:
[plain] view plaincopy[img]http://blog.csdn.net/meiwenjie110/article/details/51037424/https:/code.csdn.net/assets/CODE_ico.png[img]http://blog.csdn.net/meiwenjie110/article/details/51037424/https:/code.csdn.net/assets/ico_fork.svg
 
  1. [UIDevice platformString]: unrecognized selector sent to instance  

还是不着急调试,去到Build Setting,找到Linking下的Other Linker Flags,添加“-ObjC”:
[img]http://img.blog.csdn.net/20140106233108437?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzM5NTM3MA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
然后编译再试,oh my god!可以播放啦!
如果这时候你依然很冷静,在思考一个问题:为啥这么一设就好了呢?其实Vitamio sdk作者早已料到你有此一问,你可以在上文提到的Doc文件夹下找到一个FAQ.md文件,里面就专门对这个问题进行了解答。
另外,我不会告诉你,Doc下的 Vitamio_SDK_for_iOS_User_Manual_cn.md是一篇比本博文更简洁但信息足够齐全的中文教程。你值得一读。
 

多说两句


能够播放和暂停是一个好的开始,但你肯定觉得不够。停止呢?进度控制呢?时长呢?快放呢?后台播放呢?切换上一首下一首呢?截图呢?视频缩略图呢?播放在线视频呢?……
各种播放器该有的功能在以后的博客里都会讲到,敬请期待。
最后,记得设置你工程的version为1.0。

源码在这

https://github.com/itechblue/myPlayer

来源:http://blog.csdn.net/itechblue/article/details/17932151
......显示全文...
    点击查看全文


上一篇文章      下一篇文章      查看所有文章
2016-04-02 20:51:48  
移动开发 最新文章
深入了解android中的消息机制Handler
Android
Libgdx之BitmapFont字体
AndroidApp发布到应用市场的流程
Android开发找工作之前先看看这些知识点吧
View的事件分发机制解析
简单介绍了解白鹭引擎Egret
Cocos2d
android获取本地图片(二)
动画特效七:碰撞动画
360图书馆 软件开发资料 文字转语音 购物精选 软件下载 美食菜谱 新闻资讯 电影视频 小游戏 Chinese Culture
生肖星座 三丰软件 视频 开发 Android开发 站长 古典小说 网文精选 搜图网 美图 中国文化英文版 多播 租车 短信
2017-7-26 10:42:32
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  软件世界网 --