下载

下载

2
评论

基于环信sdk在uni-app框架中快速开发一款多平台社交Demo SDK uni_app 环信

beyond 发表了文章 • 556 次浏览 • 2020-05-11 11:34 • 来自相关话题

说在前面:此款 demo 是基于 环信sdk 开发的一款具有单聊、群聊、聊天室、音视频等功能的应用。在此之前我们已经开发完 Vue、react(web端)、微信小程序。这三个热门领域的版本,如有需要源码可以后台留言索取。





 
安装开发工具

我们选用微信小程序来用做示例(如果选择百度、支付宝安装对应开发者工具即可)、

微信开发者工具建议还是安装最新版的。uni-app的开发也必须安装HBuilderX工具,这个是捆绑的,没得选择。要用uni-app,你必须得装!

工具安装:

微信开发者工具

HBuilderX

项目demo介绍:






项目demo启动预览:





 
快速集成环信 sdk:

1、复制整个utils文件






如果你想具体了解主要配置文件 请看这个链接:

http://docs-im.easemob.com/im/web/intro/start

2、如何使用环信的appkey ,可以在环信 console 后台注册一个 账号申请appkey ,可以参考这里 ,获取到  appkey 以后添加到配置文件中 ,如下图所示:






以上两个重要的配置准备完成之后就可以进行一系列的操作了(收发消息、好友申请、进群入群通知等)

在uni-app中 使用环信 sdk 实现添加、删除好友:

1、在全局 App.vue 文件 钩子函数 onLaunch() 中监听各种事件 (好友申请、收到各类消息等)如图:






发送好友请求:






在onPresence(message)事件中接收到好友消息申请:






同意好友请求:






拒绝好友请求:






实现收发消息:

1、给好友发送消息:






2、接收到消息:

在onTextMessage(message)事件中接收到好友消息,然后做消息上屏处理(具体消息上屏逻辑可看demo中代码示例):





以上展示的仅仅为基本业务场景,更多的业务逻辑详情请看demo示例。api具体详情可以查看 环信sdk 文档

最后结语:基于uni-app这个框架可实现多平台, 虽然目前一期集成环信sdk的版本仅支持微信小程序版本,但二期我们将加入头条、支付宝等小程序,敬请期待。PS:对于安卓、ios移动端,我们建议使用针对移动端开发的sdk版本。

基于uni-app的开发其中也趟了不少坑,在这里就不多赘述了。回归到框架的选型来讲,选用uni-app开发小程序,可同时并行多端小程序,这点是真香,一次开发多端发布。至于审核嘛~ 时快时慢。 查看全部
说在前面:此款 demo 是基于 环信sdk 开发的一款具有单聊、群聊、聊天室、音视频等功能的应用。在此之前我们已经开发完 Vue、react(web端)、微信小程序。这三个热门领域的版本,如有需要源码可以后台留言索取。

1.jpg

 
安装开发工具

我们选用微信小程序来用做示例(如果选择百度、支付宝安装对应开发者工具即可)、

微信开发者工具建议还是安装最新版的。uni-app的开发也必须安装HBuilderX工具,这个是捆绑的,没得选择。要用uni-app,你必须得装!

工具安装:

微信开发者工具

HBuilderX

项目demo介绍:

2.jpg


项目demo启动预览:

3.jpg

 
快速集成环信 sdk:

1、复制整个utils文件

4.jpg


如果你想具体了解主要配置文件 请看这个链接:

http://docs-im.easemob.com/im/web/intro/start

2、如何使用环信的appkey ,可以在环信 console 后台注册一个 账号申请appkey ,可以参考这里 ,获取到  appkey 以后添加到配置文件中 ,如下图所示:

5.jpg


以上两个重要的配置准备完成之后就可以进行一系列的操作了(收发消息、好友申请、进群入群通知等)

在uni-app中 使用环信 sdk 实现添加、删除好友:

1、在全局 App.vue 文件 钩子函数 onLaunch() 中监听各种事件 (好友申请、收到各类消息等)如图:

6.jpg


发送好友请求:

7.jpg


在onPresence(message)事件中接收到好友消息申请:

8.jpg


同意好友请求:

9.jpg


拒绝好友请求:

10.jpg


实现收发消息:

1、给好友发送消息:

11.jpg


2、接收到消息:

在onTextMessage(message)事件中接收到好友消息,然后做消息上屏处理(具体消息上屏逻辑可看demo中代码示例):

12.jpg

以上展示的仅仅为基本业务场景,更多的业务逻辑详情请看demo示例。api具体详情可以查看 环信sdk 文档

最后结语:基于uni-app这个框架可实现多平台, 虽然目前一期集成环信sdk的版本仅支持微信小程序版本,但二期我们将加入头条、支付宝等小程序,敬请期待。PS:对于安卓、ios移动端,我们建议使用针对移动端开发的sdk版本。

基于uni-app的开发其中也趟了不少坑,在这里就不多赘述了。回归到框架的选型来讲,选用uni-app开发小程序,可同时并行多端小程序,这点是真香,一次开发多端发布。至于审核嘛~ 时快时慢。
1
评论

手把手教程:4小时开发一个视频会议APP【附开源代码】 环信 开源 视频会议

fat1 发表了文章 • 1054 次浏览 • 2020-04-17 00:29 • 来自相关话题

今年是不平凡的一年,没错,就是因为疫情,因为疫情原因 ,大家只能呆着家里,严重影响了我们正常的学习 生活 工作,在这种情况下,只能在家办公,这时候大家就会想到线上视频会议,目前很多互联网公司有这个产品,比较出名的就比如 腾讯会议 钉钉 zoom等,用这些是很方便,但是如果能开发自己的视频会议,那会不会更好或者是更有成就感,下面简单介绍这个这个项目,和大概的开发过程。本项目基于环信音视频云来完成,实现的主要功能有:
  创建会议、删除会议、获取指定会议室详情、加入会议室、退出会议室等关于会议的管理 ;  获取会议室参会人名列表、踢人,设置观众为主播,设置主播为观众等关于会议室的人员管理;  共享桌面(web端);
 三个端的实现:Android,iOS,Web

上面这些功能在项目中都已经实现。还有水印 ,变声等高级功能在环信音视频SDK的接口内部都已经封装好,本项目没有实现 ,大家可以自行去实现。有关多人音视频功能更详细的介绍大家可以参考:这儿。多人音视频实现的实现主要有以下一些场景:社交交友,远程心理咨询、远程医疗、一对一在线教育、远程视频辅助等。咳咳 ,接下来就是纯干货了,给大家介绍我是如何一步步开发出一个完整的多人音视频app。
 
项目截图
 
首先给大家展示下项目运行的效果图,会议界面 主窗口是一个大的 RelativeLayout ,最下面的那一排排小窗口是的实现方法是HorizontalScrollView加上一个开源的组件 com.jaouan.compoundlayout.RadioLayoutGroup 实现的,点击下面的小窗口后,可以 把小窗口的视频流显示在大屏上,具体是调用 updateRemoteSurfaceView(String streamId, EMCallSurfaceView remoteView)来更新SurfaceView,具体的细节大家可以看看代码里面的实现 最后会公布代码开源地址。
















准备工作
    大家得下载安装Android Studio,配置好Android 开发环境,怎么详细配置我就在这不再细说了 网上有很多的教程,大家自己可以找找看,然后大家可以看看环信多人音视频会议的主要功能和一些基本概念介绍。
集成 
  1. 首先大家会想问怎么调用环信的SDK ,大家可以使用 远程依赖SDK包,建议大家用最新版本的远程依赖:
     com.hyphenate:hyphenate-sdk:3.6.6 ,依赖包可以放在 build.gradle里面的 dependencies 选项下面,如下图所示





2.其次怎么使用环信的appkey ,可以在环信音视频云后台注册一个 账号申请appkey ,可以参考这里 ,获取到  appkey 以后添加到AndroidManifest.xml中 ,如下图所示:






3.经过以上两个重要的前期配置准备 ,接下来我们就可以开始进行代码开发了,首先我们先创建一个项目的DemoApplication类和      DemoHelper类,DemoApplication 类和DemoHelper类都是一个单例类 ,DemoApplication 主要功能就是进行DemoHelper 的初始化,而DemoHelper里面主要是主要有一些option 配置和EMClient 进行初始化,代码如下所示:public void init(Context context) {
EMOptions options = initChatOptions(context);
EMClient.getInstance().init(context, options);
PreferenceManager.init(context);
}
  DemoHelper还有一个重要的功能就是设置  EMConferenceListener 进行会议监听,有关 EMConferenceListener的类的详细介绍 ,通过这个监听可以再加入会议的时候获取到已经在会议中的流和主播信息,分别是通过其中以下两个回调获取:@Override
public void onMemberJoined(EMConferenceMember member){

}

