You need to enable JavaScript to run this app.
文档中心
企业直播

企业直播

复制全文
下载 pdf
企业直播
将直播间 H5 页面嵌入移动端 Native App
复制全文
下载 pdf
将直播间 H5 页面嵌入移动端 Native App

您可以将企业直播直播间的 H5 页面嵌入到您的移动端 Native App 中,实现画中画、自动播放等常见功能。本文以 iOS 和 Android App 的 Demo 为例,介绍如何实现相关功能。

注意

若您通过集成 Web 观播 SDK 方式获取 H5 页面,请确保您的 Web 观播 SDK 版本不低于 2.1.20。

Demo 介绍

企业直播提供了开源示例项目 BDLWebDemo,用于演示如何将直播间的 H5 页面嵌入到您的移动端 Native App 中。Demo 项目中对 H5 页面做了良好适配,优化了观看体验,并提供了画中画、自动播放等拓展功能。
Demo 项目实现了以下功能。您可以按需修改 Demo 中的代码,实现自定义的业务逻辑。

  • 画中画(包含系统画中画和应用内画中画)
  • 自动播放
  • 配置全屏按钮点击行为
  • 自定义跳转逻辑

前提条件

通过以下任一方式获取直播间 H5 页面:

  • Web 观播 SDK:在集成 2.1.20 及以上版本的 Web 观播 SDK 时,创建单个直播或点播播放器实例。集成 Web 观播 SDK 的观看页即为直播间 H5 页面,观看页中仅展示一个播放器。有关如何集成 Web 观播 SDK,详见集成 Web 观播 SDK。
  • SaaS:此处以企业直播控制台为例,介绍如何获取 SaaS 的直播间 H5 页面。
    1. 在直播列表中,单击进入直播间。
    2. 单击观看地址,打开 SaaS 的直播间 H5 页面。
      Image

运行环境要求

  • iOS 11.0 及以上版本的真机或模拟器。

    说明

    • 如需在 Demo 或您的项目中实现系统画中画功能,确保您的 iOS 操作系统版本为 14.0 及以上。
    • 模拟器仅用于调试界面,无法保证音视频、画中画等功能的正常使用。为避免出现花屏、黑边等异常情况,建议在真机上进行测试和使用。
  • Xcode 16 及以上版本。
  • CocoaPods 16 及以上版本。

运行 Demo

完成以下步骤,运行 iOS App 的 Demo:

  1. 点击此处,下载 BDLWebDemo 包至本地,并解压。

  2. 打开终端窗口,cd 到 BDLWebDemo/iOS/Example 文件目录,并执行 pod install 命令安装第三方库。

    cd ./BDLWebDemo/iOS/Example
    pod install
    
  3. 在 Finder 中找到 BDLWebDemo.xcworkspace 文件,并双击打开 Xcode 项目。

  4. 在 BDLWebDemo > Signing & Capabilities > All > Signing (Debug) 区域,选择 Automatically manage signing 复选框并将 Team 和 Bundle Identifier 修改为您自有的 App 信息。
    Image

    说明

    • 如使用模拟器运行 Demo,可跳过该步骤。
    • 在 Xcode 中选择 Automatically manage signing 复选框可以简化代码签名过程、节省时间,并减少潜在错误。因此,建议您选择该复选框。如果不选择该复选框,则必须将 Provisioning Profile 和 Bundle Identifier 修改为您自有的 App 信息。
    • 在 Demo 中,默认勾选了 Background Modes 区域的 Audio, AirPlay, and Picture in Picture 复选框,因此运行 Demo 时无需手动勾选。但在您的项目中实现 Demo 的系统画中画功能时,需要手动勾选该复选框,具体步骤详见快速实现 Demo 功能。
    • 在 Demo 中,默认勾选了 Deployment Info 区域的 Landscape Left 和 Landscape Right 复选框,因此运行 Demo 时无需手动勾选。但在您的项目中实现横屏播放能力时,需手动勾选业务所需复选框。
  5. 点击键盘上的 ⌘+R,启动 Demo App。

  6. 打开 App,可以看到以下界面。
    Image
    您可以完成以下操作:

    • 点击进入直播间,进入企业直播官方 Demo 直播间。您也可以将预填的地址替换为直播间 H5 页面的地址,进入指定直播间。有关如何获取直播间 H5 页面,详见前提条件。
    • 点击右上方的扫码图标,扫码进入指定直播间。
      • 如需扫码进入 SaaS 的直播间 H5 页面,可完成以下步骤:
        1. 登录企业直播控制台。
        2. 在直播列表中,单击进入直播间。
        3. 将鼠标悬浮至移动端观看,扫描对应的二维码。
          Image
      • 如需扫码进入集成 Web 观播 SDK 的直播间 H5 页面,确保页面存在对应的二维码。有关如何获取直播间 H5 页面,详见前提条件。
    • 点击 Demo 配置,进入配置页。您可以按需完成以下配置,实现不同的 Demo 效果。
      Image

      说明

      以上勾选的为默认配置项。

