白板 2.17.0-alpha.30

白板 2.17.0-alpha.30

xuyunshi 维护。



白板 2.17.0-alpha.30

  • 作者:
  • leavesster

白板

此项目是White-SDK-IOS的开源版本。为了更好地显示源代码结构,'白板'将项目分成了几个“子pods”,这更有利于开发者查看项目的源代码级别。为此,您需要修改引用关系。

中文

bridge-check iOS13+Test

文档

官方文档 —— iOS部分

参考

  • CocoaPods

pod 'Whiteboard'
  • Swift Package Manager

 dependencies: [
    .package(url: "https://github.com/netless-io/Whiteboard-iOS.git", .upToNextMajor(from: "2.15.0"))
]

示例

  • 开始示例
cd Example
pod install

转到示例文件夹并打开 Example.xcworkspace 项目文件。

同时,在 WhiteUtils.m 中根据代码注释填入 WhiteSDKTokenWhiteAppIdentifier

/* FIXME: sdkToken
 Please register at https://console.netless.link and get the SDK token
This SDK token should not be stored on the client side, and all requests involving SDK tokens (all requests in the current class) should be placed on the server to avoid unnecessary risks caused by leaks.
 */
#define WhiteSDKToken <#@sdk Token#>
#define WhiteAppIdentifier <#@App identifier#>

调试特定房间

如果您需要为调试进入特定的房间,请转到 Whiteboard-Prefix.pch 文件,取消注释 WhiteRoomUUIDWhiteRoomToken 并填写指定内容。

// If you add WhiteRoomUUID and WhiteRoomToken, then, you can define WhiteSDKToken as @""
//#define WhiteSDKToken <#@sdk Token#>
//#define WhiteAppIdentifier <#@App identifier#>

// If you need access to a specific room, uncomment the following two lines and fill in the corresponding UUID and RoomToken
//#define WhiteRoomUUID <#Room UUID#>
//#define WhiteRoomToken <#Room Token#>

此时,如果您添加或重播一个房间,您将进入该房间。

单元测试

单元测试需要测试一些特殊行为,因此对应房间需要以下操作:

  1. 插入图像接口(从单元测试启动的房间,图像阻止已启用)
  2. 发送特定的自定义事件(定义在单元测试代码中)
  3. 发送大量自定义事件

设备需求

运行设备:iOS 10 + 开发环境:Xcode 10+

项目结构

SDK由多个子pod组成,依赖结构如图所示

Project dependency structure

参数配置类:用于描述和存储API参数、返回值、状态和其他配置项的类。主要用于与webview交互。

  1. 对象:对象的主要功能是通过YYModel进行JSON转换。包含以下部分
    1. Object基类,所有在SDK配置类中使用的参数的基类。
    2. RoomPlayer API中的一些参数配置类。
  2. 基类:包括SDKDisplayer和相关的一些类,主要如下
    1. WhiteSDK及其初始化参数类。
    2. WhiteSDK设置的通用回调whiteCommonCallbacks
    3. 实现与RoomPlayer相同父类Displayer的类。
    4. 用于Displayer API的一些参数配置类。
    5. Displayer是一个用于描述当前RoomState的类。它是RoomStatePlayerState的基类。
  3. 实时房间
    1. Room类及其相关事件回调类。
    2. WhiteSDK+Room,使用SDK API创建Room
    3. 独特的Room参数配置类。
    4. 描述与Room相关的类。
  4. 可以回放房间的内容。
    1. Player类及其相关事件回调类。
    2. WhiteSDK+Player,使用SDK API创建Player
    3. Player特定的参数配置类。
    4. 描述与Player状态相关的类。
  5. NativePlayer:在iOS端播放音频和视频,并与白板播放状态同步。
    1. WhiteCombinePlayer类及其相关类。
  6. Converter:将请求转换为包装类。
  • 动态和静态转换的收费基于QPS(每日并发量)。客户端无法控制并发量,因此不建议在生产环境中使用。请参考文档获取详细信息。

原生音频和视频

SDK现在支持在原生端使用CombinePlayer播放音频和视频,SDK将负责将音频和视频的状态与白板播放同步。

具体代码示例,请查看WhitePlayerViewController

音频和视频的m3u8格式,可能需要在调用combinePlayerEndBuffering后的seek调用来播放。(否则仍可能从原始位置开始播放)

#import <Whiteboard/Whiteboard.h>

@implementation WhitePlayerViewController
- (void)initPlayer
{

  // Create WhitePlayer logic

  // 1. Configure SDK initialization parameters, more parameters, see the WhitesdkConfiguration header file
  WhiteSdkConfiguration *config = [[WhiteSdkConfiguration alloc] initWithApp:[WhiteUtils appIdentifier]];
  // 2. Initialize the SDK
  self.sdk = [[WhiteSDK alloc] initWithWhiteBoardView:self.boardView config:config commonCallbackDelegate:self.commonDelegate];
  // 3. WhitePlayerConfig, Room UUID and RoomToken are required. For more parameters, see the WhitePlayerConfig.h header file
  WhitePlayerConfig *playerConfig = [[WhitePlayerConfig alloc] initWithRoom:self.roomUuid roomToken:self.roomToken];


  // This is an example of how to do this
  self.combinePlayer = [[WhiteCombinePlayer alloc] initWithMediaUrl:[NSURL URLWithString:@"https://netless-media.oss-cn-hangzhou.aliyuncs.com/c447a98ece45696f09c7fc88f649c082_3002a61acef14e4aa1b0154f734a991d.m3u8"]];

  // Display the AVPlayer screen
  [self.videoView setAVPlayer:self.combinePlayer.nativePlayer];

  // Configure the Delegate
  self.combinePlayer.delegate = self;

   
  [self.sdk createReplayerWithConfig:playerConfig callbacks:self.eventDelegate completionHandler:^(BOOL success, WhitePlayer * _Nonnull player, NSError * _Nonnull error) {
​    if (self.playBlock) {
​      self.playBlock(player, error);
​    } else if (error) {
​      NSLog(@"Failed to create playback room error:%@", [error localizedDescription]);
​    } else {
​      self.player = player;
​      [self.player addHighFrequencyEventListener:@"a" fireInterval:1000];

​      //Config WhitePlayer
​      self.combinePlayer.whitePlayer = player;
​      //WhitePlayer  need to manually seek to 0 to trigger the buffering behavior
​      [player seekToScheduleTime:0];
​    }
  }];
}