@Override
public void onStreamAdded(EMConferenceStream stream){

}
4.DemoApplication类完成以后,接下来就是怎么去登陆 环信IM 账号和 创建加入会议房间了,首次安装的时候都没有账号,我们使用的办法是自动注册一个账号 在本地进行保存,然后进行登录 ,注册 登录详细接口请看 这儿,  注册 登录的调用大概如下所示: 
 try {
        //注册一个环信ID
        EMClient.getInstance().createAccount(username, password);
            
        //注册成功进行登录
        PreferenceManager.getInstance().setCurrentUserName(username);
        PreferenceManager.getInstance().setCurrentuserPassword(password);
        login();
    } catch (final HyphenateException e) {
       runOnUiThread(new Runnable() {
               public void run() {
                  int errorCode=e.getErrorCode();
                   if(errorCode==EMError.NETWORK_ERROR){
                    Toast.makeText(getApplicationContext(), getResources().getString(R.string.network_anomalies), Toast.LENGTH_SHORT).show();
      }
   }   
}
 
  public void login() {
 
        //登录已经注册成功的环信ID
        EMClient.getInstance().login(username, password, new EMCallBack() {
            @Override
            public void onSuccess() {
                Log.d(TAG, "login: onSuccess");
                //登录成功进入会议房间
                joinRoom();
            }
            @Override
            public void onProgress(int progress, String status) {
                Log.d(TAG, "login: onProgress");
            }
            @Override
            public void onError(final int code, final String message) {
                Log.d(TAG, "login: onError: " + code);
                runOnUiThread(new Runnable() {
                    public void run() {
                        Toast.makeText(getApplicationContext(), getString(R.string.Login_failed) + message,Toast.LENGTH_SHORT).show();
                    }
                });
            }
        });
    }
登录完成以后,我们可以根据房间名创建并加入房间,主要代码大概如下: EMClient.getInstance().conferenceManager().joinRoom(currentRoomname, currentPassword, conferenceRole,roomConfig, new EMValueCallBack<EMConference>(){
@Override
public void onSuccess(EMConference value) {
EMLog.i(TAG, "join conference success");
Intent intent = new Intent(MainActivity.this, ConferenceActivity.class);
startActivity(intent);
finish();
}
@Override
public void onError(final int error, final String errorMsg) {
EMLog.e(TAG, "join conference failed error " + error + ", msg " + errorMsg);
runOnUiThread(new Runnable() {
@Override
public void run() {
setBtnEnable(true);
if(error == CALL_TALKER_ISFULL) {
takerFullDialogDisplay();
}else{
Toast.makeText(getApplicationContext(), "Join conference failed " + error + " " + errorMsg, Toast.LENGTH_SHORT).show();
}
}
});
}
});
EMClient.getInstance().conferenceManager().joinRoom() API可以根据房间名创建指定会议,当以该房间名命名的会议不存在时候,会直接创建,当会议已经创建好 可以根据正确的房间名和密码加入房间 ,到这一步为止,我们已经成功的创建 并加入会议。
5.加入会议以后我们进入到会议界面,展示从DemoHelper类 EMConferenceListener 中的 onStreamAdded 回调 和 onMemberJoined 获取到的流和主播列表 ,在ConferenceActivity 中实现 EMConferenceListener ,然后直接把 ConferenceActivity 注册监听,用以下方法  EMClient.getInstance().conferenceManager().addConferenceListener(this); 这样就可实现 EMConferenceListener 事件的处理,比如
 主播 进出房间 :
public void onMemberJoined(final EMConferenceMember member);
public void onMemberExited(final EMConferenceMember member);

增加流 移除流:
public void onStreamAdded(final EMConferenceStream stream)
 public void onStreamRemoved(final EMConferenceStream stream)

管理员变更: 
public void onAdminAdded(String streamId) ;  
public void onAdminRemoved(String streamId)

角色变更  用户被踢  谁在说话等各种回调,可以处理各种业务逻辑 ,详细的请参考 项目中的实现 ,最后会附上项目的开源地址。

6 进入会议房间以后如果用户角色为主播可以进行发布视频流 ,观众只能订阅视频流 不能发布视频流 ,可以调用SDK的publish接口发布流,该接口用到了EMStreamParam参数,你可以自由配置,比如是否上传视频,是否上传音频,使用前置或后置摄像头,视频码率,显示视频页面等等,具体实现可以参考 中发布 订阅视频流的内容, 关于以上的代码逻辑如以 如以下: //发布视频流
normalParam = new EMStreamParam();
normalParam.setStreamType(EMConferenceStream.StreamType.NORMAL);
normalParam.setVideoOff(true);
normalParam.setAudioOff(true);

EMClient.getInstance().conferenceManager().publish(normalParam, new EMValueCallBack<String>() {
@Override
public void onSuccess(String value) {
conference.setPubStreamId(value, EMConferenceStream.StreamType.NORMAL);
addOrUpdateStreamList("local-stream", value);

PhoneStateManager.get(ConferenceActivity.this).addStateCallback(phoneStateCallback);
}

@Override
public void onError(int error, String errorMsg) {
EMLog.i(TAG, "publish failed: error=" + error + ", msg=" + errorMsg);
}
});
//订阅其他主播的视频流
private void subscribe(EMConferenceStream stream, EMCallSurfaceView surfaceView) {
EMClient.getInstance().conferenceManager().subscribe(stream, surfaceView, new EMValueCallBack<String>() {
@Override
public void onSuccess(String value) {
}

@Override
public void onError(int error, String errorMsg) {

}
});
}
7.有关上麦 下麦 的逻辑处理,观众可以请求上麦成为主播,主播可以下麦成为观众,上麦 下麦 是利用 EMConferenceAttribute进行处理 ,EMConferenceAttribute  是一个事件广播,广播事件是一个key-value格式,key-value 可以由开发者进行自行定义,增添事件以后 ,服务器会把事件进行广播。会议中成员会收到 onAttributesUpdated回调。例如本项目中的会议上麦 下麦 代码如下所示://上麦申请

EMClient.getInstance().conferenceManager().setConferenceAttribute(
EMClient.getInstance().getCurrentUser(),
"request_tobe_speaker",
new EMValueCallBack<Void>() {
@Override
public void onSuccess(Void value) {
EMLog.i(TAG, "request_tobe_speaker scuessed");

}

@Override
public void onError(int error, String errorMsg) {
EMLog.i(TAG, "request_tobe_speaker failed: error=" + error

}
});

//下麦申请
EMClient.getInstance().conferenceManager().setConferenceAttribute(EMClient.getInstance().getCurrentUser()
, "request_tobe_audience", new EMValueCallBack<Void>() {
@Override
public void onSuccess(Void value) {
EMLog.i(TAG, "request_tobe_audience scuessed");
}

@Override
public void onError(int error, String errorMsg) {
EMLog.i(TAG, "request_tobe_audience failed: error=" + error + ", msg=" + errorMsg);
}
});
 上麦 下麦 请求发出以后 只能由主持人去处理,处理在 EMConferenceListener  的回调 onAttributesUpdated(EMConferenceAttribute attributes) 去处理 ,收到回调以后 解析attributes 然后进行处理请求,处理的过程代码大概如下: EMClient.getInstance().conferenceManager().grantRole(conference.getConferenceId()
, new EMConferenceMember(memName, null, null,null)
, EMConferenceManager.EMConferenceRole.Talker, new EMValueCallBack<String>() {
@Override
public void onSuccess(String value) {
EMLog.i(TAG, " requestTalkerDisplay request_tobe_speaker changeRole success, result: " + value);
dialog.dismiss();
}
@Override
public void onError(int error, String errorMsg) {
EMLog.i(TAG, " requestTalkerDisplay request_tobe_speaker changeRole failed, error: " + error + " - " + errorMsg);

}
});
下麦也是和上麦一样是利用 EMConferenceAttribute进行处理。

9.有关退出会议 销毁会议 普通主播  观众只能退出会议 ,主持人还可以 销毁会议 正在进行中的会议可以进行销毁,退出会议 销毁会议 具体代码如下: EMClient.getInstance().conferenceManager().exitConference(new EMValueCallBack() {
@Override
public void onSuccess(Object value) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "您已成功退出当前会议!", Toast.LENGTH_SHORT).show();
}
});
}

@Override
public void onError(int error, String errorMsg) {
EMLog.i(TAG, "exit conference failed " + error + ", " + errorMsg);
}
});

EMClient.getInstance().conferenceManager().destroyConference(new EMValueCallBack() {
@Override
public void onSuccess(Object value) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "您已成功销毁当前会议!", Toast.LENGTH_SHORT).show();
}
});
EMLog.i(TAG, "finish ConferenceActivity");
finish();
}