功能实现

快速实现 Demo 功能

如无自定义需求,您可以通过复制 Demo 代码,快速在您的项目中实现 Demo 的功能。

完成以下步骤。

  1. 将 BDLWebDemo/iOS/BDLWeb 目录下的所有代码复制到您的项目中。

    BDLWebDemo
    └── iOS
        ├── BDLWeb // Web 功能封装代码。您可以将该目录下的所有代码复制到自己的项目中,快速实现 Demo 的功能。
        │   ├── BDLWeb
        │   │   ├── Category // 系统类的能力扩展。
        │   │   │   ├── UIDevice+BDL.h
        │   │   │   ├── UIDevice+BDL.m
        │   │   │   ├── UIImage+BDLAdditions.h
        │   │   │   ├── UIImage+BDLAdditions.m
        │   │   │   ├── UIWindow+BDLAdditions.h
        │   │   │   └── UIWindow+BDLAdditions.m
        │   │   ├── Config // 自定义配置。
        │   │   │   ├── BDLSettings.h
        │   │   │   └── BDLSettings.m
        │   │   ├── FloatingPlayer // 应用内画中画逻辑。
        │   │   │   ├── BDLFloatingPlayer.h
        │   │   │   ├── BDLFloatingPlayer.m
        │   │   │   ├── BDLFloatingWindow.h
        │   │   │   └── BDLFloatingWindow.m
        │   │   ├── PiP // 系统画中画逻辑。
        │   │   │   ├── BDLPiPHelper.h
        │   │   │   ├── BDLPiPHelper.m
        │   │   │   ├── BDLPiPVideoWriter.h
        │   │   │   └── BDLPiPVideoWriter.m
        │   │   ├── Utils // 辅助工具。
        │   │   │   ├── BDLDefines.h
        │   │   │   ├── BDLResponder.h
        │   │   │   ├── BDLResponder.m
        │   │   │   ├── BDLUtils.h
        │   │   │   └── BDLUtils.m
        │   │   └── WebView // 直播间容器。
        │   │       ├── BDLWebMessageModel.h
        │   │       ├── BDLWebMessageModel.m
        │   │       ├── BDLWebView.h
        │   │       ├── BDLWebView.m
        │   │       ├── BDLWebViewController.h
        │   │       └── BDLWebViewController.m
        │   └── BDLWeb.podspec
        └── Example // Demo UI 代码,包括配置页面、扫码页面,以及输入观看页地址的引导页面。
            └── BDLWebDemo
                ├── AppDelegate.h
                ├── AppDelegate.m
                ├── BDLCommonWebViewController.h // 打开商品详情页等 URL 的通用 WebView,可以替换为您 App 中的 WebView 或商品页面。
                ├── BDLCommonWebViewController.m
                ├── BDLCustomConfig.h
                ├── BDLCustomConfig.m
                ├── BDLScanViewController.h // Demo 的扫码页面。
                ├── BDLScanViewController.m
                ├── BDLSelectionCell.h
                ├── BDLSelectionCell.m
                ├── BDLSelectionView.h
                ├── BDLSelectionView.m
                ├── BDLSelectionViewController.h  // Demo 配置页面。
                ├── BDLSelectionViewController.m
                ├── NavigationController.h // Demo 的导航栏。
                ├── NavigationController.m
                ├── ViewController.h // Demo 输入观看页地址的引导页面。
                └── ViewController.m
            └── Podfile
    
  2. 参考 BDLWebDemo/iOS/Example/Podfile 文件中的配置,在您项目的 Podfile 文件中添加对 BDLWeb 的依赖。

    说明

    如果您的项目尚未使用过 CocoaPods,在项目的根目录下,执行 pod init && pod install,可以得到 Podfile 文件。

    # 您 App Target 的名字
    target 'BDLWebDemo' do
    ...
      # 将 ../BDLWeb 替换为指向您项目中 BDLWeb 文件夹的路径。
      pod 'BDLWeb', :path => '../BDLWeb'
    
    end
    
  3. 打开终端窗口,并 cd 到您的项目根目录。执行 pod install 命令安装依赖。

  4. 参考 BDLWebDemo/iOS/Example 目录下 ViewController.m 的代码,引用 BDLWebDemo/iOS/BDLWeb/BDLWeb/Config 目录下的 BDLSettings.h 和 BDLWebDemo/iOS/BDLWeb/BDLWeb/WebView 目录下的 BDLWebViewController.h 头文件,接入 BDLWeb。

  5. 参考 BDLWebDemo/iOS/Example 目录下 ViewController.m 文件中的以下代码,创建并管理直播间。

    // MARK: - 这些是需要接入的重点代码。
    
    - (void)onJoinButtonClicked:(UIButton *)sender {
        // 由于可能会在显示应用内画中画时,重新点击进入直播间按钮,所以需要判断 webViewController是否已经存在。
        if (!self.webViewController) {
            self.webViewController = [[BDLWebViewController alloc] init];
            self.webViewController.modalPresentationStyle = UIModalPresentationFullScreen;
            self.webViewController.delegate = self;
        }
        // 判断输入的观看页地址是否和当前直播间的观看页地址一致,如果不一致则重新加载新输入的观看页地址。
        if (![self.textField.text isEqualToString:self.currentURL]) {
            [self.webViewController loadURLStr:self.textField.text];
            self.currentURL = self.textField.text;
        }
        [self.navigationController pushViewController:self.webViewController animated:YES];
    }
    
    - (void)viewWillAppear:(BOOL)animated {
        [super viewWillAppear:animated];
        // 如果未开启应用内画中画,则将 webViewController 置空,从而销毁 webViewController,避免内存泄漏和直播间声音持续播放。
        if (!BDLSettings.sharedInstance.enableInAppPiP) {
            self.webViewController = nil;
            self.currentURL = nil;
        }
    }
    
    - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
        [coordinator animateAlongsideTransition:nil completion:^(id<UIViewControllerTransitionCoordinatorContext>  _Nonnull context) {
        }];
        UIInterfaceOrientation orientation = UIInterfaceOrientationUnknown;
        if (@available(iOS 13, *)) {
            orientation = self.view.window.windowScene.interfaceOrientation;
        } else {
            orientation = UIApplication.sharedApplication.statusBarOrientation;
        }
        // 将 webViewController 的 floatingPlayerOrientation 设置为当前的 orientation,以确保应用内画中画窗口的方向和当前屏幕方向一致。
        self.webViewController.floatingPlayerOrientation = orientation;
    }
    
    // MARK: - BDLWebViewControllerDelegate
    // 应用内画中画窗口的点击回调。
    - (void)webViewController:(BDLWebViewController *)controller floatingPlayerDidSingleTap:(BDLFloatingPlayer *)floatingPlayer {
        // 在 Demo 首页点击画中画窗口,则以 push 方式展示直播间页面。
        if (![self.navigationController.viewControllers containsObject:controller]) {
            [self.navigationController pushViewController:controller animated:YES];
            return;
        }
        // 在商品详情页点击画中画窗口,则弹出直播间页面上面的 ViewController,直到显示直播间页面。
        [self.navigationController popToViewController:controller animated:YES];
    }
    
    - (void)webViewController:(BDLWebViewController *)controller floatingPlayerDidClickClose:(BDLFloatingPlayer *)floatingPlayer {
    }
    // URL 点击回调。仅在新页面展示 URL 内容时,会触发该回调。
    - (void)webViewController:(BDLWebViewController *)controller onURLRequestClicked:(NSURLRequest *)urlRequest {
        NSLog(@"debug %s request %@ url %@", __func__, urlRequest, urlRequest.URL);
        // 此处以通用 WebView 为例。请替换为您 App 中的 WebView 或商品页面来展示 URL 内容。
        BDLCommonWebViewController *vc = [[BDLCommonWebViewController alloc] init];
        [vc.webView loadRequest:urlRequest];
        [self.navigationController pushViewController:vc animated:YES];
    }
    
    - (void)webViewControllerWillLeaveLiveRoom:(BDLWebViewController *)controller {
        // 离开直播间时,将 webViewController 置空,避免内存泄漏。
        self.webViewController = nil;
        self.currentURL = nil;
    }
    
  6. 为确保能够正常使用系统画中画功能,请完成以下操作:

    1. 在 Xcode 中,您的项目 App Target 下,单击 Signing & Capabilities 页签下的 + Capability,并双击添加 Background Modes。
      Image
    2. 在 Background Modes 区域,选择 Audio, AirPlay, and Picture in Picture 复选框。
      Image
  7. 如需修改 Demo 代码中的默认配置,可调用 BDLSettings 中的以下方法进行配置。

    • 系统画中画
      对 BDLSettings.sharedInstance.enableSystemPiP 进行赋值,开启或关闭系统画中画。默认值为 YES。
      • YES:开启。观众将当前 App 切换到后台后,且在设备的设置 > 通用 > 画中画中开启了自动开启画中画开关,即可通过画中画继续观看直播或点播视频。
      • NO:关闭。
    • 应用内画中画
      对 BDLSettings.sharedInstance.enableInAppPiP 进行赋值,开启或关闭应用内画中画。默认值为 YES。
      • YES:开启。观众在当前 App 内打开其他页面时,可通过画中画继续观看直播或点播视频。
      • NO:关闭。
    • 自动播放
      对 BDLSettings.sharedInstance.enableAutoPlay 进行赋值,设置观众进入直播间页面后,是否自动播放直播或点播视频。默认值为 YES。
      • YES:自动播放。
      • NO:不自动播放。
    • 配置全屏按钮点击行为
      对 BDLSettings.sharedInstance.fullscreenBtnType 进行赋值,设置全屏按钮的点击行为,即进入全屏模式后,是否会旋转屏幕。默认值为 BDLSettingsFullscreenBtnTypeRotate,即根据视频的宽高比判断是否会旋转屏幕。
      取值如下。
      typedef NS_ENUM(NSUInteger, BDLSettingsFullscreenBtnType) {
          /**
           * 不旋转屏幕,屏幕方向仍为竖屏。 
           */
          BDLSettingsFullscreenBtnTypeDoNotRotate,
          /**
           * 根据视频的宽高比判断是否会旋转屏幕。横屏视频(宽大于高)进入全屏模式后,会旋转为横屏,竖屏视频(宽小于高)进入全屏模式后,屏幕方向仍为竖屏。 
           */
          BDLSettingsFullscreenBtnTypeRotate,
          /**
           * 强制旋转为横屏。  
           */
          BDLSettingsFullscreenBtnTypeForceRotate,
      };
      

