封装WKWebView播放YouTuBe视频的播放器

ps:上个项目做过有关YouTube视频播放的功能,之前在GitHub上搜的是使用UIWebView加载html的方式播放,由于UIWebView自身的缺陷问题,对内存消耗是个大问题,iOS8之后推出的WebKit框架中的WKWebView极大程度上解决了这个难题,于是乎,笔者就想到用WKWebView代替UIWebView去封装一个YouTube视频播放控件,花了一些时间搞了搞。 YouTube视频播放前提是要能翻墙

定制播放控件

1.YouTube采用的是网页加载html文件完成功能,所以本地搞个Html文件,在html中做的主要是调用Youtube的iframe api,初始化播放器,并且规定和客户端交互的scheme,简单的代码如下:
 var tag = document.createElement('script');
            tag.src = "https://www.youtube.com/iframe_api";
            var firstScriptTag = document.getElementsByTagName('script')[0];
            firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
            //这个函数创建一个< iframe >(和YouTube播放器)zPUdFID3lmo   M7lc1UVf-VE
            var player;
            var errorCode = -1;//用来记录错误码
            function onYouTubeIframeAPIReady() {
                player = new YT.Player('player',%@);
                player.setSize(window.innerWidth, window.innerHeight);
            }
复制代码

html中的一些播放控制事件定义:

 function onPlayerReady(event) {
                event.target.playVideo();
                console.log('开始');
                window.location.href = 'wabridge://onPlayerReady?data=' + event.data;
            }
            //当播放器的状态改变时,这个函数调用这个函数
            var done = false;
            function onPlayerStateChange(event) {
                window.location.href = 'wabridge://onPlayerStateChange?data=' + event.data + "&errorCode=" + errorCode;
            }
            //此事件在播放器出错时触发。
            function onPlayerError(event) {
                console.log('播放失败');
                    errorCode = event.data;
                //window.location.href = 'wabridge://onPlayerError?data=' + event.data;
            }
复制代码

另外在OC端代码中,webviewJavascriptBridge代码中作如下处理:

#define urlScheme @"wabridge"

- (void)webView:(WKWebView *)webView
decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction
decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    if (webView != _webView) { return; }
    NSURL *url = navigationAction.request.URL;
    __strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate;
    if ([_base isCorrectProcotocolScheme:url]) {
        if ([_base isBridgeLoadedURL:url]) {
            [_base injectJavascriptFile];
        } else if ([_base isQueueMessageURL:url]) {
            [self WKFlushMessageQueue];
        }else {
            [_base logUnkownMessage:url];
        }
        decisionHandler(WKNavigationActionPolicyCancel);
    }
    
    else if ([[url scheme] isEqualToString:urlScheme]) {
        [self handleQuery:url];
        decisionHandler(WKNavigationActionPolicyCancel);
    }
    else if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:decidePolicyForNavigationAction:decisionHandler:)]) {
        [_webViewDelegate webView:webView decidePolicyForNavigationAction:navigationAction decisionHandler:decisionHandler];
    } else {
        decisionHandler(WKNavigationActionPolicyAllow);
    }
}
复制代码

这里的urlScheme就是根据html中的waBridge来定义的

2. 封装播放控制器

我这里主要是实现了几个简单的常用功能:开始播放,暂停,停止播放,跳转到指定时长进行播放等,下面就贴出代码,对各个功能进行实现:

2.1开始播放视频
/**
 play video with videoId
 **/
- (BOOL)playVideoWithVideoId:(NSString *)videoId {

    NSDictionary *dic = @{@"autoplay":@1,@"controls":@2,@"playsinline":@1,@"origin":YouTubeOrigin};
    return  [self playVideoWithVideoId:videoId playerVars:dic];
}
复制代码
/**
 play video with videoId and playerVars
 **/
- (BOOL)playVideoWithVideoId:(NSString *)videoId playerVars:(NSDictionary *)playerVars {
    if (!playerVars) {
        playerVars = @{};
    }
    NSDictionary *playerParams = @{ @"videoId" : videoId, @"playerVars" : playerVars };
    return [self playVideoWithParams:playerParams];
}
复制代码
/*
 play video with playerVars
 **/