尾语
至此 整个 多人音视频会议开发的详细步骤 已经完成 ,虽然比较麻烦 但是每个步骤都很清晰 ,有不太清楚的欢迎大家积极讨论, 附上本项目的github地址:https://github.com/easemob/videocall-android  欢迎大家积极参与 ,谢谢支持。
Demo下载 二维码如下 欢迎大家体验(iOS版和web版下载地址请见:https://www.easemob.com/download/rtc)






  查看全部
今年是不平凡的一年,没错,就是因为疫情,因为疫情原因 ,大家只能呆着家里,严重影响了我们正常的学习 生活 工作,在这种情况下,只能在家办公,这时候大家就会想到线上视频会议,目前很多互联网公司有这个产品,比较出名的就比如 腾讯会议 钉钉 zoom等,用这些是很方便,但是如果能开发自己的视频会议,那会不会更好或者是更有成就感,下面简单介绍这个这个项目,和大概的开发过程。本项目基于环信音视频云来完成,实现的主要功能有:
  •   创建会议、删除会议、获取指定会议室详情、加入会议室、退出会议室等关于会议的管理 ;
  •   获取会议室参会人名列表、踢人,设置观众为主播,设置主播为观众等关于会议室的人员管理;
  •   共享桌面(web端);

 三个端的实现:Android,iOS,Web

上面这些功能在项目中都已经实现。还有水印 ,变声等高级功能在环信音视频SDK的接口内部都已经封装好,本项目没有实现 ,大家可以自行去实现。有关多人音视频功能更详细的介绍大家可以参考:这儿。多人音视频实现的实现主要有以下一些场景:社交交友,远程心理咨询、远程医疗、一对一在线教育、远程视频辅助等。咳咳 ,接下来就是纯干货了,给大家介绍我是如何一步步开发出一个完整的多人音视频app。
 
项目截图
 
首先给大家展示下项目运行的效果图,会议界面 主窗口是一个大的 RelativeLayout ,最下面的那一排排小窗口是的实现方法是HorizontalScrollView加上一个开源的组件 com.jaouan.compoundlayout.RadioLayoutGroup 实现的,点击下面的小窗口后,可以 把小窗口的视频流显示在大屏上,具体是调用 updateRemoteSurfaceView(String streamId, EMCallSurfaceView remoteView)来更新SurfaceView,具体的细节大家可以看看代码里面的实现 最后会公布代码开源地址。

20200410140627956.jpg


20200410140855852.jpg


20200410141055394.jpg


准备工作
    大家得下载安装Android Studio,配置好Android 开发环境,怎么详细配置我就在这不再细说了 网上有很多的教程,大家自己可以找找看,然后大家可以看看环信多人音视频会议的主要功能和一些基本概念介绍。
集成 
  1. 首先大家会想问怎么调用环信的SDK ,大家可以使用 远程依赖SDK包,建议大家用最新版本的远程依赖:
     com.hyphenate:hyphenate-sdk:3.6.6 ,依赖包可以放在 build.gradle里面的 dependencies 选项下面,如下图所示
2020040917363212.png


2.其次怎么使用环信的appkey ,可以在环信音视频云后台注册一个 账号申请appkey ,可以参考这里 ,获取到  appkey 以后添加到AndroidManifest.xml中 ,如下图所示:

20200409213959916.png


3.经过以上两个重要的前期配置准备 ,接下来我们就可以开始进行代码开发了,首先我们先创建一个项目的DemoApplication类和      DemoHelper类,DemoApplication 类和DemoHelper类都是一个单例类 ,DemoApplication 主要功能就是进行DemoHelper 的初始化,而DemoHelper里面主要是主要有一些option 配置和EMClient 进行初始化,代码如下所示:
public void init(Context context) {
EMOptions options = initChatOptions(context);
EMClient.getInstance().init(context, options);
PreferenceManager.init(context);
}

  DemoHelper还有一个重要的功能就是设置  EMConferenceListener 进行会议监听,有关 EMConferenceListener的类的详细介绍 ,通过这个监听可以再加入会议的时候获取到已经在会议中的流和主播信息,分别是通过其中以下两个回调获取:
@Override 
public void onMemberJoined(EMConferenceMember member){

}

@Override
public void onStreamAdded(EMConferenceStream stream){

}

4.DemoApplication类完成以后,接下来就是怎么去登陆 环信IM 账号和 创建加入会议房间了,首次安装的时候都没有账号,我们使用的办法是自动注册一个账号 在本地进行保存,然后进行登录 ,注册 登录详细接口请看 这儿,  注册 登录的调用大概如下所示: 
 try {
        //注册一个环信ID
        EMClient.getInstance().createAccount(username, password);
            
        //注册成功进行登录
        PreferenceManager.getInstance().setCurrentUserName(username);
        PreferenceManager.getInstance().setCurrentuserPassword(password);
        login();
    } catch (final HyphenateException e) {
       runOnUiThread(new Runnable() {
               public void run() {
                  int errorCode=e.getErrorCode();
                   if(errorCode==EMError.NETWORK_ERROR){
                    Toast.makeText(getApplicationContext(), getResources().getString(R.string.network_anomalies), Toast.LENGTH_SHORT).show();
      }
   }   
}
 
  public void login() {
 
        //登录已经注册成功的环信ID
        EMClient.getInstance().login(username, password, new EMCallBack() {
            @Override
            public void onSuccess() {
                Log.d(TAG, "login: onSuccess");
                //登录成功进入会议房间
                joinRoom();
            }
            @Override
            public void onProgress(int progress, String status) {
                Log.d(TAG, "login: onProgress");
            }
            @Override
            public void onError(final int code, final String message) {
                Log.d(TAG, "login: onError: " + code);
                runOnUiThread(new Runnable() {
                    public void run() {
                        Toast.makeText(getApplicationContext(), getString(R.string.Login_failed) + message,Toast.LENGTH_SHORT).show();
                    }
                });
            }
        });
    }
登录完成以后,我们可以根据房间名创建并加入房间,主要代码大概如下:
 EMClient.getInstance().conferenceManager().joinRoom(currentRoomname, currentPassword, conferenceRole,roomConfig, new EMValueCallBack<EMConference>(){
@Override
public void onSuccess(EMConference value) {
EMLog.i(TAG, "join conference success");
Intent intent = new Intent(MainActivity.this, ConferenceActivity.class);
startActivity(intent);
finish();
}
@Override
public void onError(final int error, final String errorMsg) {
EMLog.e(TAG, "join conference failed error " + error + ", msg " + errorMsg);
runOnUiThread(new Runnable() {
@Override
public void run() {
setBtnEnable(true);
if(error == CALL_TALKER_ISFULL) {
takerFullDialogDisplay();
}else{
Toast.makeText(getApplicationContext(), "Join conference failed " + error + " " + errorMsg, Toast.LENGTH_SHORT).show();
}
}
});
}
});

EMClient.getInstance().conferenceManager().joinRoom() API可以根据房间名创建指定会议,当以该房间名命名的会议不存在时候,会直接创建,当会议已经创建好 可以根据正确的房间名和密码加入房间 ,到这一步为止,我们已经成功的创建 并加入会议。
5.加入会议以后我们进入到会议界面,展示从DemoHelper类 EMConferenceListener 中的 onStreamAdded 回调 和 onMemberJoined 获取到的流和主播列表 ,在ConferenceActivity 中实现 EMConferenceListener ,然后直接把 ConferenceActivity 注册监听,用以下方法  EMClient.getInstance().conferenceManager().addConferenceListener(this); 这样就可实现 EMConferenceListener 事件的处理,比如
 主播 进出房间 :
public void onMemberJoined(final EMConferenceMember member);
public void onMemberExited(final EMConferenceMember member);

增加流 移除流:
public void onStreamAdded(final EMConferenceStream stream)
 public void onStreamRemoved(final EMConferenceStream stream)

管理员变更: 
public void onAdminAdded(String streamId) ;  
public void onAdminRemoved(String streamId)

角色变更  用户被踢  谁在说话等各种回调,可以处理各种业务逻辑 ,详细的请参考 项目中的实现 ,最后会附上项目的开源地址。

6 进入会议房间以后如果用户角色为主播可以进行发布视频流 ,观众只能订阅视频流 不能发布视频流 ,可以调用SDK的publish接口发布流,该接口用到了EMStreamParam参数,你可以自由配置,比如是否上传视频,是否上传音频,使用前置或后置摄像头,视频码率,显示视频页面等等,具体实现可以参考 中发布 订阅视频流的内容, 关于以上的代码逻辑如以 如以下:
 //发布视频流
normalParam = new EMStreamParam();
normalParam.setStreamType(EMConferenceStream.StreamType.NORMAL);
normalParam.setVideoOff(true);
normalParam.setAudioOff(true);

EMClient.getInstance().conferenceManager().publish(normalParam, new EMValueCallBack<String>() {
@Override
public void onSuccess(String value) {
conference.setPubStreamId(value, EMConferenceStream.StreamType.NORMAL);
addOrUpdateStreamList("local-stream", value);

PhoneStateManager.get(ConferenceActivity.this).addStateCallback(phoneStateCallback);
}

@Override
public void onError(int error, String errorMsg) {
EMLog.i(TAG, "publish failed: error=" + error + ", msg=" + errorMsg);
}
});
//订阅其他主播的视频流
private void subscribe(EMConferenceStream stream, EMCallSurfaceView surfaceView) {
EMClient.getInstance().conferenceManager().subscribe(stream, surfaceView, new EMValueCallBack<String>() {
@Override
public void onSuccess(String value) {
}

@Override
public void onError(int error, String errorMsg) {

}
});
}

7.有关上麦 下麦 的逻辑处理,观众可以请求上麦成为主播,主播可以下麦成为观众,上麦 下麦 是利用 EMConferenceAttribute进行处理 ,EMConferenceAttribute  是一个事件广播,广播事件是一个key-value格式,key-value 可以由开发者进行自行定义,增添事件以后 ,服务器会把事件进行广播。会议中成员会收到 onAttributesUpdated回调。例如本项目中的会议上麦 下麦 代码如下所示:
//上麦申请  

EMClient.getInstance().conferenceManager().setConferenceAttribute(
EMClient.getInstance().getCurrentUser(),
"request_tobe_speaker",
new EMValueCallBack<Void>() {
@Override
public void onSuccess(Void value) {
EMLog.i(TAG, "request_tobe_speaker scuessed");

}

@Override
public void onError(int error, String errorMsg) {
EMLog.i(TAG, "request_tobe_speaker failed: error=" + error

}
});

//下麦申请
EMClient.getInstance().conferenceManager().setConferenceAttribute(EMClient.getInstance().getCurrentUser()
, "request_tobe_audience", new EMValueCallBack<Void>() {
@Override
public void onSuccess(Void value) {
EMLog.i(TAG, "request_tobe_audience scuessed");
}

@Override
public void onError(int error, String errorMsg) {
EMLog.i(TAG, "request_tobe_audience failed: error=" + error + ", msg=" + errorMsg);
}
});

 上麦 下麦 请求发出以后 只能由主持人去处理,处理在 EMConferenceListener  的回调 onAttributesUpdated(EMConferenceAttribute attributes) 去处理 ,收到回调以后 解析attributes 然后进行处理请求,处理的过程代码大概如下:
   EMClient.getInstance().conferenceManager().grantRole(conference.getConferenceId()
, new EMConferenceMember(memName, null, null,null)
, EMConferenceManager.EMConferenceRole.Talker, new EMValueCallBack<String>() {
@Override
public void onSuccess(String value) {
EMLog.i(TAG, " requestTalkerDisplay request_tobe_speaker changeRole success, result: " + value);
dialog.dismiss();
}
@Override
public void onError(int error, String errorMsg) {
EMLog.i(TAG, " requestTalkerDisplay request_tobe_speaker changeRole failed, error: " + error + " - " + errorMsg);

}
});

下麦也是和上麦一样是利用 EMConferenceAttribute进行处理。

9.有关退出会议 销毁会议 普通主播  观众只能退出会议 ,主持人还可以 销毁会议 正在进行中的会议可以进行销毁,退出会议 销毁会议 具体代码如下:
 EMClient.getInstance().conferenceManager().exitConference(new EMValueCallBack() {
@Override
public void onSuccess(Object value) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "您已成功退出当前会议!", Toast.LENGTH_SHORT).show();
}
});
}

@Override
public void onError(int error, String errorMsg) {
EMLog.i(TAG, "exit conference failed " + error + ", " + errorMsg);
}
});

EMClient.getInstance().conferenceManager().destroyConference(new EMValueCallBack() {
@Override
public void onSuccess(Object value) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "您已成功销毁当前会议!", Toast.LENGTH_SHORT).show();
}
});
EMLog.i(TAG, "finish ConferenceActivity");
finish();
}