基础自定义配置

在完成快速实现 Demo 功能后,如需对 Demo 中的功能做一些基础的自定义配置,可以参考以下内容。

  • 修改应用内画中画窗口的宽度和高度
    在 BDLWebDemo/iOS/BDLWeb/BDLWeb/WebView/BDLWebViewController.m 的 getFloatingFrame 方法中,修改 size.height(高度)和 size.width(宽度)的取值。单位为 point。

    - (CGRect)getFloatingFrame {
        CGSize size = self.webView.videoSize;
        // 竖屏视频,即宽度小于高度。
        if (self.webView.isPortraitVideo) {
            CGFloat height = size.height;
            size.height = 180;
            size.width = size.width / height * 180;
        }
        else {
        // 横屏视频,即宽度大于高度。
            CGFloat width = size.width;
            size.width = 180;
            size.height = size.height / width * 180;
        }
        CGSize screenSize = [BDLUtils landscapeScreenSize];
        if (self.isPortrait) {
            screenSize = [BDLUtils portraitScreenSize];
        }
        return CGRectMake(screenSize.width - size.width - 20,
                          screenSize.height - size.height - 20,
                          size.width,
                          size.height);
    }
    
  • 在应用内画中画窗口中,添加控制 UI 或自定义控制 UI 的显示样式
    在 BDLWebDemo/iOS/BDLWeb/BDLWeb/FloatingPlayer/BDLFloatingPlayer.m 的 showWithFrame:closeButton: 方法中,添加应用内画中画窗口的控制 UI 或自定义控制 UI 的显示样式。
    以下示例代码修改了应用内画中画窗口关闭按钮的显示样式。

    - (BOOL)showWithFrame:(CGRect)frame closeButton:(BOOL)haveCloseButton {
        if ([self.floatingWindow isFloating]) {
            return NO;
        }
        
        self.haveCloseButton = haveCloseButton;
        self.floatingFrame = frame;
            
        @bdl_weakify(self);
        self.floatingWindow.allowClose = self.haveCloseButton;
        // 替换为自定义的关闭按钮图片。
        UIImage *closeImage = [BDLUtils imageNamed:@"close"]; 
        [self.floatingWindow showWithView:self.containerView
                               closeImage:closeImage
                           closeImageSize:CGSizeMake(30, 30)
                                initFrame:[self getInitFrame]
                               finalFrame:self.floatingFrame
                                 duration:0.3
                               willAppear:^(UIView * _Nonnull floatingView) {
            @bdl_strongify(self);
            if ([self.delegate respondsToSelector:@selector(floatingPlayerWillAppear:)]) {
                [self.delegate floatingPlayerWillAppear:self];
            }
        } didDisappear:^(UIView * _Nonnull floatingView) {
            @bdl_strongify(self);
            if ([self.delegate respondsToSelector:@selector(floatingPlayerDidDisappear:)]) {
                [self.delegate floatingPlayerDidDisappear:self];
            }
        } willClose:^(UIView * _Nonnull floatingView) {
            @bdl_strongify(self);
            if ([self.delegate respondsToSelector:@selector(floatingPlayerWillClose:)]) {
                [self.delegate floatingPlayerWillClose:self];
            }
        }];
        return YES;
    }
    
  • 自定义跳转逻辑
    在 Demo 中,观众在点击菜单内商品卡片、浮窗商品卡片、页头广告、页中广告、浮标广告、主播账号、聊天互动菜单内评论区中的 URL 或置顶评论中的 URL 时,会使用基础 WKWebView 打开 http 或 https 协议头的地址。如需自定义跳转逻辑,根据特定场景或需求,定制页面的跳转行为,可以将 BDLWebDemo/iOS/Example/ViewController.m 中 webViewController:onURLRequestClicked: 方法的逻辑替换为您自定义的跳转逻辑。

    - (void)webViewController:(BDLWebViewController *)controller onURLRequestClicked:(NSURLRequest *)urlRequest {
        NSLog(@"debug %s request %@ url %@", __func__, urlRequest, urlRequest.URL);
        BDLCommonWebViewController *vc = [[BDLCommonWebViewController alloc] init];
        [vc.webView loadRequest:urlRequest];
        [self.navigationController pushViewController:vc animated:YES];
    }
    

