You need to enable JavaScript to run this app.
导航
进阶功能
最近更新时间:2024.12.12 21:20:40首次发布时间:2024.02.21 18:10:12

本文介绍 iOS 观播 SDK 进阶功能的接入方法。您可以根据实际业务需求,按需实现复杂功能。

前提条件

功能列表

本文介绍以下功能的接入方法。

自定义登录

如果您需要观众先登录您的 App 再观看直播或参与评论、互动等操作,可以选择自定义登录方式,观众可以使用在您 App 中的身份信息进入直播间。
您可以按需选择观众在您 App 的登录时机。

  • 观众先完成登录,再进入直播间。
    Image

    1. 观众登录 App 并进入直播间后,您需通过调用 GetSDKTokenAPI 接口获取 Mode=2 时的授权 Token。
    2. 获取 Token 后,调用 SDK 的 joinLiveRoomWithActivity:success:failure: 方法进入直播间。

    示例代码如下所示。

    - (void)joinLiveRoom {    
        BDLActivity *activity = [[BDLActivity alloc] init];
        activity.activityId = @(167808997736****); // 直播间的活动 ID。
        activity.token = @"ak3T%2FdaGJDL5zSFD7%2F1GPGP****"; // Mode=2 时的授权 Token。
        activity.isPortrait = YES; // 竖屏直播间。
        activity.authMode = BDLActivityAuthModeCustom; // 自定义模式。
        [[BDLLiveEngine sharedInstance] joinLiveRoomWithActivity:activity success:^{
            // 进入直播间成功
        } failure:^(NSError * _Nonnull error) {
            // 进入直播间失败
        }];
    }
    
  • 观众先进入直播间观看直播、查看评论等,在参与评论、互动等操作时触发登录流程,将鉴权模式从公开模式切换为自定义模式。

    注意

    如果 setNickname:complete: 方法的 nickname 参数值非空,则不会触发 BDLLoginProvider 的任何方法。

    Image

    1. 观众先以公开模式进入直播间。

    2. 您需自行实现获取公开模式 Token 的方法,通过调用 GetSDKTokenAPI 接口请求 Mode=1 时的授权 Token。

    3. 设置 BDLLiveEngineloginProvider,即自定义登录直播间代理。
      示例代码如下所示。

      ...
      [[BDLLiveEngine sharedInstance] setLoginProvider:self];
      ...
      
    4. 调用 SDK 的 joinLiveRoomWithActivity:success:failure: 方法进入直播间。

    5. 在观众进行以下需要用户信息的操作时,会触发 App 的自定义登录流程:

      • 点击聊天互动或私聊互动菜单的评论输入框
      • 点赞评论
      • 打赏礼物
      • 点击直播预约按钮
      • 答题
      • 投票
      • 抽奖
      • 实名问卷
      • 观众连麦
      • 分享二维码、链接或邀请海报(仅在直播分享开启强制登录时会触发自定义登录流程)
    6. SDK 调用 loginWithActivity:completion: 方法,允许观众通过您的 App 登录直播间。您需要自行实现获取自定义模式 Token 的方法,并在观众完成自定义登录后,通过调用 GetSDKTokenAPI 接口请求 Mode=2 时的授权 Token。在成功获取 Token 后,您需调用 completion 方法将 Token 传入 SDK。
      示例代码如下所示。

      - (void)loginWithActivity:(BDLActivity *)activity completion:(void (^)(NSString * _Nullable token))completion {
          // 请将 getToken: 方法替换为您用来获取授权 Token 的方法。
          [self getToken:^(NSString *token) {
              completion(token);
          }];
      }
      
    7. SDK 通过 Token 向企业直播请求观众信息。

    8. 企业直播验证 Token 合法后,将观众信息传入 SDK。如果 Token 验证失败或为空,则将报错信息传入 SDK。

    9. SDK 调用 loginComplete:error: 方法通知 App 自定义登录流程是否成功。
      示例代码如下所示。

      - (void)loginComplete:(BDLActivity *)activity error:(NSError *)error {
          if (!error) {
              NSLog(@"自定义登录成功");
          }
          else {
              NSLog(@"自定义登录失败 %@", error.localizedDescription);
          }
      }
      
    10. (可选)如果在观众登录过程中关闭了直播间页面,SDK 会触发 cancelLoginWithActivity: 回调,您可按需取消自定义登录流程。
      示例代码如下所示。

      - (void)cancelLoginWithActivity:(BDLActivity *)activity {
      // 触发 cancelLoginWithActivity: 回调后,按需取消自定义登录流程
          NSLog(@"登录过程中关闭了直播间页面,此时 App 可按需取消登录流程");
      }
      