尾语
至此 整个 多人音视频会议开发的详细步骤 已经完成 ,虽然比较麻烦 但是每个步骤都很清晰 ,有不太清楚的欢迎大家积极讨论, 附上本项目的github地址:https://github.com/easemob/videocall-android  欢迎大家积极参与 ,谢谢支持。
Demo下载 二维码如下 欢迎大家体验(iOS版和web版下载地址请见:https://www.easemob.com/download/rtc)


20200410142228530.png

 
0
评论

史上最完整的官方Oracle OCP中文文教材,快来下载吧!! 下载

beyond 发表了文章 • 1943 次浏览 • 2019-05-09 16:18 • 来自相关话题

内含文件:
1、Oracle Database 11g:SQL 基础 学生指南第1 册 
2、Oracle Database 11g:SQL 基础 学生指南第2 册 
3、Oracle Database 11g:数据库管理- 课堂练习I 学生指南第1 册
4、Oracle Database 11g:数据库管理- 课堂练习II 学生指南第1 册 
5、Oracle Database 11g:数据库管理- 课堂练习I 学生指南第2 册 
6、Oracle Database 11g:数据库管理- 课堂练习II 学生指南第2 册 
7、Oracle Da等等 查看全部
内含文件:
1、Oracle Database 11g:SQL 基础 学生指南第1 册 
2、Oracle Database 11g:SQL 基础 学生指南第2 册 
3、Oracle Database 11g:数据库管理- 课堂练习I 学生指南第1 册
4、Oracle Database 11g:数据库管理- 课堂练习II 学生指南第1 册 
5、Oracle Database 11g:数据库管理- 课堂练习I 学生指南第2 册 
6、Oracle Database 11g:数据库管理- 课堂练习II 学生指南第2 册 
7、Oracle Da等等
2
评论

基于环信sdk在uni-app框架中快速开发一款多平台社交Demo SDK uni_app 环信

beyond 发表了文章 • 556 次浏览 • 2020-05-11 11:34 • 来自相关话题

说在前面:此款 demo 是基于 环信sdk 开发的一款具有单聊、群聊、聊天室、音视频等功能的应用。在此之前我们已经开发完 Vue、react(web端)、微信小程序。这三个热门领域的版本,如有需要源码可以后台留言索取。





 
安装开发工具

我们选用微信小程序来用做示例(如果选择百度、支付宝安装对应开发者工具即可)、

微信开发者工具建议还是安装最新版的。uni-app的开发也必须安装HBuilderX工具,这个是捆绑的,没得选择。要用uni-app,你必须得装!

工具安装:

微信开发者工具

HBuilderX

项目demo介绍:






项目demo启动预览:





 
快速集成环信 sdk:

1、复制整个utils文件






如果你想具体了解主要配置文件 请看这个链接:

http://docs-im.easemob.com/im/web/intro/start

2、如何使用环信的appkey ,可以在环信 console 后台注册一个 账号申请appkey ,可以参考这里 ,获取到  appkey 以后添加到配置文件中 ,如下图所示:






以上两个重要的配置准备完成之后就可以进行一系列的操作了(收发消息、好友申请、进群入群通知等)

在uni-app中 使用环信 sdk 实现添加、删除好友:

1、在全局 App.vue 文件 钩子函数 onLaunch() 中监听各种事件 (好友申请、收到各类消息等)如图:






发送好友请求:






在onPresence(message)事件中接收到好友消息申请:






同意好友请求:






拒绝好友请求:






实现收发消息:

1、给好友发送消息:






2、接收到消息:

在onTextMessage(message)事件中接收到好友消息,然后做消息上屏处理(具体消息上屏逻辑可看demo中代码示例):





以上展示的仅仅为基本业务场景,更多的业务逻辑详情请看demo示例。api具体详情可以查看 环信sdk 文档

最后结语:基于uni-app这个框架可实现多平台, 虽然目前一期集成环信sdk的版本仅支持微信小程序版本,但二期我们将加入头条、支付宝等小程序,敬请期待。PS:对于安卓、ios移动端,我们建议使用针对移动端开发的sdk版本。

基于uni-app的开发其中也趟了不少坑,在这里就不多赘述了。回归到框架的选型来讲,选用uni-app开发小程序,可同时并行多端小程序,这点是真香,一次开发多端发布。至于审核嘛~ 时快时慢。 查看全部
说在前面:此款 demo 是基于 环信sdk 开发的一款具有单聊、群聊、聊天室、音视频等功能的应用。在此之前我们已经开发完 Vue、react(web端)、微信小程序。这三个热门领域的版本,如有需要源码可以后台留言索取。

1.jpg

 
安装开发工具

我们选用微信小程序来用做示例(如果选择百度、支付宝安装对应开发者工具即可)、

微信开发者工具建议还是安装最新版的。uni-app的开发也必须安装HBuilderX工具,这个是捆绑的,没得选择。要用uni-app,你必须得装!

工具安装:

微信开发者工具

HBuilderX

项目demo介绍:

2.jpg


项目demo启动预览:

3.jpg

 
快速集成环信 sdk:

1、复制整个utils文件

4.jpg


如果你想具体了解主要配置文件 请看这个链接:

http://docs-im.easemob.com/im/web/intro/start

2、如何使用环信的appkey ,可以在环信 console 后台注册一个 账号申请appkey ,可以参考这里 ,获取到  appkey 以后添加到配置文件中 ,如下图所示:

5.jpg


以上两个重要的配置准备完成之后就可以进行一系列的操作了(收发消息、好友申请、进群入群通知等)

在uni-app中 使用环信 sdk 实现添加、删除好友:

1、在全局 App.vue 文件 钩子函数 onLaunch() 中监听各种事件 (好友申请、收到各类消息等)如图:

6.jpg


发送好友请求:

7.jpg


在onPresence(message)事件中接收到好友消息申请:

8.jpg


同意好友请求:

9.jpg


拒绝好友请求:

10.jpg


实现收发消息:

1、给好友发送消息:

11.jpg


2、接收到消息:

在onTextMessage(message)事件中接收到好友消息,然后做消息上屏处理(具体消息上屏逻辑可看demo中代码示例):

12.jpg

以上展示的仅仅为基本业务场景,更多的业务逻辑详情请看demo示例。api具体详情可以查看 环信sdk 文档

最后结语:基于uni-app这个框架可实现多平台, 虽然目前一期集成环信sdk的版本仅支持微信小程序版本,但二期我们将加入头条、支付宝等小程序,敬请期待。PS:对于安卓、ios移动端,我们建议使用针对移动端开发的sdk版本。

基于uni-app的开发其中也趟了不少坑,在这里就不多赘述了。回归到框架的选型来讲,选用uni-app开发小程序,可同时并行多端小程序,这点是真香,一次开发多端发布。至于审核嘛~ 时快时慢。
1
评论

手把手教程:4小时开发一个视频会议APP【附开源代码】 环信 开源 视频会议

fat1 发表了文章 • 1054 次浏览 • 2020-04-17 00:29 • 来自相关话题

今年是不平凡的一年,没错,就是因为疫情,因为疫情原因 ,大家只能呆着家里,严重影响了我们正常的学习 生活 工作,在这种情况下,只能在家办公,这时候大家就会想到线上视频会议,目前很多互联网公司有这个产品,比较出名的就比如 腾讯会议 钉钉 zoom等,用这些是很方便,但是如果能开发自己的视频会议,那会不会更好或者是更有成就感,下面简单介绍这个这个项目,和大概的开发过程。本项目基于环信音视频云来完成,实现的主要功能有:
  创建会议、删除会议、获取指定会议室详情、加入会议室、退出会议室等关于会议的管理 ;  获取会议室参会人名列表、踢人,设置观众为主播,设置主播为观众等关于会议室的人员管理;  共享桌面(web端);
 三个端的实现:Android,iOS,Web

上面这些功能在项目中都已经实现。还有水印 ,变声等高级功能在环信音视频SDK的接口内部都已经封装好,本项目没有实现 ,大家可以自行去实现。有关多人音视频功能更详细的介绍大家可以参考:这儿。多人音视频实现的实现主要有以下一些场景:社交交友,远程心理咨询、远程医疗、一对一在线教育、远程视频辅助等。咳咳 ,接下来就是纯干货了,给大家介绍我是如何一步步开发出一个完整的多人音视频app。
 
项目截图
 
首先给大家展示下项目运行的效果图,会议界面 主窗口是一个大的 RelativeLayout ,最下面的那一排排小窗口是的实现方法是HorizontalScrollView加上一个开源的组件 com.jaouan.compoundlayout.RadioLayoutGroup 实现的,点击下面的小窗口后,可以 把小窗口的视频流显示在大屏上,具体是调用 updateRemoteSurfaceView(String streamId, EMCallSurfaceView remoteView)来更新SurfaceView,具体的细节大家可以看看代码里面的实现 最后会公布代码开源地址。
















准备工作
    大家得下载安装Android Studio,配置好Android 开发环境,怎么详细配置我就在这不再细说了 网上有很多的教程,大家自己可以找找看,然后大家可以看看环信多人音视频会议的主要功能和一些基本概念介绍。
集成 
  1. 首先大家会想问怎么调用环信的SDK ,大家可以使用 远程依赖SDK包,建议大家用最新版本的远程依赖:
     com.hyphenate:hyphenate-sdk:3.6.6 ,依赖包可以放在 build.gradle里面的 dependencies 选项下面,如下图所示





2.其次怎么使用环信的appkey ,可以在环信音视频云后台注册一个 账号申请appkey ,可以参考这里 ,获取到  appkey 以后添加到AndroidManifest.xml中 ,如下图所示:






3.经过以上两个重要的前期配置准备 ,接下来我们就可以开始进行代码开发了,首先我们先创建一个项目的DemoApplication类和      DemoHelper类,DemoApplication 类和DemoHelper类都是一个单例类 ,DemoApplication 主要功能就是进行DemoHelper 的初始化,而DemoHelper里面主要是主要有一些option 配置和EMClient 进行初始化,代码如下所示:public void init(Context context) {
EMOptions options = initChatOptions(context);
EMClient.getInstance().init(context, options);
PreferenceManager.init(context);
}
  DemoHelper还有一个重要的功能就是设置  EMConferenceListener 进行会议监听,有关 EMConferenceListener的类的详细介绍 ,通过这个监听可以再加入会议的时候获取到已经在会议中的流和主播信息,分别是通过其中以下两个回调获取:@Override
public void onMemberJoined(EMConferenceMember member){

}

@Override
public void onStreamAdded(EMConferenceStream stream){

}
4.DemoApplication类完成以后,接下来就是怎么去登陆 环信IM 账号和 创建加入会议房间了,首次安装的时候都没有账号,我们使用的办法是自动注册一个账号 在本地进行保存,然后进行登录 ,注册 登录详细接口请看 这儿,  注册 登录的调用大概如下所示: 
 try {
        //注册一个环信ID
        EMClient.getInstance().createAccount(username, password);
            
        //注册成功进行登录
        PreferenceManager.getInstance().setCurrentUserName(username);
        PreferenceManager.getInstance().setCurrentuserPassword(password);
        login();
    } catch (final HyphenateException e) {
       runOnUiThread(new Runnable() {
               public void run() {
                  int errorCode=e.getErrorCode();
                   if(errorCode==EMError.NETWORK_ERROR){
                    Toast.makeText(getApplicationContext(), getResources().getString(R.string.network_anomalies), Toast.LENGTH_SHORT).show();
      }
   }   
}
 
  public void login() {
 
        //登录已经注册成功的环信ID
        EMClient.getInstance().login(username, password, new EMCallBack() {
            @Override
            public void onSuccess() {
                Log.d(TAG, "login: onSuccess");
                //登录成功进入会议房间
                joinRoom();
            }
            @Override
            public void onProgress(int progress, String status) {
                Log.d(TAG, "login: onProgress");
            }
            @Override
            public void onError(final int code, final String message) {
                Log.d(TAG, "login: onError: " + code);
                runOnUiThread(new Runnable() {
                    public void run() {
                        Toast.makeText(getApplicationContext(), getString(R.string.Login_failed) + message,Toast.LENGTH_SHORT).show();
                    }
                });
            }
        });
    }
登录完成以后,我们可以根据房间名创建并加入房间,主要代码大概如下: EMClient.getInstance().conferenceManager().joinRoom(currentRoomname, currentPassword, conferenceRole,roomConfig, new EMValueCallBack<EMConference>(){
@Override
public void onSuccess(EMConference value) {
EMLog.i(TAG, "join conference success");
Intent intent = new Intent(MainActivity.this, ConferenceActivity.class);
startActivity(intent);
finish();
}
@Override
public void onError(final int error, final String errorMsg) {
EMLog.e(TAG, "join conference failed error " + error + ", msg " + errorMsg);
runOnUiThread(new Runnable() {
@Override
public void run() {
setBtnEnable(true);
if(error == CALL_TALKER_ISFULL) {
takerFullDialogDisplay();
}else{
Toast.makeText(getApplicationContext(), "Join conference failed " + error + " " + errorMsg, Toast.LENGTH_SHORT).show();
}
}
});
}
});
EMClient.getInstance().conferenceManager().joinRoom() API可以根据房间名创建指定会议,当以该房间名命名的会议不存在时候,会直接创建,当会议已经创建好 可以根据正确的房间名和密码加入房间 ,到这一步为止,我们已经成功的创建 并加入会议。
5.加入会议以后我们进入到会议界面,展示从DemoHelper类 EMConferenceListener 中的 onStreamAdded 回调 和 onMemberJoined 获取到的流和主播列表 ,在ConferenceActivity 中实现 EMConferenceListener ,然后直接把 ConferenceActivity 注册监听,用以下方法  EMClient.getInstance().conferenceManager().addConferenceListener(this); 这样就可实现 EMConferenceListener 事件的处理,比如
 主播 进出房间 :
public void onMemberJoined(final EMConferenceMember member);
public void onMemberExited(final EMConferenceMember member);

增加流 移除流:
public void onStreamAdded(final EMConferenceStream stream)
 public void onStreamRemoved(final EMConferenceStream stream)

管理员变更: 
public void onAdminAdded(String streamId) ;  
public void onAdminRemoved(String streamId)

角色变更  用户被踢  谁在说话等各种回调,可以处理各种业务逻辑 ,详细的请参考 项目中的实现 ,最后会附上项目的开源地址。

6 进入会议房间以后如果用户角色为主播可以进行发布视频流 ,观众只能订阅视频流 不能发布视频流 ,可以调用SDK的publish接口发布流,该接口用到了EMStreamParam参数,你可以自由配置,比如是否上传视频,是否上传音频,使用前置或后置摄像头,视频码率,显示视频页面等等,具体实现可以参考 中发布 订阅视频流的内容, 关于以上的代码逻辑如以 如以下: //发布视频流
normalParam = new EMStreamParam();
normalParam.setStreamType(EMConferenceStream.StreamType.NORMAL);
normalParam.setVideoOff(true);
normalParam.setAudioOff(true);

EMClient.getInstance().conferenceManager().publish(normalParam, new EMValueCallBack<String>() {
@Override
public void onSuccess(String value) {
conference.setPubStreamId(value, EMConferenceStream.StreamType.NORMAL);
addOrUpdateStreamList("local-stream", value);

PhoneStateManager.get(ConferenceActivity.this).addStateCallback(phoneStateCallback);
}

@Override
public void onError(int error, String errorMsg) {
EMLog.i(TAG, "publish failed: error=" + error + ", msg=" + errorMsg);
}
});
//订阅其他主播的视频流
private void subscribe(EMConferenceStream stream, EMCallSurfaceView surfaceView) {
EMClient.getInstance().conferenceManager().subscribe(stream, surfaceView, new EMValueCallBack<String>() {
@Override
public void onSuccess(String value) {
}

@Override
public void onError(int error, String errorMsg) {

}
});
}
7.有关上麦 下麦 的逻辑处理,观众可以请求上麦成为主播,主播可以下麦成为观众,上麦 下麦 是利用 EMConferenceAttribute进行处理 ,EMConferenceAttribute  是一个事件广播,广播事件是一个key-value格式,key-value 可以由开发者进行自行定义,增添事件以后 ,服务器会把事件进行广播。会议中成员会收到 onAttributesUpdated回调。例如本项目中的会议上麦 下麦 代码如下所示://上麦申请

EMClient.getInstance().conferenceManager().setConferenceAttribute(
EMClient.getInstance().getCurrentUser(),
"request_tobe_speaker",
new EMValueCallBack<Void>() {
@Override
public void onSuccess(Void value) {
EMLog.i(TAG, "request_tobe_speaker scuessed");

}

@Override
public void onError(int error, String errorMsg) {
EMLog.i(TAG, "request_tobe_speaker failed: error=" + error

}
});

//下麦申请
EMClient.getInstance().conferenceManager().setConferenceAttribute(EMClient.getInstance().getCurrentUser()
, "request_tobe_audience", new EMValueCallBack<Void>() {
@Override
public void onSuccess(Void value) {
EMLog.i(TAG, "request_tobe_audience scuessed");
}

@Override
public void onError(int error, String errorMsg) {
EMLog.i(TAG, "request_tobe_audience failed: error=" + error + ", msg=" + errorMsg);
}
});
 上麦 下麦 请求发出以后 只能由主持人去处理,处理在 EMConferenceListener  的回调 onAttributesUpdated(EMConferenceAttribute attributes) 去处理 ,收到回调以后 解析attributes 然后进行处理请求,处理的过程代码大概如下: EMClient.getInstance().conferenceManager().grantRole(conference.getConferenceId()
, new EMConferenceMember(memName, null, null,null)
, EMConferenceManager.EMConferenceRole.Talker, new EMValueCallBack<String>() {
@Override
public void onSuccess(String value) {
EMLog.i(TAG, " requestTalkerDisplay request_tobe_speaker changeRole success, result: " + value);
dialog.dismiss();
}
@Override
public void onError(int error, String errorMsg) {
EMLog.i(TAG, " requestTalkerDisplay request_tobe_speaker changeRole failed, error: " + error + " - " + errorMsg);

}
});
下麦也是和上麦一样是利用 EMConferenceAttribute进行处理。

9.有关退出会议 销毁会议 普通主播  观众只能退出会议 ,主持人还可以 销毁会议 正在进行中的会议可以进行销毁,退出会议 销毁会议 具体代码如下: EMClient.getInstance().conferenceManager().exitConference(new EMValueCallBack() {
@Override
public void onSuccess(Object value) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "您已成功退出当前会议!", Toast.LENGTH_SHORT).show();
}
});
}

@Override
public void onError(int error, String errorMsg) {
EMLog.i(TAG, "exit conference failed " + error + ", " + errorMsg);
}
});