深度自定义开发

如果基础自定义配置无法满足您的需求,您需要在了解 Demo 功能实现的具体逻辑后,进行深度自定义开发。
本节介绍了 Demo 中核心能力的具体实现,帮助您理解核心能力的实现逻辑。

系统画中画

关键代码详见 BDLWebDemo/iOS/BDLWeb/BDLWeb/PiP 目录。其中,BDLPiPVideoWriter 实现了创建黑帧视频的逻辑,BDLPiPHelper 负责管理 AVPlayerController 并将其加入到当前直播间容器 (BDLWebViewController) 中。
关键方法如下所示:

  • BDLPiPHelper 中
    • setEnablePiPMode 设置是否开启系统画中画
    • updateVideoSize: 更新视频尺寸。当切换回放视频时,实际播放的视频尺寸可能发生变化,此时 BDLWebViewController 会调用该方法,更新黑帧视频尺寸。
    • preparePlayer 创建 AVPlayerController 并将其添加到当前直播间容器中
    • updatePlayerVCParentViewController 更新 AVPlayerController 的父视图,以便从系统画中画切换回 App 时能正常展现切换动画
    • playLocalVideoIfNeeded 创建并播放本地黑帧视频
    • playerViewControllerWillStartPictureInPicture: 通知 BDLWebViewController 画中画即将启动,并将 WebView 添加至系统画中画的 WindowScene 中
  • BDLPiPVideoWriter 中
    • videoWithSize:color:completion: 尝试获取对应尺寸的黑帧视频。如果不存在对应尺寸的黑帧视频,则调用 writeVideoWithSize:color:atPath:completion: 方法创建黑帧视频,并返回黑帧视频的路径
    • writeVideoWithSize:color:atPath:completion: 根据视频尺寸、颜色、路径创建黑帧视频,并返回黑帧视频的路径