自定义跳转逻辑

观众在点击菜单内商品卡片、页头广告、页中广告、浮标广告、浮窗商品卡片、主播账号、聊天互动菜单内评论区中的 URL 或置顶评论中的 URL 时,SDK 会执行后续默认的跳转行为。您可以通过拦截后续 SDK 的默认跳转行为,在观众完成点击后,实现自定义跳转逻辑,即 SDK 不会执行后续默认的跳转行为,从而能够根据特定场景或需求,定制页面的跳转行为,提升用户体验。

说明

有关如何在企业直播控制台配置商品卡片、页头广告、页中广告、浮标广告、主播账号、聊天互动菜单、置顶评论,详见商品卡片广告位设置关联主播账号聊天互动

您可以在 configLivePullViewController: 中添加相关代码,获取点击的 URL 等信息并自定义跳转逻辑。

- (void)configLivePullViewController:(BDLLivePullViewController *)livePullVC {
}

菜单内商品卡片

Image
观众在点击菜单内的商品卡片后,触发 cardViewTappedBlock 回调,并向 App 传入商品卡片的跳转链接以及是否浮层展示商品详情页。
示例代码如下所示。

livePullVC.config.customShoppingCardController = ^(BDLLivePullViewController * _Nonnull viewController, BDLShoppingCardController * _Nonnull shoppingCardController) {
    shoppingCardController.customizeShoppingCardView = ^__kindof BDLBaseView * _Nullable(BDLShoppingCardController * _Nonnull controller, BDLShoppingCardView * _Nonnull shoppingCardView) {
        shoppingCardView.cardViewTappedBlock = ^(NSString * _Nullable urlStr, BOOL enableFloating) {
        // 触发 cardViewTappedBlock 回调后,执行菜单内商品卡片的自定义跳转逻辑。
            NSLog(@"%@ %d", urlStr, enableFloating);
        };
        return shoppingCardView;
    };
};

页头广告

Image
观众在点击页头广告后,触发 livePullViewController:didClickHeaderAd:floatingEnable: 回调,并向 App 传入页头广告跳转链接以及是否浮层展示广告页面。
示例代码如下所示。

- (void)livePullViewController:(BDLLivePullViewController *)livePullVC didClickHeaderAd:(NSString *)url floatingEnable:(BOOL)floatingEnable {
// 触发 livePullViewController:didClickHeaderAd:floatingEnable: 回调后,执行页头广告的自定义跳转逻辑。
    NSLog(@"%@ %d", url, floatingEnable);
}

页中广告

Image
观众在点击页中广告后,触发 viewTappedBlock 回调,并向 App 传入当前的 BDLPageAdView 实例、广告相关信息以及是否浮层展示广告页面。
示例代码如下所示。

livePullVC.config.customizePageAdView = ^__kindof BDLBaseView * _Nullable(BDLLivePullViewController *viewController, BDLPageAdView * _Nonnull view) {
    view.viewTappedBlock = ^(BDLPageAdView * _Nonnull view, BDLAdvertisementModel * _Nonnull ad, BOOL isFloatingEnable) {
    // 触发 viewTappedBlock 回调后,执行页中广告的自定义跳转逻辑。
        NSLog(@"%@ %d", ad.advertisementRedirectUrl, isFloatingEnable);
    };
    return view;
};