EMClient.getInstance().conferenceManager().destroyConference(new EMValueCallBack() {
@Override
public void onSuccess(Object value) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "您已成功销毁当前会议!", Toast.LENGTH_SHORT).show();
}
});
EMLog.i(TAG, "finish ConferenceActivity");
finish();
}

尾语
至此 整个 多人音视频会议开发的详细步骤 已经完成 ,虽然比较麻烦 但是每个步骤都很清晰 ,有不太清楚的欢迎大家积极讨论, 附上本项目的github地址:https://github.com/easemob/videocall-android  欢迎大家积极参与 ,谢谢支持。
Demo下载 二维码如下 欢迎大家体验(iOS版和web版下载地址请见:https://www.easemob.com/download/rtc)






  查看全部
今年是不平凡的一年,没错,就是因为疫情,因为疫情原因 ,大家只能呆着家里,严重影响了我们正常的学习 生活 工作,在这种情况下,只能在家办公,这时候大家就会想到线上视频会议,目前很多互联网公司有这个产品,比较出名的就比如 腾讯会议 钉钉 zoom等,用这些是很方便,但是如果能开发自己的视频会议,那会不会更好或者是更有成就感,下面简单介绍这个这个项目,和大概的开发过程。本项目基于环信音视频云来完成,实现的主要功能有:
  •   创建会议、删除会议、获取指定会议室详情、加入会议室、退出会议室等关于会议的管理 ;
  •   获取会议室参会人名列表、踢人,设置观众为主播,设置主播为观众等关于会议室的人员管理;
  •   共享桌面(web端);

 三个端的实现:Android,iOS,Web

上面这些功能在项目中都已经实现。还有水印 ,变声等高级功能在环信音视频SDK的接口内部都已经封装好,本项目没有实现 ,大家可以自行去实现。有关多人音视频功能更详细的介绍大家可以参考:这儿。多人音视频实现的实现主要有以下一些场景:社交交友,远程心理咨询、远程医疗、一对一在线教育、远程视频辅助等。咳咳 ,接下来就是纯干货了,给大家介绍我是如何一步步开发出一个完整的多人音视频app。
 
项目截图
 
首先给大家展示下项目运行的效果图,会议界面 主窗口是一个大的 RelativeLayout ,最下面的那一排排小窗口是的实现方法是HorizontalScrollView加上一个开源的组件 com.jaouan.compoundlayout.RadioLayoutGroup 实现的,点击下面的小窗口后,可以 把小窗口的视频流显示在大屏上,具体是调用 updateRemoteSurfaceView(String streamId, EMCallSurfaceView remoteView)来更新SurfaceView,具体的细节大家可以看看代码里面的实现 最后会公布代码开源地址。

20200410140627956.jpg


20200410140855852.jpg


20200410141055394.jpg


准备工作
    大家得下载安装Android Studio,配置好Android 开发环境,怎么详细配置我就在这不再细说了 网上有很多的教程,大家自己可以找找看,然后大家可以看看环信多人音视频会议的主要功能和一些基本概念介绍。
集成 
  1. 首先大家会想问怎么调用环信的SDK ,大家可以使用 远程依赖SDK包,建议大家用最新版本的远程依赖:
     com.hyphenate:hyphenate-sdk:3.6.6 ,依赖包可以放在 build.gradle里面的 dependencies 选项下面,如下图所示
2020040917363212.png


2.其次怎么使用环信的appkey ,可以在环信音视频云后台注册一个 账号申请appkey ,可以参考这里 ,获取到  appkey 以后添加到AndroidManifest.xml中 ,如下图所示:

20200409213959916.png


3.经过以上两个重要的前期配置准备 ,接下来我们就可以开始进行代码开发了,首先我们先创建一个项目的DemoApplication类和      DemoHelper类,DemoApplication 类和DemoHelper类都是一个单例类 ,DemoApplication 主要功能就是进行DemoHelper 的初始化,而DemoHelper里面主要是主要有一些option 配置和EMClient 进行初始化,代码如下所示:
public void init(Context context) {
EMOptions options = initChatOptions(context);
EMClient.getInstance().init(context, options);
PreferenceManager.init(context);
}

  DemoHelper还有一个重要的功能就是设置  EMConferenceListener 进行会议监听,有关 EMConferenceListener的类的详细介绍 ,通过这个监听可以再加入会议的时候获取到已经在会议中的流和主播信息,分别是通过其中以下两个回调获取:
@Override 
public void onMemberJoined(EMConferenceMember member){

}

@Override
public void onStreamAdded(EMConferenceStream stream){

}

4.DemoApplication类完成以后,接下来就是怎么去登陆 环信IM 账号和 创建加入会议房间了,首次安装的时候都没有账号,我们使用的办法是自动注册一个账号 在本地进行保存,然后进行登录 ,注册 登录详细接口请看 这儿,  注册 登录的调用大概如下所示: 
 try {
        //注册一个环信ID
        EMClient.getInstance().createAccount(username, password);
            
        //注册成功进行登录
        PreferenceManager.getInstance().setCurrentUserName(username);
        PreferenceManager.getInstance().setCurrentuserPassword(password);
        login();
    } catch (final HyphenateException e) {
       runOnUiThread(new Runnable() {
               public void run() {
                  int errorCode=e.getErrorCode();
                   if(errorCode==EMError.NETWORK_ERROR){
                    Toast.makeText(getApplicationContext(), getResources().getString(R.string.network_anomalies), Toast.LENGTH_SHORT).show();
      }
   }   
}
 
  public void login() {
 
        //登录已经注册成功的环信ID
        EMClient.getInstance().login(username, password, new EMCallBack() {
            @Override
            public void onSuccess() {
                Log.d(TAG, "login: onSuccess");
                //登录成功进入会议房间
                joinRoom();
            }
            @Override
            public void onProgress(int progress, String status) {
                Log.d(TAG, "login: onProgress");
            }
            @Override
            public void onError(final int code, final String message) {
                Log.d(TAG, "login: onError: " + code);
                runOnUiThread(new Runnable() {
                    public void run() {
                        Toast.makeText(getApplicationContext(), getString(R.string.Login_failed) + message,Toast.LENGTH_SHORT).show();
                    }
                });
            }
        });
    }
登录完成以后,我们可以根据房间名创建并加入房间,主要代码大概如下:
 EMClient.getInstance().conferenceManager().joinRoom(currentRoomname, currentPassword, conferenceRole,roomConfig, new EMValueCallBack<EMConference>(){
@Override
public void onSuccess(EMConference value) {
EMLog.i(TAG, "join conference success");
Intent intent = new Intent(MainActivity.this, ConferenceActivity.class);
startActivity(intent);
finish();
}
@Override
public void onError(final int error, final String errorMsg) {
EMLog.e(TAG, "join conference failed error " + error + ", msg " + errorMsg);
runOnUiThread(new Runnable() {
@Override
public void run() {
setBtnEnable(true);
if(error == CALL_TALKER_ISFULL) {
takerFullDialogDisplay();
}else{
Toast.makeText(getApplicationContext(), "Join conference failed " + error + " " + errorMsg, Toast.LENGTH_SHORT).show();
}
}
});
}
});

EMClient.getInstance().conferenceManager().joinRoom() API可以根据房间名创建指定会议,当以该房间名命名的会议不存在时候,会直接创建,当会议已经创建好 可以根据正确的房间名和密码加入房间 ,到这一步为止,我们已经成功的创建 并加入会议。
5.加入会议以后我们进入到会议界面,展示从DemoHelper类 EMConferenceListener 中的 onStreamAdded 回调 和 onMemberJoined 获取到的流和主播列表 ,在ConferenceActivity 中实现 EMConferenceListener ,然后直接把 ConferenceActivity 注册监听,用以下方法  EMClient.getInstance().conferenceManager().addConferenceListener(this); 这样就可实现 EMConferenceListener 事件的处理,比如
 主播 进出房间 :
public void onMemberJoined(final EMConferenceMember member);
public void onMemberExited(final EMConferenceMember member);

增加流 移除流:
public void onStreamAdded(final EMConferenceStream stream)
 public void onStreamRemoved(final EMConferenceStream stream)

管理员变更: 
public void onAdminAdded(String streamId) ;  
public void onAdminRemoved(String streamId)

角色变更  用户被踢  谁在说话等各种回调,可以处理各种业务逻辑 ,详细的请参考 项目中的实现 ,最后会附上项目的开源地址。

6 进入会议房间以后如果用户角色为主播可以进行发布视频流 ,观众只能订阅视频流 不能发布视频流 ,可以调用SDK的publish接口发布流,该接口用到了EMStreamParam参数,你可以自由配置,比如是否上传视频,是否上传音频,使用前置或后置摄像头,视频码率,显示视频页面等等,具体实现可以参考 中发布 订阅视频流的内容, 关于以上的代码逻辑如以 如以下:
 //发布视频流
normalParam = new EMStreamParam();
normalParam.setStreamType(EMConferenceStream.StreamType.NORMAL);
normalParam.setVideoOff(true);
normalParam.setAudioOff(true);

EMClient.getInstance().conferenceManager().publish(normalParam, new EMValueCallBack<String>() {
@Override
public void onSuccess(String value) {
conference.setPubStreamId(value, EMConferenceStream.StreamType.NORMAL);
addOrUpdateStreamList("local-stream", value);

PhoneStateManager.get(ConferenceActivity.this).addStateCallback(phoneStateCallback);
}

@Override
public void onError(int error, String errorMsg) {
EMLog.i(TAG, "publish failed: error=" + error + ", msg=" + errorMsg);
}
});
//订阅其他主播的视频流
private void subscribe(EMConferenceStream stream, EMCallSurfaceView surfaceView) {
EMClient.getInstance().conferenceManager().subscribe(stream, surfaceView, new EMValueCallBack<String>() {
@Override
public void onSuccess(String value) {
}

@Override
public void onError(int error, String errorMsg) {

}
});
}

7.有关上麦 下麦 的逻辑处理,观众可以请求上麦成为主播,主播可以下麦成为观众,上麦 下麦 是利用 EMConferenceAttribute进行处理 ,EMConferenceAttribute  是一个事件广播,广播事件是一个key-value格式,key-value 可以由开发者进行自行定义,增添事件以后 ,服务器会把事件进行广播。会议中成员会收到 onAttributesUpdated回调。例如本项目中的会议上麦 下麦 代码如下所示:
//上麦申请  

EMClient.getInstance().conferenceManager().setConferenceAttribute(
EMClient.getInstance().getCurrentUser(),
"request_tobe_speaker",
new EMValueCallBack<Void>() {
@Override
public void onSuccess(Void value) {
EMLog.i(TAG, "request_tobe_speaker scuessed");

}

@Override
public void onError(int error, String errorMsg) {
EMLog.i(TAG, "request_tobe_speaker failed: error=" + error

}
});

//下麦申请
EMClient.getInstance().conferenceManager().setConferenceAttribute(EMClient.getInstance().getCurrentUser()
, "request_tobe_audience", new EMValueCallBack<Void>() {
@Override
public void onSuccess(Void value) {
EMLog.i(TAG, "request_tobe_audience scuessed");
}

@Override
public void onError(int error, String errorMsg) {
EMLog.i(TAG, "request_tobe_audience failed: error=" + error + ", msg=" + errorMsg);
}
});

 上麦 下麦 请求发出以后 只能由主持人去处理,处理在 EMConferenceListener  的回调 onAttributesUpdated(EMConferenceAttribute attributes) 去处理 ,收到回调以后 解析attributes 然后进行处理请求,处理的过程代码大概如下:
   EMClient.getInstance().conferenceManager().grantRole(conference.getConferenceId()
, new EMConferenceMember(memName, null, null,null)
, EMConferenceManager.EMConferenceRole.Talker, new EMValueCallBack<String>() {
@Override
public void onSuccess(String value) {
EMLog.i(TAG, " requestTalkerDisplay request_tobe_speaker changeRole success, result: " + value);
dialog.dismiss();
}
@Override
public void onError(int error, String errorMsg) {
EMLog.i(TAG, " requestTalkerDisplay request_tobe_speaker changeRole failed, error: " + error + " - " + errorMsg);

}
});

下麦也是和上麦一样是利用 EMConferenceAttribute进行处理。

9.有关退出会议 销毁会议 普通主播  观众只能退出会议 ,主持人还可以 销毁会议 正在进行中的会议可以进行销毁,退出会议 销毁会议 具体代码如下:
 EMClient.getInstance().conferenceManager().exitConference(new EMValueCallBack() {
@Override
public void onSuccess(Object value) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "您已成功退出当前会议!", Toast.LENGTH_SHORT).show();
}
});
}

@Override
public void onError(int error, String errorMsg) {
EMLog.i(TAG, "exit conference failed " + error + ", " + errorMsg);
}
});

