如何开发一个 AVPlayer iPad 程序
airplay 并不是新东西,它在 ios 4.3 sdk 中就存在了。但airplay api 中不断有新的东西加入。其中一个有趣新特性是 ipad 程序能通过 apple tv 2 播放来自 ios 设备上的内容,或者镜像ipad 2 上的屏幕内容。
简而言之,airplay 就是将媒体内容投放到高清显示器(电视)或高清音效上。apple tv 2 则是用于连接 ios 设备或 itunes与高清设备之间的桥梁。
随着 ios 5 的出现,任何使用 av foundation 类的程序都能从程序中投放音视频内容到 apple tv。你可以用mpmoviewplayercontroller 通过 airplay 将当前正在播放的内容投影到高清电视或其它高清显示设备上。另一个进步是从uiwebview 投放视频,这是激动人心的改进,因为这意味着我们可以直接从 web 上将在线的音视频投影到电视或者 apple tv 2 上。
使用 avfoundation 投影视频内容
要在应用程序中使用 avfoundation,需要实现 avplayer 并设置 allowsairplayvideo 为 yes 以开启 airplay,或者设置为no 以关闭 airplay,如以下代码所示:
-(bool)setairplay:(bool)airplaymode{
return self.player.allowsairplayvideo=airplaymode;
}
编写应用程序
为了演示如何创建 avplayer 应用程序以及实现 airplay,我们将创建一个 single view application(注意勾选 usestoryboards),新建一个 avplayer 类并实现 airplay 特性。
创建一个 single view application。目标类型可以选择 iphone、ipod 或者 ipad。创建项目之后,再导入 av foundation 框架。
接着创建一个新 class,命名为 player,并继承 uiview 类。在头文件中,加入 avplayer 类并增加一个 avplayer 属性。如下列代码所示。
@class avplayer;
@interface player : uiview
@property(nonatomic, strong) avplayer * player;
接下来就是实现 player 类。
我们实现了最基本的 avplayer 需要实现的最起码的 4 个方法,同时还提供了一个方法作为我们的 airplay 开关。
首先我们需要一个 avlayer 类的包装类。该类是一个 calayer 子类,用于对媒体的可视内容进行管理。创建包装类的代码如下:
+ (class)layerclass {
return [avplayerlayer class];
}
然后为需要一个方法,实例化一个 avplayer 对象(我们在头文件中定义的)。如下列代码所示。
-(avplayer *) player{
return [(avplayerlayer *)[self layer] player];
}
在 setplayer 方法中,如下列代码所示,有一个 avplayer 参数,用于将一个 avplayer 实例添加到 uiview。这个 uiview 子类,将用在主 view controller 中。
- (void)setplayer:(avplayer*)player {
[(avplayerlayer*)[self layer] setplayer:player];
}
这个类的最后一个方法是 setairplay 方法。其参数将用于指定 avplayer uiview (player)的allowsairplayvideo 属性。如以下代码所示。
-(bool)setairplay:(bool)airplaymode{
return self.player.allowsairplayvideo=airplaymode;
}
为视频的输出指定图层(avplayerlayer)时,可以指定任意数量的图层,只要能方便控制内容显示。比如说处理音频和视频之间的时间同步。通过setdisplaymode,你可以设置用于显示的图层,先创建一个 avplayerlayer 对象作为显示图层,然后修改它的属性。默认是avlayervideogravityresizeaspect 属性,另外也可以设置 avlayervideogravityresizeaspectfill 属性和avlayervideogravityresize 属性。 avlayervideogravityresizeaspect 保持视频的宽高比并使播放内容自动适应播放窗口的大小。avlayervideogravityresizeaspectfill 和前者类似,但它是以播放内容填充而不是适应播放窗口的大小。最后一个值会拉伸播放内容以适应播放窗口。
player 类的完整代码如下:
#import <uikit/uikit.h>
#import <avfoundation/avfoundation.h>
@class avplayer;
@interface player : uiview
@property(nonatomic, strong) avplayer * player;
-(bool) setairplay:(bool) airplaymode;
@end
#import "player.h"
#import <avfoundation/avfoundation.h>
@implementation player
+ (class)layerclass {
return [avplayerlayer class];
}
-(avplayer *) player{
return [(avplayerlayer *)[self layer] player];
}
- (void)setplayer:(avplayer*)player {
[(avplayerlayer*)[self layer] setplayer:player];
}
//enable or disable airplay mode
-(bool)setairplay:(bool)airplaymode{
return self.player.allowsairplayvideo=airplaymode;
}
@end
在程序中使用 player (uiview子类)
上述代码包括了player (avplayer 的 uiview 子类)的.h文件和.m 文件。
要在一个 uiviewcontroller 中使用这个 avplayer 视图,打开 xcode 的故事板(storyboard,前提是创建项目时使用了“usestoryboard”选项)。选中uiview(不是 uiviewcontroller)并将它的类修改为 player。你可以在 identity 面板的 customeclass 字段输入,也可以从它的下拉列表中选择。
打开 assistant editor ,为 uiview 子类 player 创建一个 iboutlet,从 view 用右键拖到右边的头文件中即可。如下图所示。
创建ibactions 和 iboutlets 连接
创建一个委托到 klviewcontroller 。在 player 上右键,从 iboutlet 拖一个连接线到 klviewcontroller (dock 上的黄色方块) ,如下图所示。
添加委托连接 klviewcontroller
在故事版中,加一个 toolbar 。在 toolbar 是加入两个按钮,分别将标签文本设置为 play 和 pause。然后加一个 switch,用于切换airplay 开关状态。为这 3 个控件创建相应的 ibaction(可以用 assistant editor)。剩下的事情在 klviewcontroller 类中进行。
打开 klviewcontroller.h 文件,加入 @class player 和 @class avplayer 语句并导入 avfoundation 框架和 player.h。源代码见下:
#import <uikit/uikit.h>
#import <avfoundation/avfoundation.h>
#import "player.h"
@class player;
@class avplayer;
@interface klviewcontroller : uiviewcontroller
声明一个 avplayer 属性,用于加载到 palyer 视图中。
声明一个 nsurl 属性。然后是 switch 控件的 iboutlet(用 assistant editor创建)。
kvliewcontroller.h 文件代码如下:
#import <uikit/uikit.h>
#import <avfoundation/avfoundation.h>
#import player.h
@class player;
@class avplayer;
@interface klviewcontroller : uiviewcontroller
@property(nonatomic, strong) avplayer * myplayer;
@property(nonatomic, strong) nsurl * avcontenturl;
@property (strong, nonatomic) iboutlet player *airplayview;
@property (nonatomic, retain) iboutlet uiswitch * airplayswitch;
- (ibaction)playvideo:(id)sender;
- (ibaction)pausevideo:(id)sender;
- (ibaction)isairplayon:(id)sender;
@end
接下来是类的实现文件。在 viewdidload 方法中,用一个视频文件的 url 地址初始化 avcontenturl:
avcontenturl = [[nsurl alloc] initwithstring
然后用 avcontenturl 初始化一个 avplayer ,用于给头文件中定义的 myplayer 属性赋值。将 myplayer 赋给 airplayview 的 player 属性,airplayerview 是一个 player 对象。如下列代码所示:
self.myplayer = [avplayer playerwithurl:avcontenturl];
[airplayview setplayer:[self myplayer]];
现在,要实现两个按钮的视频播放和暂停功能,以及 switch 控件的 airplay 开关功能。播放按钮的 action 方法代码如下所示:
- (ibaction)playvideo:(id)sender {
[self.myplayer play];
}
暂停按钮的 action 方法代码如下所示:
- (ibaction)pausevideo:(id)sender {
[self.myplayer pause];
}
switch 控件的 action 方法代码如下所示:
- (ibaction)isairplayon:(id)sender {
airplayswitch = (uiswitch *) sender;
if (airplayswitch.on) {
[airplayview setairplay:no];
}else
{
[airplayview setairplay:yes];
}
}
结尾
另一个与 airplay 有关的属性是 usesairplayvideowhileairplayscreenisactive ,它用于自动在在播放期间将 avplayer 切换到 airplay,当然仅仅是在 airplay 已开启的情况下。默认是 false 的。
要运行本示例程序,需要在 ipad 上进行,并将 ipad 连接至 apple tv 同一 wifi 网络,然后视频资源的 url 必须是有效的。在模拟器中airplay 是无效的。
klviewcontroller.h 文件
#import <uikit/uikit.h>
#import <avfoundation/avfoundation.h>
#import "player.h"
@class player;
@class avplayer;
@interface klviewcontroller : uiviewcontroller
@property(nonatomic, strong) avplayer * myplayer;
@property(nonatomic, strong) nsurl * avcontenturl;
@property (strong, nonatomic) iboutlet player *airplayview;
@property (nonatomic, retain) iboutlet uiswitch * airplayswitch;
- (ibaction)playvideo:(id)sender;
- (ibaction)pausevideo:(id)sender;
- (ibaction)isairplayon:(id)sender;
@end
klviewcontroller.m 文件
#import "klviewcontroller.h"
@implementation klviewcontroller
@synthesize airplayview;
@synthesize avcontenturl, myplayer, airplayswitch;
- (void)didreceivememorywarning
{
[super didreceivememorywarning];
// release any cached data, images, etc that aren't in use.
}
#pragma mark - view lifecycle
- (void)viewdidload
{
[super viewdidload];
//this is an apple sample video
avcontenturl = [[nsurl alloc] initwithstring:@" self.myplayer = [avplayer playerwithurl:avcontenturl];
[airplayview setplayer:[self myplayer]];
[self.myplayer play];
}
- (void)viewdidunload
{
[self setairplayview:nil];
[super viewdidunload];
// release any retained subviews of the main view.
// e.g. self.myoutlet = nil;
}
- (void)viewwillappear:(bool)animated
{
[super viewwillappear:animated];
}
- (void)viewdidappear:(bool)animated
{
[super viewdidappear:animated];
}
- (void)viewwilldisappear:(bool)animated
{
[super viewwilldisappear:animated];
}
- (void)viewdiddisappear:(bool)animated
{
[super viewdiddisappear:animated];
}
- (bool)shouldautorotatetointerfaceorientation:(uiinterfaceorientation)interfaceorientation
{
// return yes for supported orientations
return (interfaceorientation != uiinterfaceorientationportraitupsidedown);
}
- (ibaction)playvideo:(id)sender {
[self.myplayer play];
}
- (ibaction)pausevideo:(id)sender {
[self.myplayer pause];
}
- (ibaction)isairplayon:(id)sender {
airplayswitch = (uiswitch *) sender;
if (airplayswitch.on) {
[airplayview setairplay:no];
}else
{
[airplayview setairplay:yes];
}
}
@end
上一篇: ios MVC 结构问题