1.x.x Migration Guide
Overview
This project is a sample Demo for the VOD SDK 2.x.x. Its 1.x.x project is polyv-ios-client-demo. Since 2.x.x was not developed as a continuation of 1.x.x, they are not in the same project. Consequently, the 2.x.x APIs also differ from those in 1.x.x.
This document explains how to quickly migrate from the VOD 1.x.x SDK to 2.x.x using common usage patterns.
Configuring the Player
Class name changes:
| 1.x.x | 2.x.x |
|---|---|
| SkinVideoViewController | PLVVodSkinPlayerController |
For detailed configuration, refer to PLVSimpleDetailController, PLVCourseDetailController, or PLVVodVidTestController.
Deployment
1.x.x deployment:
// 初始化
_videoPlayer = [[SkinVideoViewController alloc] initWithFrame:CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y, width, width*(9.0/16.0))];
[_videoPlayer configObserver];
// 添加到视图
[self.view addSubview:self.videoPlayer.view];
[self.videoPlayer setParentViewController:self];
// 需要保留导航栏
[self.videoPlayer keepNavigationBar:YES];
[self.videoPlayer setNavigationController:self.navigationController];
2.x.x no longer uses frame-based layout; instead, it adopts Auto Layout. To simplify Auto Layout usage for developers, 2.x.x eliminates the need for manual Auto Layout code. Instead, you need to pre-layout a placeholder view for portrait or half-screen states:

The 2.x.x player deployment code is as follows:
PLVVodSkinPlayerController *player = [[PLVVodSkinPlayerController alloc] initWithNibName:nil bundle:nil];
[player addPlayerOnPlaceholderView:self.playerPlaceholder rootViewController:self];
self.player = player;
2.x.x player deployment does not require actively calling configuration methods; the SDK internally handles configuration at the appropriate time.
To have the player control the status bar style, as shown in the Demo, you also need to implement two UIViewController methods.
- (BOOL)prefersStatusBarHidden {
return self.player.prefersStatusBarHidden;
}
- (UIStatusBarStyle)preferredStatusBarStyle {
return self.player.preferredStatusBarStyle;
}
Since the
PLVVodPlayerViewControllerbase player class is a subclass ofUIViewController, you can even operate the player like a regularUIViewControllerobject.
Setting the Video to Play
1.x.x setting the video to play:
[self.videoPlayer setVid:self.video.vid];
2.x.x setting the video to play:
_weak typeof(self) weakSelf = self;
[PLVVodVideo requestVideoWithVid:vid completion:^(PLVVodVideo *video, NSError *error) {
if (!video.available) return;
weakSelf.player.video = video;
}];
In 2.x.x, playing a video with a given vid involves obtaining a PLVVodVideo object and passing it to the player. Although this is more complex than before, it significantly improves data consistency. For example, the SDK's video download interface also uses the PLVVodVideo object to add downloads. Additionally, it enhances the reusability of video data; by accessing the properties of the obtained PLVVodVideo object, users can retrieve all available information about the video.
Player Feature Configuration and Status Callbacks
For 2.x.x player feature configuration and status retrieval/callbacks, refer to Player Configuration.
Configuring the Downloader
Class name changes:
| 1.x.x | 2.x.x |
|---|---|
| PvUrlSessionDownload | PLVVodDownloadManager PLVVodDownloadInfo |
Creating the Downloader
1.x.x downloader creation:
PvUrlSessionDownload *downloader = [[PvUrlSessionDownload alloc] initWithVid:video.vid level:video.level];
//设置下载代理为自身,需要实现四个代理方法download delegate
[downloader setDownloadDelegate:self];
[downloader start];
In 2.x.x, developers do not need to actively create and manage downloaders. Instead, use PLVVodDownloadManager to uniformly manage a download queue; developers only need to start or stop the queue. Thus, adding a downloader becomes adding it to the queue for download:
PLVVodDownloadManager *downloadManager = [PLVVodDownloadManager sharedManager];
PLVVodDownloadInfo *info = [downloadManager downloadVideo:self.video];
[downloadManager startDownload];
Status Monitoring
1.x.x status monitoring:
// 下载失败回调
- (void)dataDownloadFailed:(PvUrlSessionDownload *)downloader withVid:(NSString *)vid reason:(NSString *)reason {
[[FMDBHelper sharedInstance] updateDownloadStatic:vid status:-1];
NSLog(@"dataDownloadFailed %@ - %@", vid, reason);
}
// 实时获取下载进度百分比回调
- (void)dataDownloadAtPercent:(PvUrlSessionDownload *)downloader withVid:(NSString *)vid percent:(NSNumber *)aPercent {
// !!!: 频繁写入数据库会造成UI卡顿风险,因此此处是隔3秒更新一次数据库
NSTimeInterval timeDiff = [[NSDate date] timeIntervalSinceDate:self.lastTime];
if (timeDiff > 3) {
[[FMDBHelper sharedInstance] updateDownloadPercent:vid percent:aPercent];
self.lastTime = [NSDate date];
}
Video *video = self.videoDic[vid];
video.percent = aPercent.floatValue;
[self updateCellWithVid:vid];
}
// 实时下载速率回调
- (void)dataDownloadAtRate:(PvUrlSessionDownload *)downloader withVid:(NSString *)vid rate:(NSNumber *)aRate {
Video *video = self.videoDic[vid];
video.rate = aRate.floatValue;
[self updateCellWithVid:vid];
}
// 下载状态回调
- (void)downloader:(PvUrlSessionDownload *)downloader withVid:(NSString *)vid didChangeDownloadState:(PLVDownloadState)state {
switch (state) {
case PLVDownloadStatePreparing:{
}break;
case PLVDownloadStateReady:{
NSLog(@"%@ 任务创建", vid);
}break;
case PLVDownloadStateRunning:{
NSLog(@"%@ 任务开始", vid);
}break;
case PLVDownloadStateStopping:{
NSLog(@"%@ 正在停止", vid);
}break;
case PLVDownloadStateStopped:{
NSLog(@"%@ 任务停止", vid);
}break;
case PLVDownloadStateSuccess:{
NSLog(@"%@ 任务完成", vid);
[[FMDBHelper sharedInstance] updateDownloadPercent:vid percent:[NSNumber numberWithInt:100]];
[[FMDBHelper sharedInstance] updateDownloadStatic:vid status:1];
}break;
case PLVDownloadStateFailed:{
}break;
default:{}break;
}
}
1.x.x uses the delegate methods of the PvUrlSessionDownload downloader object for status callbacks and monitoring. Developers need to manage and maintain each downloader object and cannot actively retrieve its download status.
2.x.x uses the PLVVodDownloadInfo download info object to report download information. This object can be obtained from the return value when adding a download.
/**
添加至下载队列
添加下载器,仅当 video 错误时,才会报错,quality 错误时,只会警告,并切换到最近的质量进行下载。
@param video PLVVodVideo 视频对象
@param quality 视频画质
@return 下载信息
*/
- (PLVVodDownloadInfo *)downloadVideo:(PLVVodVideo *)video quality:(PLVVodQuality)quality;
/**
使用后台设置的默认画质添加至下载队列
@param video PLVVodVideo 视频对象
@return 下载信息
*/
- (PLVVodDownloadInfo *)downloadVideo:(PLVVodVideo *)video;
Developers can retrieve the status via the PLVVodDownloadInfo object's properties and handle callbacks by implementing its corresponding Blocks:
/// 下载状态
@property (nonatomic, assign, readonly) PLVVodDownloadState state;
@property (nonatomic, copy) void (^stateDidChangeBlock)(PLVVodDownloadInfo *info);
/// 下载速率(单位:byte/s)
@property (nonatomic, assign, readonly) double bytesPerSeconds;
@property (nonatomic, copy) void (^bytesPerSecondsDidChangeBlock)(PLVVodDownloadInfo *info);
/// 下载进度(0-1)
@property (nonatomic, assign, readonly) double progress;
@property (nonatomic, copy) void (^progressDidChangeBlock)(PLVVodDownloadInfo *info);
For example, to get the download progress:
// 获取 `PLVVodDownloadInfo` 对象
PLVVodDownloadInfo *info;
info.progressDidChangeBlock = ^(PLVVodDownloadInfo *info) {
NSLog(@"downlaod %@ progress: %@", info.vid, [NSNumberFormatter localizedStringFromNumber:@(info.progress) numberStyle:NSNumberFormatterPercentStyle]);
};
Error Handling
In 1.x.x, download error information is returned via the PvUrlSessionDownload delegate method ataDownloadFailed:withVid:reason:, with error information containing only a string, making it difficult to locate the cause.
In 2.x.x, error information generated during downloads is uniformly presented to the user via the PLVVodDownloadManager callback property:
/// 下载错误回调
@property (nonatomic, copy) void (^downloadErrorHandler)(PLVVodVideo *video, NSError *error);
2.x.x uses the standard NSError object to encapsulate detailed error information. Developers can more easily understand, locate, and resolve errors through the NSError object.