EMClient.getInstance().conferenceManager().destroyConference(new EMValueCallBack() {
@Override
public void onSuccess(Object value) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "您已成功销毁当前会议!", Toast.LENGTH_SHORT).show();
}
});
EMLog.i(TAG, "finish ConferenceActivity");
finish();
}

尾语
至此 整个 多人音视频会议开发的详细步骤 已经完成 ,虽然比较麻烦 但是每个步骤都很清晰 ,有不太清楚的欢迎大家积极讨论, 附上本项目的github地址:https://github.com/easemob/videocall-android  欢迎大家积极参与 ,谢谢支持。
Demo下载 二维码如下 欢迎大家体验(iOS版和web版下载地址请见:https://www.easemob.com/download/rtc)


20200410142228530.png

 
2
评论

基于环信sdk在uni-app框架中快速开发一款多平台社交Demo SDK uni_app 环信

beyond 发表了文章 • 556 次浏览 • 2020-05-11 11:34 • 来自相关话题

说在前面:此款 demo 是基于 环信sdk 开发的一款具有单聊、群聊、聊天室、音视频等功能的应用。在此之前我们已经开发完 Vue、react(web端)、微信小程序。这三个热门领域的版本,如有需要源码可以后台留言索取。





 
安装开发工具

我们选用微信小程序来用做示例(如果选择百度、支付宝安装对应开发者工具即可)、

微信开发者工具建议还是安装最新版的。uni-app的开发也必须安装HBuilderX工具,这个是捆绑的,没得选择。要用uni-app,你必须得装!

工具安装:

微信开发者工具

HBuilderX

项目demo介绍:






项目demo启动预览:





 
快速集成环信 sdk:

1、复制整个utils文件






如果你想具体了解主要配置文件 请看这个链接:

http://docs-im.easemob.com/im/web/intro/start

2、如何使用环信的appkey ,可以在环信 console 后台注册一个 账号申请appkey ,可以参考这里 ,获取到  appkey 以后添加到配置文件中 ,如下图所示:






以上两个重要的配置准备完成之后就可以进行一系列的操作了(收发消息、好友申请、进群入群通知等)

在uni-app中 使用环信 sdk 实现添加、删除好友:

1、在全局 App.vue 文件 钩子函数 onLaunch() 中监听各种事件 (好友申请、收到各类消息等)如图:






发送好友请求:






在onPresence(message)事件中接收到好友消息申请:






同意好友请求:






拒绝好友请求:






实现收发消息:

1、给好友发送消息:






2、接收到消息:

在onTextMessage(message)事件中接收到好友消息,然后做消息上屏处理(具体消息上屏逻辑可看demo中代码示例):





以上展示的仅仅为基本业务场景,更多的业务逻辑详情请看demo示例。api具体详情可以查看 环信sdk 文档

最后结语:基于uni-app这个框架可实现多平台, 虽然目前一期集成环信sdk的版本仅支持微信小程序版本,但二期我们将加入头条、支付宝等小程序,敬请期待。PS:对于安卓、ios移动端,我们建议使用针对移动端开发的sdk版本。

基于uni-app的开发其中也趟了不少坑,在这里就不多赘述了。回归到框架的选型来讲,选用uni-app开发小程序,可同时并行多端小程序,这点是真香,一次开发多端发布。至于审核嘛~ 时快时慢。 查看全部
说在前面:此款 demo 是基于 环信sdk 开发的一款具有单聊、群聊、聊天室、音视频等功能的应用。在此之前我们已经开发完 Vue、react(web端)、微信小程序。这三个热门领域的版本,如有需要源码可以后台留言索取。

1.jpg

 
安装开发工具

我们选用微信小程序来用做示例(如果选择百度、支付宝安装对应开发者工具即可)、

微信开发者工具建议还是安装最新版的。uni-app的开发也必须安装HBuilderX工具,这个是捆绑的,没得选择。要用uni-app,你必须得装!

工具安装:

微信开发者工具

HBuilderX

项目demo介绍:

2.jpg


项目demo启动预览:

3.jpg

 
快速集成环信 sdk:

1、复制整个utils文件

4.jpg


如果你想具体了解主要配置文件 请看这个链接:

http://docs-im.easemob.com/im/web/intro/start

2、如何使用环信的appkey ,可以在环信 console 后台注册一个 账号申请appkey ,可以参考这里 ,获取到  appkey 以后添加到配置文件中 ,如下图所示:

5.jpg


以上两个重要的配置准备完成之后就可以进行一系列的操作了(收发消息、好友申请、进群入群通知等)

在uni-app中 使用环信 sdk 实现添加、删除好友:

1、在全局 App.vue 文件 钩子函数 onLaunch() 中监听各种事件 (好友申请、收到各类消息等)如图:

6.jpg


发送好友请求:

7.jpg


在onPresence(message)事件中接收到好友消息申请:

8.jpg


同意好友请求:

9.jpg


拒绝好友请求:

10.jpg


实现收发消息:

1、给好友发送消息:

11.jpg


2、接收到消息:

在onTextMessage(message)事件中接收到好友消息,然后做消息上屏处理(具体消息上屏逻辑可看demo中代码示例):

12.jpg

以上展示的仅仅为基本业务场景,更多的业务逻辑详情请看demo示例。api具体详情可以查看 环信sdk 文档

最后结语:基于uni-app这个框架可实现多平台, 虽然目前一期集成环信sdk的版本仅支持微信小程序版本,但二期我们将加入头条、支付宝等小程序,敬请期待。PS:对于安卓、ios移动端,我们建议使用针对移动端开发的sdk版本。

基于uni-app的开发其中也趟了不少坑,在这里就不多赘述了。回归到框架的选型来讲,选用uni-app开发小程序,可同时并行多端小程序,这点是真香,一次开发多端发布。至于审核嘛~ 时快时慢。
1
评论

手把手教程:4小时开发一个视频会议APP【附开源代码】 环信 开源 视频会议

fat1 发表了文章 • 1054 次浏览 • 2020-04-17 00:29 • 来自相关话题

今年是不平凡的一年,没错,就是因为疫情,因为疫情原因 ,大家只能呆着家里,严重影响了我们正常的学习 生活 工作,在这种情况下,只能在家办公,这时候大家就会想到线上视频会议,目前很多互联网公司有这个产品,比较出名的就比如 腾讯会议 钉钉 zoom等,用这些是很方便,但是如果能开发自己的视频会议,那会不会更好或者是更有成就感,下面简单介绍这个这个项目,和大概的开发过程。本项目基于环信音视频云来完成,实现的主要功能有:
  创建会议、删除会议、获取指定会议室详情、加入会议室、退出会议室等关于会议的管理 ;  获取会议室参会人名列表、踢人,设置观众为主播,设置主播为观众等关于会议室的人员管理;  共享桌面(web端);
 三个端的实现:Android,iOS,Web

上面这些功能在项目中都已经实现。还有水印 ,变声等高级功能在环信音视频SDK的接口内部都已经封装好,本项目没有实现 ,大家可以自行去实现。有关多人音视频功能更详细的介绍大家可以参考:这儿。多人音视频实现的实现主要有以下一些场景:社交交友,远程心理咨询、远程医疗、一对一在线教育、远程视频辅助等。咳咳 ,接下来就是纯干货了,给大家介绍我是如何一步步开发出一个完整的多人音视频app。
 
项目截图
 
首先给大家展示下项目运行的效果图,会议界面 主窗口是一个大的 RelativeLayout ,最下面的那一排排小窗口是的实现方法是HorizontalScrollView加上一个开源的组件 com.jaouan.compoundlayout.RadioLayoutGroup 实现的,点击下面的小窗口后,可以 把小窗口的视频流显示在大屏上,具体是调用 updateRemoteSurfaceView(String streamId, EMCallSurfaceView remoteView)来更新SurfaceView,具体的细节大家可以看看代码里面的实现 最后会公布代码开源地址。
















准备工作
    大家得下载安装Android Studio,配置好Android 开发环境,怎么详细配置我就在这不再细说了 网上有很多的教程,大家自己可以找找看,然后大家可以看看环信多人音视频会议的主要功能和一些基本概念介绍。
集成 
  1. 首先大家会想问怎么调用环信的SDK ,大家可以使用 远程依赖SDK包,建议大家用最新版本的远程依赖:
     com.hyphenate:hyphenate-sdk:3.6.6 ,依赖包可以放在 build.gradle里面的 dependencies 选项下面,如下图所示





2.其次怎么使用环信的appkey ,可以在环信音视频云后台注册一个 账号申请appkey ,可以参考这里 ,获取到  appkey 以后添加到AndroidManifest.xml中 ,如下图所示:






3.经过以上两个重要的前期配置准备 ,接下来我们就可以开始进行代码开发了,首先我们先创建一个项目的DemoApplication类和      DemoHelper类,DemoApplication 类和DemoHelper类都是一个单例类 ,DemoApplication 主要功能就是进行DemoHelper 的初始化,而DemoHelper里面主要是主要有一些option 配置和EMClient 进行初始化,代码如下所示:public void init(Context context) {
EMOptions options = initChatOptions(context);
EMClient.getInstance().init(context, options);
PreferenceManager.init(context);
}
  DemoHelper还有一个重要的功能就是设置  EMConferenceListener 进行会议监听,有关 EMConferenceListener的类的详细介绍 ,通过这个监听可以再加入会议的时候获取到已经在会议中的流和主播信息,分别是通过其中以下两个回调获取:@Override
public void onMemberJoined(EMConferenceMember member){

}

@Override
public void onStreamAdded(EMConferenceStream stream){

}
4.DemoApplication类完成以后,接下来就是怎么去登陆 环信IM 账号和 创建加入会议房间了,首次安装的时候都没有账号,我们使用的办法是自动注册一个账号 在本地进行保存,然后进行登录 ,注册 登录详细接口请看 这儿,  注册 登录的调用大概如下所示: 
 try {
        //注册一个环信ID
        EMClient.getInstance().createAccount(username, password);
            
        //注册成功进行登录
        PreferenceManager.getInstance().setCurrentUserName(username);
        PreferenceManager.getInstance().setCurrentuserPassword(password);
        login();
    } catch (final HyphenateException e) {
       runOnUiThread(new Runnable() {
               public void run() {
                  int errorCode=e.getErrorCode();
                   if(errorCode==EMError.NETWORK_ERROR){
                    Toast.makeText(getApplicationContext(), getResources().getString(R.string.network_anomalies), Toast.LENGTH_SHORT).show();
      }
   }   
}
 
  public void login() {
 
        //登录已经注册成功的环信ID
        EMClient.getInstance().login(username, password, new EMCallBack() {
            @Override
            public void onSuccess() {
                Log.d(TAG, "login: onSuccess");
                //登录成功进入会议房间
                joinRoom();
            }
            @Override
            public void onProgress(int progress, String status) {
                Log.d(TAG, "login: onProgress");
            }
            @Override
            public void onError(final int code, final String message) {
                Log.d(TAG, "login: onError: " + code);
                runOnUiThread(new Runnable() {
                    public void run() {
                        Toast.makeText(getApplicationContext(), getString(R.string.Login_failed) + message,Toast.LENGTH_SHORT).show();
                    }
                });
            }
        });
    }
登录完成以后,我们可以根据房间名创建并加入房间,主要代码大概如下: EMClient.getInstance().conferenceManager().joinRoom(currentRoomname, currentPassword, conferenceRole,roomConfig, new EMValueCallBack<EMConference>(){
@Override
public void onSuccess(EMConference value) {
EMLog.i(TAG, "join conference success");
Intent intent = new Intent(MainActivity.this, ConferenceActivity.class);
startActivity(intent);
finish();
}
@Override
public void onError(final int error, final String errorMsg) {
EMLog.e(TAG, "join conference failed error " + error + ", msg " + errorMsg);
runOnUiThread(new Runnable() {
@Override
public void run() {
setBtnEnable(true);
if(error == CALL_TALKER_ISFULL) {
takerFullDialogDisplay();
}else{
Toast.makeText(getApplicationContext(), "Join conference failed " + error + " " + errorMsg, Toast.LENGTH_SHORT).show();
}
}
});
}
});
EMClient.getInstance().conferenceManager().joinRoom() API可以根据房间名创建指定会议,当以该房间名命名的会议不存在时候,会直接创建,当会议已经创建好 可以根据正确的房间名和密码加入房间 ,到这一步为止,我们已经成功的创建 并加入会议。
5.加入会议以后我们进入到会议界面,展示从DemoHelper类 EMConferenceListener 中的 onStreamAdded 回调 和 onMemberJoined 获取到的流和主播列表 ,在ConferenceActivity 中实现 EMConferenceListener ,然后直接把 ConferenceActivity 注册监听,用以下方法  EMClient.getInstance().conferenceManager().addConferenceListener(this); 这样就可实现 EMConferenceListener 事件的处理,比如
 主播 进出房间 :
public void onMemberJoined(final EMConferenceMember member);
public void onMemberExited(final EMConferenceMember member);

增加流 移除流:
public void onStreamAdded(final EMConferenceStream stream)
 public void onStreamRemoved(final EMConferenceStream stream)

管理员变更: 
public void onAdminAdded(String streamId) ;  
public void onAdminRemoved(String streamId)

角色变更  用户被踢  谁在说话等各种回调,可以处理各种业务逻辑 ,详细的请参考 项目中的实现 ,最后会附上项目的开源地址。

6 进入会议房间以后如果用户角色为主播可以进行发布视频流 ,观众只能订阅视频流 不能发布视频流 ,可以调用SDK的publish接口发布流,该接口用到了EMStreamParam参数,你可以自由配置,比如是否上传视频,是否上传音频,使用前置或后置摄像头,视频码率,显示视频页面等等,具体实现可以参考 中发布 订阅视频流的内容, 关于以上的代码逻辑如以 如以下: //发布视频流
normalParam = new EMStreamParam();
normalParam.setStreamType(EMConferenceStream.StreamType.NORMAL);
normalParam.setVideoOff(true);
normalParam.setAudioOff(true);

EMClient.getInstance().conferenceManager().publish(normalParam, new EMValueCallBack<String>() {
@Override
public void onSuccess(String value) {
conference.setPubStreamId(value, EMConferenceStream.StreamType.NORMAL);
addOrUpdateStreamList("local-stream", value);

PhoneStateManager.get(ConferenceActivity.this).addStateCallback(phoneStateCallback);
}

@Override
public void onError(int error, String errorMsg) {
EMLog.i(TAG, "publish failed: error=" + error + ", msg=" + errorMsg);
}
});
//订阅其他主播的视频流
private void subscribe(EMConferenceStream stream, EMCallSurfaceView surfaceView) {
EMClient.getInstance().conferenceManager().subscribe(stream, surfaceView, new EMValueCallBack<String>() {
@Override
public void onSuccess(String value) {
}

@Override
public void onError(int error, String errorMsg) {

}
});
}
7.有关上麦 下麦 的逻辑处理,观众可以请求上麦成为主播,主播可以下麦成为观众,上麦 下麦 是利用 EMConferenceAttribute进行处理 ,EMConferenceAttribute  是一个事件广播,广播事件是一个key-value格式,key-value 可以由开发者进行自行定义,增添事件以后 ,服务器会把事件进行广播。会议中成员会收到 onAttributesUpdated回调。例如本项目中的会议上麦 下麦 代码如下所示://上麦申请

EMClient.getInstance().conferenceManager().setConferenceAttribute(
EMClient.getInstance().getCurrentUser(),
"request_tobe_speaker",
new EMValueCallBack<Void>() {
@Override
public void onSuccess(Void value) {
EMLog.i(TAG, "request_tobe_speaker scuessed");

}

@Override
public void onError(int error, String errorMsg) {
EMLog.i(TAG, "request_tobe_speaker failed: error=" + error

}
});

//下麦申请
EMClient.getInstance().conferenceManager().setConferenceAttribute(EMClient.getInstance().getCurrentUser()
, "request_tobe_audience", new EMValueCallBack<Void>() {
@Override
public void onSuccess(Void value) {
EMLog.i(TAG, "request_tobe_audience scuessed");
}

@Override
public void onError(int error, String errorMsg) {
EMLog.i(TAG, "request_tobe_audience failed: error=" + error + ", msg=" + errorMsg);
}
});
 上麦 下麦 请求发出以后 只能由主持人去处理,处理在 EMConferenceListener  的回调 onAttributesUpdated(EMConferenceAttribute attributes) 去处理 ,收到回调以后 解析attributes 然后进行处理请求,处理的过程代码大概如下: EMClient.getInstance().conferenceManager().grantRole(conference.getConferenceId()
, new EMConferenceMember(memName, null, null,null)
, EMConferenceManager.EMConferenceRole.Talker, new EMValueCallBack<String>() {
@Override
public void onSuccess(String value) {
EMLog.i(TAG, " requestTalkerDisplay request_tobe_speaker changeRole success, result: " + value);
dialog.dismiss();
}
@Override
public void onError(int error, String errorMsg) {
EMLog.i(TAG, " requestTalkerDisplay request_tobe_speaker changeRole failed, error: " + error + " - " + errorMsg);

}
});
下麦也是和上麦一样是利用 EMConferenceAttribute进行处理。

9.有关退出会议 销毁会议 普通主播  观众只能退出会议 ,主持人还可以 销毁会议 正在进行中的会议可以进行销毁,退出会议 销毁会议 具体代码如下: EMClient.getInstance().conferenceManager().exitConference(new EMValueCallBack() {
@Override
public void onSuccess(Object value) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "您已成功退出当前会议!", Toast.LENGTH_SHORT).show();
}
});
}

@Override
public void onError(int error, String errorMsg) {
EMLog.i(TAG, "exit conference failed " + error + ", " + errorMsg);
}
});