展示和关闭系统画中画窗口的实现流程如下所示。

展示系统画中画窗口:

  1. 当 WebView 开始播放视频时,BDLWebViewController 会创建并初始化 BDLPiPHelper。
  2. BDLPiPHelper 创建黑帧视频并使用 AVPlayerController 以极慢的速度在屏幕上播放该黑帧视频,且将 AVPlayer 的 View 透明度设置为完全透明,这样,观众在观看视频时不会看到黑帧视频。
  3. 当 App 切换到后台时,AVPlayerController 会自动创建一个系统画中画的 WindowScene。
  4. BDLPiPHelper 将 WebView 嵌入画中画窗口,即添加 WebView 到系统画中画的 WindowScene 中,从而展示系统画中画窗口。

关闭系统画中画窗口:

  1. 当 App 切换到前台时,BDLPiPHelper 将重新播放黑帧视频,确保下次切换到后台时,画中画窗口可以正常展示。
  2. BDLPiPHelper 通知 BDLWebViewController 退出画中画模式,并将 WebView 添加回 BDLFloatingPlayer 从而将系统画中画窗口变更为应用内画中画窗口或添加回 BDLWebViewController 从而返回直播间页面。

应用内画中画

直播间(BDLWebViewController)中包含 BDLFloatingPlayer,而 BDLFloatingPlayer 中包含 BDLFloatingWindow。
关键方法如下所示:

  • BDLFloatingPlayer 中
    • updateWebView: 在退出系统画中画模式时,将 BDLWebView 添加到 BDLFloatingWindow 中
    • getNewFloatingWindow: 根据传入的旋转方向,创建 BDLFloatingWindow 实例
    • setUIOrientation: 设置 BDLFloatingPlayer 的 UI 方向。此方法将调用 getNewFloatingWindow: 重新创建新方向的 BDLFloatingWindow 实例
    • showWithFrame:closeButton: 展示应用内画中画窗口
    • close 关闭应用内画中画窗口
  • BDLFloatingWindow 中
    • floatingWnd 创建 UIWindow 的懒加载方法
    • showWithView:closeImage:closeImageSize:initFrame:finalFrame:duration:willAppear:didDisappear:willClose: 展示应用内画中画窗口
    • close 通知 BDLWebViewController 即将退出应用内画中画模式,并关闭应用内画中画窗口
    • onPanGesture: 实现应用内画中画窗口的拖拽功能

