本项目为 White-SDK-iOS 的开源版本,为了更好的显示源码结构,Whiteboard
将项目分为了多个subpod
,更有利于开发者查看项目源码层级。为此需要修改引用关系。
pod 'Whiteboard'
dependencies: [
.package(url: "https://github.com/netless-io/Whiteboard-iOS.git", .upToNextMajor(from: "2.15.0"))
]
White-SDK-iOS 闭源库迁移
只需要将
#import <White-SDK-iOS/WhiteSDK.h>
修改为
#import <Whiteboard/Whiteboard.h>
即可。
使用时,只要 import 以下内容即可。
#import <Whiteboard/Whiteboard.h>
# 使用白板sdk中任意类
cd Example
pod install
进入Example文件夹,打开 Example.xcworkspace
项目文件。
同时在
Whiteboard-Prefix.pch
根据代码注释填写WhiteSDKToken
,WhiteAppIdentifier
。
/* FIXME: sdkToken
该 sdk token 不应该保存在客户端中,所有涉及 sdk token 的请求(当前类中所有请求),都应该放在服务器中进行,以免泄露产生不必要的风险。
*/
//#define WhiteSDKToken <#@sdk Token#>
//#define WhiteAppIdentifier <#@App identifier#>
#endif
如果需要进入确定的房间进行调试,找到Whiteboard-Prefix.pch
文件中,取消WhiteRoomUUID
,以及WhiteRoomToken
注释,同时填入指定的内容。
# 如果填写了 WhiteRoomUUID WhiteRoomToken,WhiteSDKToken 可以填写为空字符串
//#define WhiteSDKToken <#@sdk Token#>
//#define WhiteAppIdentifier <#@App identifier#>
// 如果需要进入特定房间,取消以下两行注释,同时填入对应的 UUID 以及 roomToken
//#define WhiteRoomUUID <#Room UUID#>
//#define WhiteRoomToken <#Room Token#>
此时,如果在加入或者回放房间时,都会进入该房间。
单元测试需要对某些特殊行为进行测试,所以需要对应房间有以下操作:
运行设备:iOS 10 + 开发环境:Xcode 10+
SDK由多个subpod
组成,依赖结构如下图所示:
参数配置类:用于描述和存储API参数,返回值,状态等配置项的类。主要用于与
webview
进行交互。
YYModel
处理JSON
转换。包含以下部分:
Object
基类,所有sdk
中使用的参数配置类的基类。Room
,Player
中API所涉及到的一些参数配置类。SDK
Displayer
以及部分相关类,主要为以下部分:
WhiteSDK
以及其初始化参数类。WhiteSDK
设置的通用回调WhiteCommonCallbacks
Room
与Player
共同的父类Displayer
类的实现。Displayer
中API所使用的一些参数配置类。Displayer
用来描述当前房间状态的类,为RoomState
,PlayerState
的基类。Room
类,及其相关事件回调类。WhiteSDK+Room
,使用SDK
创建Room
的API。Room
特有的参数配置类。Room
状态相关的类。Player
类,及其相关事件回调类。WhiteSDK+Player
,使用SDK
创建Player
的API。Player
特有的参数配置类。Player
状态相关的类。iOS
端播放音视频,并与白板播放状态做同步
WhiteCombinePlayer
类,及其相关部分类。sdk 现在支持使用 CombinePlayer,在 Native 端播放音视频,sdk 会负责音视频与白板回放的状态同步。
具体代码示例,可以参看 WhitePlayerViewController
m3u8 格式的音视频,可能需要经过一次 combinePlayerEndBuffering 调用后,才能进行
seek
播放。(否则可能仍然从初始位置开始播放)
#import <Whiteboard/Whiteboard.h>
@implementation WhitePlayerViewController
- (void)initPlayer
{
// 创建 WhitePlayer逻辑
// 1. 配置 SDK 初始化参数,更多参数,可见 WhiteSdkConfiguration 头文件
WhiteSdkConfiguration *config = [[WhiteSdkConfiguration alloc] initWithApp:[WhiteUtils appIdentifier]];
// 2. 初始化 SDK
self.sdk = [[WhiteSDK alloc] initWithWhiteBoardView:self.boardView config:config commonCallbackDelegate:self.commonDelegate];
// 3. 配置 WhitePlayerConfig,room uuid 与 roomToken 为必须。其他更多参数,见 WhitePlayerConfig.h 头文件
WhitePlayerConfig *playerConfig = [[WhitePlayerConfig alloc] initWithRoom:self.roomUuid roomToken:self.roomToken];
//音视频,白板混合播放处理类
self.combinePlayer = [[WhiteCombinePlayer alloc] initWithMediaUrl:[NSURL URLWithString:@"https://netless-media.oss-cn-hangzhou.aliyuncs.com/c447a98ece45696f09c7fc88f649c082_3002a61acef14e4aa1b0154f734a991d.m3u8"]];
//显示 AVPlayer 画面
[self.videoView setAVPlayer:self.combinePlayer.nativePlayer];
//配置代理
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(@"创建回放房间失败 error:%@", [error localizedDescription]);
} else {
self.player = player;
[self.player addHighFrequencyEventListener:@"a" fireInterval:1000];
//配置 WhitePlayer
self.combinePlayer.whitePlayer = player;/Users/Agora/Documents/Agora/Whiteboard-iOS/README-zh.md
//WhitePlayer 需要先手动 seek 到 0 才会触发缓冲行为
[player seekToScheduleTime:0];
}
}];
}
#pragma mark - WhitePlayerEventDelegate
- (void)phaseChanged:(WhitePlayerPhase)phase
{
NSLog(@"player %s %ld", __FUNCTION__, (long)phase);
// 注意!必须完成该操作,WhiteCombinePlayer 才能正确同步状态
[self.combinePlayer updateWhitePlayerPhase:phase];
}
// 其他回调方法...
#pragma mark - WhiteCombinePlayerDelegate
- (void)combinePlayerStartBuffering
{
//任意一端进入缓冲
NSLog(@"combinePlayerStartBuffering");
}
- (void)combinePlayerEndBuffering
{
//两端都结束缓冲
NSLog(@"combinePlayerEndBuffering");
}
@end
原理:提前下载动态转换所有需要的资源包,使用 WKWebView iOS 11 开始支持的自定义 scheme 请求,拦截 webView 请求,返回 native 端本地资源。
具体实现,请查看 git 记录:
add dependency to demo for ppt zip feature
implement local zip
>注意,当前 demo 中,实现拦截,还需要在WhiteBaseViewController.m
中,将WhitePptParams
的 scheme 参数为kPPTScheme
。pod 'Whiteboard/fpa'
依赖nativeWebSocket
为 YES[[FpaProxyService sharedFpaProxyService] setupDelegate:(id<FpaProxyServiceDelegate>)self];
注意:如果是M1的电脑想要在模拟器调试,请在Podfile里加入如下声明:
post_install do |installer|
installer.pods_project.build_configurations.each do |config|
config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64"
end
自定义App插件可以扩展白板功能,用户通过编写js代码来实现自己的白板插件。
Native端在使用自定义App时需要注册对应的App到SDK中。
注册方法时WhiteSDk
的registerAppWithParams:
其中WhiteRegisterAppParams
有两种生成方式:
@interface WhiteRegisterAppParams : WhiteObject
/** 创建一个由js代码生成的自定义app
@param javascriptString js代码字符串
@param kind 插件类型名称,需要在多端保持一致
@param appOptions 插件注册额外参数,按需填
@param variable 在上述注入的javascript中,要插入的app变量名
*/
+ (instancetype)paramsWithJavascriptString: (NSString *)javascriptString kind:(NSString *)kind appOptions:(NSDictionary *)appOptions variable:(NSString *)variable;
/** 创建一个由远端js生成的自定义app @param url js地址 @param kind 插件类型名称,需要在多端保持一致。(白板会利用这个名字去寻找app入口) @param appOptions 插件注册额外参数,按需填 */
(instancetype)paramsWithUrl: (NSString *)url kind:(NSString *)kind appOptions:(NSDictionary *)appOptions;
### 添加自定义App插件到白板中
添加自定义App方法是`WhiteRoom`的`addApp:comletionHandler:`
其中`WhiteAppParam`用来描述你的自定义App
请调用该方法完成`WhiteAppParam`初始化
```Objective-C
@interface WhiteAppParam : WhiteObject
/** 特定的App,一般用来创建自定义的App插入参数
@param kind 注册App时使用的kind
@param options 详见[WhiteAppOptions](WhiteAppOptions)
@param attrs 初始化App的参数,按需填
*/
- (instancetype)initWithKind:(NSString *)kind options:(WhiteAppOptions *)options attrs:(NSDictionary *)attrs;
本SDK默认依赖为YYModel,部分使用者若使用YYKit,依赖关系将会发生错误。
解决方法为修改Podfile:
pod 'Whiteboard/Whiteboard-YYKit'
如果你引用了fpa你可以这样声明:
pod 'Whiteboard/fpa-YYKit'
White
,未严格使用前置三大写字母做前缀。WhiteBoardView
的 navigationDelegate
来监听 webViewWebContentProcessDidTerminate:
方法。当白板被kill掉时,会调用该方法,你可以在该方法中提示用户重新连接以恢复白板。Framework 打包(需安装pod package 插件:sudo gem install cocoapods-packager
)
pod package Whiteboard.podspec --embedded --force
(基于Github源码)pod package Whiteboard.podspec --force --embedded --local
(基于本地源码)gem install specific_install
gem specific_install https://github.com/CocoaPods/cocoapods-packager
关于Framework 手动添加
Whiteboard.framework yymodel.framework dsBridge.framework 一并拖入Embed设置为 Do not embed
FAQ:
遇到问题:have the same architectures (arm64) and can't be in the same fat output file
参考
1.https://github.com/CocoaPods/cocoapods-packager/issues/259
2.“could not build module xxx” 报错:修改工程target - Allow Non-modular Includes In Framework Modules
3.Command CodeSign failed with a nonzero exit code报错 Whiteboard.framework 改为Do not embed