浮标广告或浮窗商品卡片

Image

观众在点击浮标广告或浮窗商品卡片后,触发 openUrlBlock 回调,并向 App 传入浮窗控制器、广告或商品卡片的跳转链接以及是否浮层展示广告页面或商品详情页。
示例代码如下所示。

livePullVC.config.customFloatingController = ^(BDLLivePullViewController * _Nonnull viewController, BDLFloatingController * _Nonnull floatingController) {
    
    floatingController.openUrlBlock = ^(BDLFloatingController * _Nonnull floatingController, NSURL * _Nonnull url, BOOL isFloatingEnable) {
    // 触发 openUrlBlock 回调后,执行浮标广告或浮窗商品卡片的自定义跳转逻辑。
        NSLog(@"url: %@ isFloatingEnable:%d", url, isFloatingEnable);
    };
};

主播账号

Image
观众在点击主播账号头像或名称后,触发 viewTappedBlock 回调,并向 App 传入主播账号的跳转链接。
示例代码如下所示。

livePullVC.config.customizeAccountView = ^__kindof BDLBaseView * _Nullable(BDLLivePullViewController *viewController, BDLBusinessAccountView * _Nonnull view) {
    view.viewTappedBlock = ^(NSString * _Nullable urlStr) {
     // 触发 viewTappedBlock 回调后,执行主播账号的自定义跳转逻辑。
        NSLog(@"%@", urlStr);
    };
    return view;
};

聊天互动菜单内评论区中的 URL

Image
默认情况下,仅主持人评论中的 URL 为可点击状态。您可以通过以下方法,将观众评论中的 URL 设置为可点击状态。

[[[BDLLiveEngine sharedInstance] liveRoomConfiguration] commentViewConfig].enableAudienceURLTap = YES;

观众在聊天互动菜单内点击评论区中的 URL (非置顶评论 URL)后,触发 urlClickBlock 回调,并向 App 传入当前的 BDLCommentBaseView 实例、评论相关信息以及评论 URL。
示例代码如下所示。

void (^customizeCommentView)(BDLCommentView *view) = ^(BDLCommentView *view) {
    view.urlClickBlock = ^(__kindof BDLCommentBaseView * _Nonnull commentView, BDLCommentModel * _Nonnull comment, NSURL * _Nonnull url) {
       // 触发 urlClickBlock 回调后,执行评论区中 URL 的自定义跳转逻辑。   
            NSLog(@"%@ %@", url, comment);
    };
};

// 在竖屏直播间的聊天互动菜单评论区调用 urlClickBlock。
livePullVC.config.customizeCommentView = ^(BDLLivePullViewController * _Nonnull viewController, BDLCommentView * _Nonnull view) {
    customizeCommentView(view);
};

// 在横屏直播间的聊天互动菜单评论区调用 urlClickBlock。
// 请与其他 customizeMenuBarView 方法合并使用,以免互相覆盖配置。
livePullVC.config.customizeMenuBarView = ^(BDLLivePullViewController * _Nonnull viewController, BDLMenuBarView * _Nonnull view) {
    view.customizeCommentView = ^(BDLMenuBarView * _Nonnull view, BDLCommentView * _Nonnull commentView) {
        customizeCommentView(commentView);
    };
};

置顶评论中的 URL

Image
观众点击置顶评论后,会弹出置顶内容弹窗,点击弹窗中的评论 URL 后,会触发 urlClickBlock 回调,并向 App 传入评论 URL。
示例代码如下所示。

livePullVC.config.customizeAlertController = ^__kindof UIViewController * _Nonnull(BDLLivePullViewController * _Nonnull viewController, BDLAlertController * _Nonnull controller) {
    __weak typeof(self) weakSelf = self;
    __weak BDLAlertController * weakController = controller;
    controller.urlClickBlock = ^(NSURL * _Nonnull url) {
        [weakController dismissAlertControllerAnimated:YES completion:^{
        // 触发 urlClickBlock 回调后,执行置顶评论中 URL 的自定义跳转逻辑。          
            NSLog(@"%@", url);
        }];
    };
    return controller;
};