展示和关闭应用内画中画窗口的实现流程如下所示。

展示应用内画中画窗口:

  1. 当观众在当前 App 内打开其他页面(包含返回 Demo 首页)时,BDLWebViewController 会创建 BDLFloatingPlayer ,BDLFloatingPlayer 随即会创建 BDLFloatingWindow。
  2. BDLFloatingWindow 会创建 一个 UIWindow,并将该 UIWindow 添加到当前 App 的 keyWindow 中,从而展示应用内画中画窗口。

关闭应用内画中画窗口:

  1. 当观众点击画中画窗口的视频画面或关闭按钮时,或者当网页通知需要关闭画中画窗口时,返回直播间页面。
  2. BDLFloatingWindow 从 keyWindow 中移除 UIWindow。
  3. 销毁 BDLFloatingWindow。
  4. 销毁 BDLFloatingPlayer,从而关闭应用内画中画窗口。

关键代码详见 BDLWebDemo/iOS/BDLWeb/BDLWeb/FloatingPlayer 目录。

自动播放

可参考 BDLWebDemo/iOS/BDLWeb/BDLWeb/WebView 目录下的 BDLWebView.m 文件,关键代码如下所示。

if (BDLSettings.sharedInstance.enableAutoPlay) {
    // 如果开启自动播放功能,则不需要观众手动操作就可以播放直播和点播视频。
    config.mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeNone;
}
else {
    // 如果未开启自动播放功能,则直播和点播视频需要观众手动操作才能播放。
    config.mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeAll;
}

全屏按钮点击行为

当观众点击全屏按钮进入全屏模式时,调用 webView:didEnterFullScreen: 方法。

