title: 实战教程

本文档将给出一些详尽的示例教程。

示例说明

本教程以一对一视频通话为例,讲解如何通过 Video SDK 实现实时视频通话功能。

在此之前需要开启控制面板中的“实时视频通话”功能。

示例的最终的展示效果如下图:

video_quickstart_android_conversation

具体步骤

1.安装 SDK

Video SDK 包含了 Sync 和 Auth SDK 的依赖,不需要重复导入 Sync / Auth SDK 。

  • 使用 Maven 安装 Wilddog Video SDK
  1. <dependency>
    <groupId>com.wilddog.client</groupId>
    <artifactId>wilddog-video-android</artifactId>
    <version>0.5.15</version>
    <type>aar</type>
    </dependency>
  • 使用 Gradle 安装 Wilddog Video SDK
  1. dependencies {
    compile 'com.wilddog.client:wilddog-video-android:0.5.15'
    }

如果出现由于文件重复导致的编译错误,可以在 build.gradle 中添加 packingOptions:

  1. android {
  2. ...
  3. packagingOptions {
  4. exclude 'META-INF/LICENSE'
  5. exclude 'META-INF/NOTICE'
  6. }
  7. }

2. 用户身份认证

视频通话的前提条件是要有可识别的用户身份。在这里使用 Auth SDK 的匿名登录实现身份认证。认证后会为每个用户分配唯一的 Wilddog ID。

  1. //初始化 WilddogApp,完成初始化之后可在项目任意位置通过 getInstance() 获取 Sync & Auth 对象
  2. WilddogOptions.Builder builder = new WilddogOptions.Builder().setSyncUrl("http://" + mAppId + ".wilddogio.com");
  3. WilddogOptions options = builder.build();
  4. WilddogApp.initializeApp(getApplicationContext(), options);
  5. //获取 Sync & Auth 对象
  6. SyncReference mRef = WilddogSync.getInstance().getReference();
  7. WilddogAuth auth = WilddogAuth.getInstance();
  8. //采用匿名登录方式认证
  9. //还可以选择其他登录方式
  10. //auth.signInWithEmailAndPassword();
  11. //auth.signInWithCredential();
  12. //auth.signInWithCustomToken();
  13. auth.signInAnonymously().addOnCompleteListener(new OnCompleteListener<AuthResult>() {
  14. @Override
  15. public void onComplete(Task<AuthResult> task) {
  16. if (task.isSuccessful()) {
  17. //身份认证成功
  18. }else {
  19. throw new RuntimeException("auth 失败"+task.getException().getMessage());
  20. }
  21. }
  22. });

3. 初始化 Wilddog Video SDK

用户身份认证成功后,可以初始化 Wilddog Video SDK 。

  1. //初始化 WilddogVideo SDK
  2. WilddogVideo.initializeWilddogVideo(getApplicationContext(), <Wilddog APPID>);
  3. //获取 WilddogVideo对象
  4. WilddogVideo videoWilddogVideo.getInstance();
  5. //获取client对象
  6. WilddogVideoClient client = video.getClient();
  7. //....

4. 实现用户列表

邀请对方加入视频通话,需要获取对方的在线状态。Video SDK 本身不提供获取在线用户列表功能,因此需要开发者使用 Sync SDK 来自己实现。用户登陆系统后将自己的 Wilddog ID 保存到用户列表中。

数据库中的数据结构如图所示:

video_resources_ios_datatree

4.1 存储用户的 Wilddog ID