- (BOOL)playVideoWithParams:(NSDictionary *)additionalPlayerParams {
    NSDictionary *playerCallbacks = @{
                                      @"onReady" : @"onPlayerReady",
                                      @"onStateChange" : @"onPlayerStateChange",
                                      @"onError" : @"onPlayerError"
                                      };
    NSMutableDictionary *playerParams = [[NSMutableDictionary alloc] init];
    if (additionalPlayerParams) {
        [playerParams addEntriesFromDictionary:additionalPlayerParams];
    }
    if (![playerParams objectForKey:@"height"]) {
        [playerParams setValue:@"100%" forKey:@"height"];
    }
    if (![playerParams objectForKey:@"width"]) {
        [playerParams setValue:@"100%" forKey:@"width"];
    }
    
    [playerParams setValue:playerCallbacks forKey:@"events"];
    
    if ([playerParams objectForKey:@"playerVars"]) {
        NSMutableDictionary *playerVars = [[NSMutableDictionary alloc] init];
        [playerVars addEntriesFromDictionary:[playerParams objectForKey:@"playerVars"]];
        
        if (![playerVars objectForKey:@"origin"]) {
            self.originalURL = [NSURL URLWithString:YouTubeOrigin];
        } else {
            self.originalURL = [NSURL URLWithString: [playerVars objectForKey:@"origin"]];
        }
    } else {
        // This must not be empty so we can render a '{}' in the output JSON
        [playerParams setValue:[[NSDictionary alloc] init] forKey:@"playerVars"];
    }
    NSString *html = [[NSBundle mainBundle] pathForResource:@"youtube" ofType:@"html"];
    NSString *htmlStr = [NSString stringWithContentsOfFile:html encoding:NSUTF8StringEncoding error:nil];
    NSError *jsonRenderingError = nil;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:playerParams
                                                       options:NSJSONWritingPrettyPrinted
                                                         error:&jsonRenderingError];
    NSString *playerVarsJsonString =
    [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    
    NSString *embedHTML = [NSString stringWithFormat:htmlStr, playerVarsJsonString];
        self.webView.userInteractionEnabled = YES;
        [self.webView loadHTMLString:embedHTML baseURL: self.originalURL];
    
    return YES;

}
复制代码
2.2暂停播放
/**
 pause play video
 **/
- (void)pauseVideo {

    if (self.webView.isLoading) {
        [self.webView stopLoading];
    }
    [self.webView evaluateJavaScript:@"player.pauseVideo();" completionHandler:nil];
    
}
复制代码
2.3停止播放
/**
 stop play video
 **/
- (void)stopVideo {

    if (self.webView.isLoading) {
        [self.webView stopLoading];
    }
    [self.webView evaluateJavaScript:@"player.stopVideo();" completionHandler:nil];
    [self closeInterfacePlayer];
}

复制代码
2.4跳转到指定时间播放
/**
 play video from seconds
 **/
- (void)seekToSecondsPlayVideo:(float)seconds allowSeekAhead:(BOOL)allowSeekAhead {

    NSString *command = [NSString stringWithFormat:@"player.seekTo(%@,%@);",[NSNumber numberWithFloat:seconds],allowSeekAhead ? @"true":@"false"];

    [self.webView evaluateJavaScript:command completionHandler:nil];
}
复制代码
2.5暂停之后再点击开始播放
/**
 start play video
 **/
- (void)startVideo {

    [self openInterfacePlayer];
    [self.webView evaluateJavaScript:@"player.playVideo();" completionHandler:nil];
}
复制代码
2.6获取当前播放时长
/*
 get video play time
 **/
- (void)currentTime:(void (^)(float, NSError *))complentionHandler {

    [self.webView evaluateJavaScript:@"player.getCurrentTime();" completionHandler:^(id returnValue, NSError * _Nullable error) {
        float currentTime = [returnValue floatValue];
        complentionHandler(currentTime,error);
    }];
}

复制代码

在外界只需要导入YouTuBePlayerView头文件,直接调用其中的方法即可:

最后附上一张效果图

在GitHub上有相关的源码,欢迎有需要的同胞前去下载,有问题请指出来,大家共同学习进步,谢谢,最后附上源码下载链接:

YouTube视频播放源码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值