- (void)webView:(nonnull BDLWebView *)webView didEnterFullScreen:(nonnull BDLWebMessageModel *)model {
    BDLSettings *settings = BDLSettings.sharedInstance;
    // 如果当前屏幕方向为竖屏,且全屏按钮点击行为被设置为强制旋转为横屏,或根据视频的宽高比判断是否会旋转屏幕且视频的宽大于高。
    if (self.isPortrait
        && (settings.fullscreenBtnType == BDLSettingsFullscreenBtnTypeForceRotate
            || (settings.fullscreenBtnType == BDLSettingsFullscreenBtnTypeRotate
                && !self.webView.isPortraitVideo))) {
        // 旋转为横屏。
        [UIDevice BDL_switchNewOrientation:UIInterfaceOrientationLandscapeRight];
    }
    [self updateViewFullscreen:YES];
}

当观众点击全屏按钮退出全屏模式时,调用 webView:didExitFullScreen: 方法。

- (void)webView:(nonnull BDLWebView *)webView didExitFullScreen:(nonnull BDLWebMessageModel *)model {
     // 如果当前屏幕方向为横屏,则旋转为竖屏。
    if (!self.isPortrait) {
        [UIDevice BDL_switchNewOrientation:UIInterfaceOrientationPortrait];
    }
    [self updateViewFullscreen:NO];
}

您也可以通过 supportedInterfaceOrientations 方法定义支持的屏幕方向。

- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    // 如果播放器未创建,则屏幕方向仅支持竖屏。
    if (!self.webView.isPlayerCreated) {
        return UIInterfaceOrientationMaskPortrait;
    }
    BDLSettings *settings = BDLSettings.sharedInstance;
    // 如果全屏按钮点击行为被设置为强制旋转为横屏,或根据视频的宽高比判断是否会旋转屏幕且视频的宽大于高,则支持除倒置外的所有屏幕方向。
    if (settings.fullscreenBtnType == BDLSettingsFullscreenBtnTypeForceRotate
        || (settings.fullscreenBtnType == BDLSettingsFullscreenBtnTypeRotate
            && !self.webView.isPortraitVideo)) {
        return UIInterfaceOrientationMaskAllButUpsideDown;
    }
    // 否则,屏幕方向仅支持竖屏。
    return UIInterfaceOrientationMaskPortrait;
}

详见 BDLWebDemo/iOS/BDLWeb/BDLWeb/WebView 目录下的 BDLWebViewController.m 文件。

常见问题

Web 与移动端 Native App 之间如何通信?

企业直播 Web 与您的移动端 Native App(以下简称 Native)之间具备一套通信机制。Web 和 Native 之间会互相发送消息,从而实现本文介绍的功能。如果您希望在您的自有 Web 页面(包括通过 iframe 嵌入 WebView 的自有 Web 页面)和 Native 之间进行通信,从而实现相关功能,需了解 Web 和 Native 之间的通信机制,并在您的自有 Web 页面自行实现 Web 事件的接收与发送。

JsBridge 交互流程

JSBridge 是一道横跨 Native 和 Web 的桥梁,是双端进行通信的媒介。
企业直播在 window 上注入全局变量 window.ByteLiveJsBridge,包含以下 API:

  • nativeCallBack:Native 调用 window.ByteLiveJsBridge.nativeCallBack 向 Web 发送消息。
  • invokeNative:Web 调用该 API 向 Native 发送消息。

Native 监听的 Web 事件