在登录时存储用户的 Wilddog ID:

  1. //用户可以使用任意自定义节点来保存用户数据,但是不要使用 [交互路径/video]节点存放私有数据,以防和Video SDK 数据发生冲突
  2. //本示例采用根节点下的[交互路径/users] 节点作为用户列表存储节点,
  3. auth.signInAnonymously().addOnCompleteListener(new OnCompleteListener<AuthResult>() {
  4. @Override
  5. public void onComplete(Task<AuthResult> task) {
  6. if (task.isSuccessful()) {
  7. //获取Wilddog ID
  8. String uid = auth.getCurrentUser().getUid();
  9. //用户可以使用任意自定义节点来保存用户数据,但是不要使用 [wilddogVideo]节点存放私有数据
  10. //以防和Video SDK 数据发生冲突
  11. //本示例采用根节点下的[users] 节点作为用户列表存储节点
  12. Map<String, Object> map = new HashMap<String, Object>();
  13. map.put(uid, true);
  14. SyncReference userRef=WilddogSync.getInstance().getReference("users");
  15. userRef.updateChildren(map);
  16. userRef.child(uid).onDisconnect().removeValue();
  17. }else {
  18. throw new RuntimeException("auth 失败"+task.getException().getMessage());
  19. }
  20. }
  21. });

4.2 监听在线用户

获取用户列表时,监听users节点,获取到在线用户信息

  1. private List<String> userList = new ArrayList<>();
  2. //监听users节点
  3. mRef.child("users").addChildEventListener(new ChildEventListener() {
  4. @Override
  5. public void onChildAdded(DataSnapshot dataSnapshot, String s) {
  6. if (dataSnapshot != null) {
  7. //获取用户Wilddog ID并添加到用户列表中
  8. String uid = dataSnapshot.getKey();
  9. if (!mUid.equals(uid)) {
  10. userList.add(uid);
  11. }
  12. }
  13. }
  14. @Override
  15. public void onChildChanged(DataSnapshot dataSnapshot, String s) {
  16. }
  17. @Override
  18. public void onChildRemoved(DataSnapshot dataSnapshot) {
  19. if (dataSnapshot != null) {
  20. //用户离开时,从用户列表中删除用户数据
  21. String key = dataSnapshot.getKey();
  22. if (!mUid.equals(key)) {
  23. userList.remove(key);
  24. adapter.notifyDataSetChanged();
  25. }
  26. }
  27. }
  28. @Override
  29. public void onChildMoved(DataSnapshot dataSnapshot, String s) {
  30. }
  31. @Override
  32. public void onCancelled(SyncError wilddogError) {
  33. }
  34. });

5. 获取和预览本地视频

通过 Video SDK 获取本地视频流,并在视频展示控件中预览。

  1. //视频展示控件
  2. WilddogVideoView localView = (WilddogVideoView) findViewById(R.id.local_video_view);
  3. localView.setZOrderMediaOverlay(true);
  4. //本地媒体流设置镜像
  5. localView.setMirror(true);
  6. //配置本地音视频流
  7. LocalStreamOptions.Builder builder = new LocalStreamOptions.Builder();
  8. LocalStreamOptions options = builder.height(240).width(320).build();
  9. localStream = video.createLocalStream(options, new
  10. CompleteListener() {
  11. @Override
  12. public void onCompleted(VideoException e) {
  13. }
  14. });
  15. //为视频流绑定播放控件
  16. localStream.attach(localView);

6. 发起视频通话

选择用户列表中的用户,发起视频通话。

  1. //在使用 inviteToConversation 方法前需要先设置视频通话邀请监听,否则使用邀请功能会抛出IllegalStateException异常
  2. client.setInviteListener(new InviteListener(){
  3. //...
  4. });
  5. //选取用户列表中的用户,获得其 Wilddog ID
  6. String participantId=[获得的用户 Wilddog ID];
  7. //创建连接参数对象
  8. //localStream 为video.createLocalStream()获取的本地视频流
  9. //第二个参数为用户自定义的数据,类型为字符串
  10. ConnectOptions options = new ConnectOptions(localStream, "chaih");
  11. //inviteToConversation 方法会返回一个OutgoingInvite对象,
  12. //通过OutgoingInvite对象可以进行取消邀请操作
  13. outgoingInvite = client.inviteToConversation(participantId,options, new ConversationCallback() {
  14. @Override
  15. public void onConversation(Conversation conversation, VideoException exception) {
  16. if (conversation != null) {
  17. //对方接受邀请并成功建立视频通话,conversation不为空,exception为空
  18. mConversation = conversation;
  19. } else {
  20. //对方拒绝时,exception不为空
  21. }
  22. }
  23. });