组件化接入连麦模块

如果您选择组件化接入直播间,可通过该方式接入连麦模块。
以下示例代码演示了如何接入连麦模块,包括设置在连麦画面 view 中显示当前连麦观众的画面、设置相关回调、断开连麦等。

/// 接入连麦模块。
- (void)setupAudienceLink {
    // 初始化连麦 controller。
    self.audienceLinkController = [[BDLAudienceLinkController alloc] init];
    // 设置弹窗显示的父 view。
    self.audienceLinkController.popupSuperView = self.view;
    // 设置在连麦画面 view 中显示当前连麦观众的画面。
    self.audienceLinkController.showSelfVideoInRemoteView = YES;
    
    __weak typeof(self) weakSelf = self;
    // 设置连麦入口 view 显示回调。
    // 此处以显示在 self.view 左上为例。
    self.audienceLinkController.showEntranceViewBlock = ^(BDLAudienceLinkController * _Nonnull audienceLinkController, BDLAudienceLinkEntranceView * _Nonnull view, BOOL isFromEnableChange) {
        weakSelf.audienceLinkEntranceView = view;
        [weakSelf.view addSubview:view];
        // 是否由企业直播服务端返回数据变化触发。此处以展示连麦入口显示动画为例。如不需要展示动画,可直接设置 view.frame。
        if (isFromEnableChange) {
            view.frame = CGRectMake(-64, 100, 64, 64);
            [UIView animateWithDuration:0.3 animations:^{
                view.frame = CGRectMake(10, 100, 64, 64);
            }];
        }
    };
    // 设置连麦入口 view 隐藏回调。
    self.audienceLinkController.hideEntranceViewBlock = ^(BDLAudienceLinkController * _Nonnull audienceLinkController, BDLAudienceLinkEntranceView * _Nonnull view) {
        weakSelf.audienceLinkEntranceView = nil;
        [view removeFromSuperview];
    };
    // 设置连麦本地画面预览 view 显示回调。
    self.audienceLinkController.showPreviewViewBlock = ^(BDLAudienceLinkController * _Nonnull audienceLinkController, BDLAudienceLinkPreviewView * _Nonnull previewView, double aspectRatio) {
        weakSelf.audienceLinkPreviewView = previewView;
        [weakSelf.view addSubview:previewView];
        [previewView mas_remakeConstraints:^(MASConstraintMaker *make) {
            make.left.equalTo(weakSelf.view).offset(10);
            make.width.equalTo(@300);
            make.height.equalTo(previewView.mas_width).dividedBy(aspectRatio ?: 1);
            make.top.equalTo(weakSelf.view.mas_safeAreaLayoutGuideTop).offset(100);
        }];
    };
    // 设置连麦本地画面预览 view 隐藏回调。
    self.audienceLinkController.hidePreviewViewBlock = ^(BDLAudienceLinkController * _Nonnull audienceLinkController, BDLAudienceLinkPreviewView * _Nonnull previewView) {
        weakSelf.audienceLinkPreviewView = previewView;
        [previewView removeFromSuperview];
    };
    // 设置连麦画面容器 view 显示回调。
    self.audienceLinkController.showRemoteContainerViewBlock = ^(BDLAudienceLinkController * _Nonnull audienceLinkController, BDLAudienceLinkRemoteContainerView * _Nonnull remoteContainerView) {
        weakSelf.audienceLinkRemoteContainerView = remoteContainerView;
        [weakSelf.view addSubview:remoteContainerView];
        [remoteContainerView mas_remakeConstraints:^(MASConstraintMaker *make) {
            make.left.right.equalTo(weakSelf.view);
            make.height.equalTo(remoteContainerView.mas_width).multipliedBy(9/16.0);
            make.top.equalTo(weakSelf.view.mas_safeAreaLayoutGuideTop).offset(250);
        }];
        // 如果您接入了播放器组件,需要隐藏直播播放器 view 并停止播放。
        weakSelf.playerView.hidden = YES;
        weakSelf.playerView.basePlayerView.forbidPlay = YES;
        //(可选)设置单个连麦参与者画面的点击回调。
        remoteContainerView.onUserVideoClickBlock = ^(BDLAudienceLinkRemoteContainerView * _Nonnull containerView, BDLAudienceLinkLayoutUser * _Nonnull user, BOOL isSelf) {
            NSLog(@"点击了用户画面 \n user:【%p】isSelf:【%d】", user, isSelf);
        };
    };
    // 设置连麦画面容器 view 隐藏回调。
    self.audienceLinkController.hideRemoteContainerViewBlock = ^(BDLAudienceLinkController * _Nonnull audienceLinkController, BDLAudienceLinkRemoteContainerView * _Nonnull remoteContainerView) {
        weakSelf.playerView.basePlayerView.forbidPlay = NO;
        weakSelf.playerView.hidden = NO;
        weakSelf.audienceLinkRemoteContainerView = nil;
        [remoteContainerView removeFromSuperview];
    };
}