EMClient.getInstance().conferenceManager().destroyConference(new EMValueCallBack() {
@Override
public void onSuccess(Object value) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "您已成功销毁当前会议!", Toast.LENGTH_SHORT).show();
}
});
EMLog.i(TAG, "finish ConferenceActivity");
finish();
}

尾语
至此 整个 多人音视频会议开发的详细步骤 已经完成 ,虽然比较麻烦 但是每个步骤都很清晰 ,有不太清楚的欢迎大家积极讨论, 附上本项目的github地址:https://github.com/easemob/videocall-android  欢迎大家积极参与 ,谢谢支持。
Demo下载 二维码如下 欢迎大家体验(iOS版和web版下载地址请见:https://www.easemob.com/download/rtc)






  查看全部
今年是不平凡的一年,没错,就是因为疫情,因为疫情原因 ,大家只能呆着家里,严重影响了我们正常的学习 生活 工作,在这种情况下,只能在家办公,这时候大家就会想到线上视频会议,目前很多互联网公司有这个产品,比较出名的就比如 腾讯会议 钉钉 zoom等,用这些是很方便,但是如果能开发自己的视频会议,那会不会更好或者是更有成就感,下面简单介绍这个这个项目,和大概的开发过程。本项目基于环信音视频云来完成,实现的主要功能有:
  •   创建会议、删除会议、获取指定会议室详情、加入会议室、退出会议室等关于会议的管理 ;
  •   获取会议室参会人名列表、踢人,设置观众为主播,设置主播为观众等关于会议室的人员管理;
  •   共享桌面(web端);

 三个端的实现:Android,iOS,Web

上面这些功能在项目中都已经实现。还有水印 ,变声等高级功能在环信音视频SDK的接口内部都已经封装好,本项目没有实现 ,大家可以自行去实现。有关多人音视频功能更详细的介绍大家可以参考:这儿。多人音视频实现的实现主要有以下一些场景:社交交友,远程心理咨询、远程医疗、一对一在线教育、远程视频辅助等。咳咳 ,接下来就是纯干货了,给大家介绍我是如何一步步开发出一个完整的多人音视频app。
 
项目截图
 
首先给大家展示下项目运行的效果图,会议界面 主窗口是一个大的 RelativeLayout ,最下面的那一排排小窗口是的实现方法是HorizontalScrollView加上一个开源的组件 com.jaouan.compoundlayout.RadioLayoutGroup 实现的,点击下面的小窗口后,可以 把小窗口的视频流显示在大屏上,具体是调用 updateRemoteSurfaceView(String streamId, EMCallSurfaceView remoteView)来更新SurfaceView,具体的细节大家可以看看代码里面的实现 最后会公布代码开源地址。

20200410140627956.jpg


20200410140855852.jpg


20200410141055394.jpg


准备工作
    大家得下载安装Android Studio,配置好Android 开发环境,怎么详细配置我就在这不再细说了 网上有很多的教程,大家自己可以找找看,然后大家可以看看环信多人音视频会议的主要功能和一些基本概念介绍。
集成 
  1. 首先大家会想问怎么调用环信的SDK ,大家可以使用 远程依赖SDK包,建议大家用最新版本的远程依赖:
     com.hyphenate:hyphenate-sdk:3.6.6 ,依赖包可以放在 build.gradle里面的 dependencies 选项下面,如下图所示
2020040917363212.png


2.其次怎么使用环信的appkey ,可以在环信音视频云后台注册一个 账号申请appkey ,可以参考这里 ,获取到  appkey 以后添加到AndroidManifest.xml中 ,如下图所示:

20200409213959916.png


3.经过以上两个重要的前期配置准备 ,接下来我们就可以开始进行代码开发了,首先我们先创建一个项目的DemoApplication类和      DemoHelper类,DemoApplication 类和DemoHelper类都是一个单例类 ,DemoApplication 主要功能就是进行DemoHelper 的初始化,而DemoHelper里面主要是主要有一些option 配置和EMClient 进行初始化,代码如下所示:
public void init(Context context) {
EMOptions options = initChatOptions(context);
EMClient.getInstance().init(context, options);
PreferenceManager.init(context);
}

  DemoHelper还有一个重要的功能就是设置  EMConferenceListener 进行会议监听,有关 EMConferenceListener的类的详细介绍 ,通过这个监听可以再加入会议的时候获取到已经在会议中的流和主播信息,分别是通过其中以下两个回调获取:
@Override 
public void onMemberJoined(EMConferenceMember member){

}

@Override
public void onStreamAdded(EMConferenceStream stream){

}

4.DemoApplication类完成以后,接下来就是怎么去登陆 环信IM 账号和 创建加入会议房间了,首次安装的时候都没有账号,我们使用的办法是自动注册一个账号 在本地进行保存,然后进行登录 ,注册 登录详细接口请看 这儿,  注册 登录的调用大概如下所示: 
 try {
        //注册一个环信ID
        EMClient.getInstance().createAccount(username, password);
            
        //注册成功进行登录
        PreferenceManager.getInstance().setCurrentUserName(username);
        PreferenceManager.getInstance().setCurrentuserPassword(password);
        login();
    } catch (final HyphenateException e) {
       runOnUiThread(new Runnable() {
               public void run() {
                  int errorCode=e.getErrorCode();
                   if(errorCode==EMError.NETWORK_ERROR){
                    Toast.makeText(getApplicationContext(), getResources().getString(R.string.network_anomalies), Toast.LENGTH_SHORT).show();
      }
   }   
}
 
  public void login() {
 
        //登录已经注册成功的环信ID
        EMClient.getInstance().login(username, password, new EMCallBack() {
            @Override
            public void onSuccess() {
                Log.d(TAG, "login: onSuccess");
                //登录成功进入会议房间
                joinRoom();
            }
            @Override
            public void onProgress(int progress, String status) {
                Log.d(TAG, "login: onProgress");
            }
            @Override
            public void onError(final int code, final String message) {
                Log.d(TAG, "login: onError: " + code);
                runOnUiThread(new Runnable() {
                    public void run() {
                        Toast.makeText(getApplicationContext(), getString(R.string.Login_failed) + message,Toast.LENGTH_SHORT).show();
                    }
                });
            }
        });
    }
登录完成以后,我们可以根据房间名创建并加入房间,主要代码大概如下:
 EMClient.getInstance().conferenceManager().joinRoom(currentRoomname, currentPassword, conferenceRole,roomConfig, new EMValueCallBack<EMConference>(){
@Override
public void onSuccess(EMConference value) {
EMLog.i(TAG, "join conference success");
Intent intent = new Intent(MainActivity.this, ConferenceActivity.class);
startActivity(intent);
finish();
}
@Override
public void onError(final int error, final String errorMsg) {
EMLog.e(TAG, "join conference failed error " + error + ", msg " + errorMsg);
runOnUiThread(new Runnable() {
@Override
public void run() {
setBtnEnable(true);
if(error == CALL_TALKER_ISFULL) {
takerFullDialogDisplay();
}else{
Toast.makeText(getApplicationContext(), "Join conference failed " + error + " " + errorMsg, Toast.LENGTH_SHORT).show();
}
}
});
}
});

EMClient.getInstance().conferenceManager().joinRoom() API可以根据房间名创建指定会议,当以该房间名命名的会议不存在时候,会直接创建,当会议已经创建好 可以根据正确的房间名和密码加入房间 ,到这一步为止,我们已经成功的创建 并加入会议。
5.加入会议以后我们进入到会议界面,展示从DemoHelper类 EMConferenceListener 中的 onStreamAdded 回调 和 onMemberJoined 获取到的流和主播列表 ,在ConferenceActivity 中实现 EMConferenceListener ,然后直接把 ConferenceActivity 注册监听,用以下方法  EMClient.getInstance().conferenceManager().addConferenceListener(this); 这样就可实现 EMConferenceListener 事件的处理,比如
 主播 进出房间 :
public void onMemberJoined(final EMConferenceMember member);
public void onMemberExited(final EMConferenceMember member);

增加流 移除流:
public void onStreamAdded(final EMConferenceStream stream)
 public void onStreamRemoved(final EMConferenceStream stream)

管理员变更: 
public void onAdminAdded(String streamId) ;  
public void onAdminRemoved(String streamId)

角色变更  用户被踢  谁在说话等各种回调,可以处理各种业务逻辑 ,详细的请参考 项目中的实现 ,最后会附上项目的开源地址。

6 进入会议房间以后如果用户角色为主播可以进行发布视频流 ,观众只能订阅视频流 不能发布视频流 ,可以调用SDK的publish接口发布流,该接口用到了EMStreamParam参数,你可以自由配置,比如是否上传视频,是否上传音频,使用前置或后置摄像头,视频码率,显示视频页面等等,具体实现可以参考 中发布 订阅视频流的内容, 关于以上的代码逻辑如以 如以下:
 //发布视频流
normalParam = new EMStreamParam();
normalParam.setStreamType(EMConferenceStream.StreamType.NORMAL);
normalParam.setVideoOff(true);
normalParam.setAudioOff(true);

EMClient.getInstance().conferenceManager().publish(normalParam, new EMValueCallBack<String>() {
@Override
public void onSuccess(String value) {
conference.setPubStreamId(value, EMConferenceStream.StreamType.NORMAL);
addOrUpdateStreamList("local-stream", value);

PhoneStateManager.get(ConferenceActivity.this).addStateCallback(phoneStateCallback);
}

@Override
public void onError(int error, String errorMsg) {
EMLog.i(TAG, "publish failed: error=" + error + ", msg=" + errorMsg);
}
});
//订阅其他主播的视频流
private void subscribe(EMConferenceStream stream, EMCallSurfaceView surfaceView) {
EMClient.getInstance().conferenceManager().subscribe(stream, surfaceView, new EMValueCallBack<String>() {
@Override
public void onSuccess(String value) {
}

@Override
public void onError(int error, String errorMsg) {

}
});
}

7.有关上麦 下麦 的逻辑处理,观众可以请求上麦成为主播,主播可以下麦成为观众,上麦 下麦 是利用 EMConferenceAttribute进行处理 ,EMConferenceAttribute  是一个事件广播,广播事件是一个key-value格式,key-value 可以由开发者进行自行定义,增添事件以后 ,服务器会把事件进行广播。会议中成员会收到 onAttributesUpdated回调。例如本项目中的会议上麦 下麦 代码如下所示:
//上麦申请  

EMClient.getInstance().conferenceManager().setConferenceAttribute(
EMClient.getInstance().getCurrentUser(),
"request_tobe_speaker",
new EMValueCallBack<Void>() {
@Override
public void onSuccess(Void value) {
EMLog.i(TAG, "request_tobe_speaker scuessed");

}

@Override
public void onError(int error, String errorMsg) {
EMLog.i(TAG, "request_tobe_speaker failed: error=" + error

}
});

//下麦申请
EMClient.getInstance().conferenceManager().setConferenceAttribute(EMClient.getInstance().getCurrentUser()
, "request_tobe_audience", new EMValueCallBack<Void>() {
@Override
public void onSuccess(Void value) {
EMLog.i(TAG, "request_tobe_audience scuessed");
}

@Override
public void onError(int error, String errorMsg) {
EMLog.i(TAG, "request_tobe_audience failed: error=" + error + ", msg=" + errorMsg);
}
});

 上麦 下麦 请求发出以后 只能由主持人去处理,处理在 EMConferenceListener  的回调 onAttributesUpdated(EMConferenceAttribute attributes) 去处理 ,收到回调以后 解析attributes 然后进行处理请求,处理的过程代码大概如下:
   EMClient.getInstance().conferenceManager().grantRole(conference.getConferenceId()
, new EMConferenceMember(memName, null, null,null)
, EMConferenceManager.EMConferenceRole.Talker, new EMValueCallBack<String>() {
@Override
public void onSuccess(String value) {
EMLog.i(TAG, " requestTalkerDisplay request_tobe_speaker changeRole success, result: " + value);
dialog.dismiss();
}
@Override
public void onError(int error, String errorMsg) {
EMLog.i(TAG, " requestTalkerDisplay request_tobe_speaker changeRole failed, error: " + error + " - " + errorMsg);

}
});

下麦也是和上麦一样是利用 EMConferenceAttribute进行处理。

9.有关退出会议 销毁会议 普通主播  观众只能退出会议 ,主持人还可以 销毁会议 正在进行中的会议可以进行销毁,退出会议 销毁会议 具体代码如下:
 EMClient.getInstance().conferenceManager().exitConference(new EMValueCallBack() {
@Override
public void onSuccess(Object value) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "您已成功退出当前会议!", Toast.LENGTH_SHORT).show();
}
});
}

@Override
public void onError(int error, String errorMsg) {
EMLog.i(TAG, "exit conference failed " + error + ", " + errorMsg);
}
});