const data = {
  eventKey:11000, // 创建播放器事件。
  info: {
     isPortrait: true, // 竖屏模式。
     isLive: true, // 直播中。
};

// 向 Native 发送消息。
function sendMessage(){
    if(isIos){
    // iOS 平台使用 window.webkit.messageHandlers.invokeNative.postMessage 发送消息。
        window.webkit.messageHandlers.invokeNative.postMessage(data);
    }else{
    // 其他平台使用 window.ByteLiveJsBridge.invokeNative 发送消息。
        window.ByteLiveJsBridge.invokeNative(data);
    }
}

事件

Key

含义

INIT_FINISH

10001

JsBridge 加载完成事件。

CREATE_PLAYER

11000

创建播放器事件。
触发该事件后,Native 可通过 isLive 参数获取直播间是否正在直播中以及 isPortrait 参数获取直播间是否为竖屏模式。

  • isLive 参数取值如下所示:
    • true:直播中。
    • false:非直播中。
  • isPortrait 参数取值如下所示:
    • true:竖屏模式。
    • false:横屏模式。

DESTROY_PLAYER

11001

销毁播放器事件。

OPEN_FULLSCREEN

11002

进入全屏模式事件。

EXIT_FULLSCREEN

11003

退出全屏模式事件。

LIVE_ROOM_STATE_CHANGE

11004

直播间状态变化事件。
触发该事件后,Native 可通过 status 参数获取直播间状态。
status 参数取值如下所示:

  • 1:直播中。
  • 2:预告。
  • 3:回放。
  • 4:已结束。

PLAYER_STATE_CHANGE

11005

播放器状态变化事件。
触发该事件后,Native 可通过 created 和 paused 参数获取播放器状态。

  • created 参数取值如下所示:
    • true:已创建。
    • false:已销毁。
  • paused 参数取值如下所示:
    • true:暂停或结束。
    • false:播放。

MEDIA_LOAD_FINISH

11006

视频资源加载完成事件。
触发该事件后,Native 可通过 videoWidth 和 videoHeight 参数获取视频的真实尺寸,并通过视频的宽高比,配置画中画窗口的宽度和高度。

CLOSE_MINI_WINDOW

11008

退出画中画模式事件。当播放器报错时,触发该事件,同时 Web 关闭画中画窗口并返回直播间页面。

OPEN_WAKE_LOCK

11009

页面常亮不息屏开启事件。当观众进入直播间时,触发该事件。

EXIT_WAKE_LOCK

110010

页面常亮不息屏关闭事件。当观众离开直播间时,触发该事件。

Native 向 Web 发送的事件

// 进入画中画模式事件。
window.ByteLiveJsBridge.nativeCallBack({
  eventKey: 21000   
})

事件

Key

含义

ENTER_MINI_WINDOW

21000

进入画中画模式事件。

EXIT_MINI_WINDOW

21001

退出画中画模式事件。

STOP_PLAY

21002

暂停播放事件。

START_PLAY

21003

恢复播放并退出画中画模式事件。

PLAY

21004

播放事件。

实现画中画和全屏功能的通信流程

此处以画中画和全屏功能为例,介绍实现对应功能时,Web 和 Native 之间的通信流程。

  • 画中画
    Image
    1. 观众访问观看页,Native 监听到 Web 的 INIT_FINISH 事件,感知 JSBridge 已加载完成。
    2. Native 监听到 Web 的 CREATE_PLAYER 事件,感知播放器已创建完成、直播间是否正在直播中以及是否为竖屏模式。
    3. 观众离开观看页,Native 需自行实现进入画中画模式并向 Web 发送 ENTER_MINI_WINDOW 事件。
    4. Web 监听到 Native 的 ENTER_MINI_WINDOW 事件后,将播放器全屏显示在画中画小窗中。
    5. 在以下场景下,Native 需自行实现退出画中画模式并向 Web 发送 EXIT_MINI_WINDOW 事件。Web 监听到 Native 的 EXIT_MINI_WINDOW 事件后,退出播放器全屏并恢复至观看页。
      • 观众通过点击画中画小窗等方式返回观看页。
      • 直播间状态发生变化或观众切换直播频道等,Native 监听到 Web 的 DESTROY_PLAYER 事件,感知播放器已销毁。
    6. (可选)Native 可以按需向 Web 发送事件,从而播放或暂停播放直播或点播内容:
      • 在 WebView 暂停播放时,Native 向 Web 发送 PLAY 事件。Web 监听到该事件后即可播放直播或点播内容。
      • 在 WebView 播放期间,Native 向 Web 发送 STOP_PLAY 事件。Web 监听到该事件后即可暂停播放直播或点播内容。
  • 全屏
    Image
    1. 观众进入全屏模式,Native 监听到 Web 的 OPEN_FULLSCREEN 事件,感知观众已进入全屏模式,并判断是否会旋转为横屏。
    2. 观众退出全屏模式,Native 监听到 Web 的 EXIT_FULLSCREEN 事件,感知观众已退出全屏模式,并判断是否会恢复成竖屏。
最近更新时间:2026.10.26 19:23:57
这个页面对您有帮助吗?
有用
有用
无用
无用