/// 需要断开连麦时,可以调用以下方法。
- (void)onCancelAudienceClick {
    [self.audienceLinkController cancelAudienceLink:^{
        NSLog(@"断开连麦完成");
    }];
}

相关方法、回调等,详见 BDLAudienceLinkController。您也可以通过 Player Demo 体验如何接入连麦组件。详见 iOS

UI 定制

您可以通过以下两种方式自定义观看页的 UI 显示。

说明

  • SDK 的 UI 定制优先级高于企业直播控制台和服务端 OpenAPI 的自定义配置,例如同时通过 SDK 的 thumbUpButtonImage 方法和控制台自定义了直播间点赞按钮图片,观看页会展示 thumbUpButtonImage 方法自定义的按钮图片。
  • 建议在成功进入直播间后、显示直播间页面前配置 UI 定制内容。

自定义方式说明

通过前缀为 customize 的属性自定义

您可以在 joinLiveRoomWithActivity:success:failure:success 回调中调用 getLivePullViewController 方法,获取 BDLLivePullViewController 实例。然后,通过 BDLLivePullViewControllerconfig 属性,对 BDLLivePullViewController 进行自定义配置。BDLLivePullViewControllerConfig 中提供大量前缀为 customize 的 Block。您可以根据 Block 的参数获取对应的 view 并自定义 view 的属性。

  • 对于有返回值的 Block,在自定义属性后,您可以将 view 返回给 SDK,也可以直接替换成自己的实现,将您自己实现的实例返回给 SDK。
  • 对于没有返回值的 Block,则只支持自定义属性。

customizeAccountView 属性为例:

@property (nonatomic, copy, nullable) __kindof BDLBaseView * _Nullable (^customizeAccountView)(BDLLivePullViewController *viewController, BDLBusinessAccountView *view);

customizeAccountView 属性可用来自定义主播账号功能的 UI。例如,您可以通过该属性获取到 BDLBusinessAccountView,然后设置 avatarImageView 来自定义主播账号头像除圆角、图片、frame 外的所有属性。

说明

  • 如需隐藏 view,返回 nil 给 SDK 即可,或者在企业直播控制台中设置关闭该 view 对应的功能。不建议通过设置 hidden 属性隐藏 view,因为这种方式可能会被企业直播控制台中的设置覆盖。
  • 由于 view 内部使用自动布局,所以除特殊说明外,不建议自定义 view 的位置属性。如需自定义 view 的位置,建议您自行实现 view,然后替换默认的实现。
  • 不支持将 UI 控件自定义为常显示,即在企业直播控制台中关闭 UI 控件对应的功能,SDK 中却配置为显示。
  • 自定义文案时,除特殊说明外,均支持自定义多语言。不同语言的文案之间使用|分隔,SDK 会选取对应语言的内容,格式如下:
    简体中文|English|日本語|繁體中文