EMClient.getInstance().conferenceManager().destroyConference(new EMValueCallBack() {
@Override
public void onSuccess(Object value) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "您已成功销毁当前会议!", Toast.LENGTH_SHORT).show();
}
});
EMLog.i(TAG, "finish ConferenceActivity");
finish();
}

尾语
至此 整个 多人音视频会议开发的详细步骤 已经完成 ,虽然比较麻烦 但是每个步骤都很清晰 ,有不太清楚的欢迎大家积极讨论, 附上本项目的github地址:https://github.com/easemob/videocall-android  欢迎大家积极参与 ,谢谢支持。
Demo下载 二维码如下 欢迎大家体验(iOS版和web版下载地址请见:https://www.easemob.com/download/rtc)


20200410142228530.png

 
0
评论

史上最完整的官方Oracle OCP中文文教材,快来下载吧!! 下载

beyond 发表了文章 • 1943 次浏览 • 2019-05-09 16:18 • 来自相关话题

内含文件:
1、Oracle Database 11g:SQL 基础 学生指南第1 册 
2、Oracle Database 11g:SQL 基础 学生指南第2 册 
3、Oracle Database 11g:数据库管理- 课堂练习I 学生指南第1 册
4、Oracle Database 11g:数据库管理- 课堂练习II 学生指南第1 册 
5、Oracle Database 11g:数据库管理- 课堂练习I 学生指南第2 册 
6、Oracle Database 11g:数据库管理- 课堂练习II 学生指南第2 册 
7、Oracle Da等等 查看全部
内含文件:
1、Oracle Database 11g:SQL 基础 学生指南第1 册 
2、Oracle Database 11g:SQL 基础 学生指南第2 册 
3、Oracle Database 11g:数据库管理- 课堂练习I 学生指南第1 册
4、Oracle Database 11g:数据库管理- 课堂练习II 学生指南第1 册 
5、Oracle Database 11g:数据库管理- 课堂练习I 学生指南第2 册 
6、Oracle Database 11g:数据库管理- 课堂练习II 学生指南第2 册 
7、Oracle Da等等