#pragma mark - WhitePlayerEventDelegate

- (void)phaseChanged:(WhitePlayerPhase)phase
{
  NSLog(@"player %s %ld", __FUNCTION__, (long)phase);
  // Attention! This must be done for the WhiteCombinePlayer to properly synchronize the state
  [self.combinePlayer updateWhitePlayerPhase:phase];
}

// Other callback methods...

#pragma mark - WhiteCombinePlayerDelegate

- (void)combinePlayerStartBuffering
{
  //Either end goes into the buffer
  NSLog(@"combinePlayerStartBuffering");
}

- (void)combinePlayerEndBuffering
{
  //Both ends end buffering
  NSLog(@"combinePlayerEndBuffering");
}

@end

动态PPT本地资源包

原理:预先下载所有必需的动态转换zip文件,使用iOS 11支持的WKWebView自定义Scheme请求,拦截WebView请求,并返回本地资源。

具体实现,请查看Git记录。

  1. 所需依赖:为demo添加ppt zip功能的依赖项
  2. 代码实现:实现本地zip

注意,当前demo实现了拦截,还需要对WhiteBaseViewController.MWhitePptParamskPPTScheme方案参数进行调整。

动态转换zip

自定义应用程序插件

自定义应用程序插件可以扩展白板功能,用户可以编写js代码实现自己的白板插件。

如何开发自定义白板应用

注册自定义应用程序插件

在使用自定义应用程序时,Native端需要在SDK中注册相应的App。

注册方法是WhiteSDkregisterAppWithParams:

WhiteRegisterAppParams有两种生成方式。

  1. 将js代码复制到本地项目,并直接注入js字符串。注意这种方法,您需要在js中提供变量名。
@interface WhiteRegisterAppParams : WhiteObject
 
/** Create a custom app generated by js code
@param javascriptString js code string
@param kind plug-in type name, needs to be consistent across multiple ends
@param appOptions additional parameters for plugin registration, fill in as needed
@param variable The name of the app variable to be inserted in the above injected javascript
*/
+ (instancetype)paramsWithJavascriptString: (NSString *)javascriptString kind:(NSString *)kind appOptions:(NSDictionary *)appOptions variable:(NSString *)variable;
  1. 提供js代码的下载地址,让SDK进行下载和注入。注意这种方法,App变量的查找将根据kind参数确定。请确保js中的App变量名与kind一致。
@interface WhiteRegisterAppParams : WhiteObject
 
/** Create a custom app generated by remote js
@param url js address
@param kind The name of the plugin type, which needs to be consistent across multiple ends. (The whiteboard will use this name to find the app entry)
@param appOptions Additional parameters for plugin registration, fill in as needed
*/
+ (instancetype)paramsWithUrl: (NSString *)url kind:(NSString *)kind appOptions:(NSDictionary *)appOptions;

将自定义应用程序插件添加到白板中

添加自定义应用程序的方法是addApp:comletionHandler:WhiteRoom

其中WhiteAppParam用于描述您的自定义应用程序。

请调用此方法来完成WhiteAppParam的初始化。

@interface WhiteAppParam : WhiteObject
 
/* Specific App, generally used to create custom App insertion parameters
 @param kind The kind used when registering the App
 @param options See [WhiteAppOptions](WhiteAppOptions) for details
 @param attrs Parameters to initialize the App, fill in as needed
 */
- (instancetype)initWithKind:(NSString *)kind options:(WhiteAppOptions *)options attrs:(NSDictionary *)attrs;

使用YYKit

此SDK的默认依赖项为YYModel,如果使用YYKit,则某些用户可能在依赖项中遇到错误。

解决方案是修改Podfile。

pod 'Whiteboard/Whiteboard-YYKit'

问题的一部分

  1. 当前 SDK 关键字为 'White',并不严格以三个大写字母为前缀。
  2. 在复杂内容的情况下,由于内存不足,WhiteBoard 可能在系统中被杀死,导致出现白屏。我们已在版本 2.16.30 中修复了此问题。在 2.16.30 之前,您可以将 WhiteBoardViewnavigationDelegate 设置为监听 webViewWebContentProcessDidTerminate: 方法。当白板被杀死时,此方法将被调用,您可以在该方法中提示用户重新连接以恢复白板。
  3. 关于 cocoapods 发布:项目中的某些 subspec 依赖于不支持 arm64-simulator 架构的静态库,例如 YYKit,这会导致 pod lint 失败。当前的解决方案是修改本地的 validator.rb 文件。有关详细信息,请参阅 此处