7. 接受或拒绝邀请

发起视频通话后,被邀请人会收到邀请事件,被邀请人可以选择接受或拒绝该邀请,接受邀请则视频通话建立。

  1. this.client.setInviteListener(new WilddogVideoClient.Listener() {
  2. @Override
  3. public void onIncomingInvite(WilddogVideoClient wilddogVideoClient, IncomingInvite incomingInvite) {
  4. //收到邀请,接受视频通话发起者的邀请
  5. ConnectOptions connectOptions = new ConnectOptions(localStream, "");
  6. incomingInvite.accept(connectOptions, new ConversationCallback() {
  7. @Override
  8. public void onConversation(@Nullable Conversation conversation, @Nullable VideoException e) {
  9. }
  10. });
  11. }
  12. @Override
  13. public void onIncomingInviteCanceled(WilddogVideoClient wilddogVideoClient, IncomingInvite incomingInvite) {
  14. //视频通话发起者取消了邀请
  15. }
  16. });

8. 展示对方视频

视频通话建立成功后,在视频通话中能够获取到对方视频流,在视频展示控件中展示。

  1. //设置视频展示控件
  2. WilddogVideoView remoteView = (WilddogVideoView) findViewById(R.id.remote_video_view);
  3. WilddogVideoViewLayout remoteViewLayout = (WilddogVideoViewLayout) findViewById(R.id.remote_video_view_layout);
  4. remoteViewLayout.setPosition(REMOTE_X, REMOTE_Y, REMOTE_WIDTH, REMOTE_HEIGHT);

在成功建立连接后,为已建立的 conversation 建立监听参与者加入信息,并获取视频流。

  1. mConversation.setConversationListener(new Conversation.Listener() {
  2. @Override
  3. public void onConnected(Conversation conversation) {
  4. //监听视频通话连接事件
  5. }
  6. @Override
  7. public void onConnectFailed(Conversation conversation, VideoException e) {
  8. //监听视频通话连接失败事件
  9. }
  10. @Override
  11. public void onDisconnected(Conversation conversation, VideoException e) {
  12. //监听视频通话断开连接事件
  13. }
  14. @Override
  15. public void onParticipantConnected(Conversation conversation, Participant participant) {
  16. //监听参与者接受邀请并加入视频通话的事件
  17. //在参与者加入时获得到加入的参与者,并设置监听
  18. participant.setListener(new Participant.Listener() {
  19. @Override
  20. public void onStreamAdded(RemoteStream remoteStream) {
  21. //远端参与者流可用,展示远端视频流
  22. remoteStream.attach(remoteView);
  23. }
  24. @Override
  25. public void onStreamRemoved(RemoteStream remoteStream) {
  26. }
  27. @Override
  28. public void onError(VideoException e) {
  29. }
  30. });
  31. }
  32. @Override
  33. public void onParticipantDisconnected(Conversation conversation, Participant participant) {
  34. //监听参与者离开事件
  35. mConversation.disconnect();
  36. }
  37. });

9. 离开视频通话

视频通话过程中,调用下面方法离开视频通话。

  1. @Override
  2. protected void onDestroy() {
  3. super.onDestroy();
  4. //需要离开会话时调用此方法,并做资源释放和其他自定义操作
  5. localStream.detach();
  6. localStream.close();
  7. if (localView != null) {
  8. localView.release();
  9. localView = null;
  10. }
  11. if (remoteView != null) {
  12. remoteView.release();
  13. remoteView = null;
  14. }
  15. if (mConversation != null) {
  16. mConversation.disconnect();
  17. }
  18. client.dispose();
  19. video.dispose();
  20. }

获取示例源码

点此获取完整的 示例源码