通过后缀为 Config 的属性自定义

SDK 在 liveRoomConfiguration 中提供大量后缀为 Config 的属性。您可以参考以下代码,获取对应的 Config 接口进行自定义:

[[BDLLiveEngine sharedInstance] liveRoomConfiguration].xxxxConfig

具体实现

本文以直播带货场景中高频使用的 UI 定制功能点为例。更多 UI 定制相关方法与回调,详见 API 详情回调

视频画面填充模式

竖屏直播间默认视频会保持原有宽高比例填充播放器,视频的宽高会填满播放器的宽高。如果视频宽高比与播放器宽高比不同,会有部分视频内容被裁剪掉。您可以自定义视频画面的填充模式。
以下示例代码将竖屏直播间的视频内容完全填充播放器,但视频宽高比可能发生变化。

Image

BDLLiveRoomConfiguration *config = [[BDLLiveEngine sharedInstance] liveRoomConfiguration];
config.playerConfig.portrait.scalingMode = BDLPlayerScalingModeFill;

完整直播间的关闭按钮

竖屏完整直播间的关闭按钮默认显示为 x。您可以自定义关闭按钮的显示样式。
以下示例代码将关闭按钮自定义为文件名为 back 的图片。

Image

livePullVC.config.customizeCloseButton = ^__kindof UIButton * _Nullable(BDLLivePullViewController * _Nonnull viewController, UIButton * _Nonnull button) {
    // 自定义圆角半径和边框。
    button.clipsToBounds = YES;
    button.layer.cornerRadius = 3;
    button.layer.borderWidth = 2;
    button.layer.borderColor = UIColor.grayColor.CGColor;
    // 自定义按钮的图标为文件名 back 的图片。
    [button setImage:[UIImage imageNamed:@"back"] forState:UIControlStateNormal];
    return button;
};

互动工具浮窗

互动工具浮窗,即包含抽奖、答题、投票、问卷和公告图标的浮窗。竖屏直播间默认展示在直播间左上方。您可以自定义互动工具浮窗的默认位置。
以下示例代码将互动工具浮窗的默认位置向下移动了 50 pt。

Image

// 自定义完整直播间中的浮窗。
livePullVC.config.customFloatingController = ^(BDLLivePullViewController * _Nonnull viewController, BDLFloatingController * _Nonnull floatingController) {
    // 自定义互动工具浮窗的默认位置。该 View 涉及拖动,因此通过设置 view.frame 调整其位置,而非使用自动布局。
    floatingController.customizeInteractiveToolContainerView = ^__kindof UIStackView * _Nullable(BDLFloatingController * _Nonnull floatingController, UIStackView * _Nonnull view) {
        CGRect frame = view.frame;
        // 互动工具浮窗的默认位置下移 50 pt。        
        frame.origin.y += 50;
        view.frame = frame;
        return view;
    };
};

商品卡片菜单高度

商品卡片菜单的默认高度为屏幕高度的 0.73 倍。您可以自定义菜单的高度。
以下示例代码将商品卡片菜单的高度设置为屏幕高度的 1/2。

Image

livePullVC.config.customShoppingCardController = ^(BDLLivePullViewController * _Nonnull viewController, BDLShoppingCardController * _Nonnull shoppingCardController) {
    shoppingCardController.customizeShoppingCardView = ^__kindof BDLBaseView * _Nullable(BDLShoppingCardController * _Nonnull controller, BDLShoppingCardView * _Nonnull shoppingCardView) {
        [shoppingCardView mas_updateConstraints:^(MASConstraintMaker *make) {
            make.height.mas_equalTo(CGRectGetHeight(UIScreen.mainScreen.bounds) * 1 / 2);
        }];
        return shoppingCardView;
    };
};