软件世界网 购物 网址 三丰软件 | 小说 美女秀 图库大全 游戏 笑话 | 下载 开发知识库 新闻 开发 图片素材
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
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 股票 租车
生肖星座 三丰软件 视频 开发 短信 中国文化 网文精选 搜图网 美图 阅读网 多播 租车 短信 看图 日历 万年历 2018年1日历
2018-1-16 21:24:05
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  软件世界网 --