基于環(huán)信4小時開發(fā)一個視頻會議APP【附源碼】(視頻會議軟件源碼)

      網(wǎng)友投稿 1172 2022-05-30

      本項目基于環(huán)信音視頻云來完成,實現(xiàn)的主要功能有:

      創(chuàng)建會議、刪除會議、獲取指定會議室詳情、加入會議室、退出會議室等關(guān)于會議的管理 ;

      獲取會議室參會人名列表、踢人,設(shè)置觀眾為主播,設(shè)置主播為觀眾等關(guān)于會議室的人員管理;

      共享桌面(web端);

      三個端的實現(xiàn):Android,iOS,Web

      基于環(huán)信4小時開發(fā)一個視頻會議APP【附源碼】(視頻會議軟件源碼)

      上面這些功能在項目中都已經(jīng)實現(xiàn)。還有水印 ,變聲等高級功能在環(huán)信音視頻SDK的接口內(nèi)部都已經(jīng)封裝好,本項目沒有實現(xiàn) ,大家可以自行去實現(xiàn)。有關(guān)多人音視頻功能更詳細(xì)的介紹大家可以參考:這兒。多人音視頻實現(xiàn)的實現(xiàn)主要有以下一些場景:社交交友,遠(yuǎn)程心理咨詢、遠(yuǎn)程醫(yī)療、一對一在線教育、遠(yuǎn)程視頻輔助等。咳咳 ,接下來就是純干貨了,給大家介紹我是如何一步步開發(fā)出一個完整的多人音視頻app。

      項目截圖:

      首先給大家展示下項目運行的效果圖,會議界面 主窗口是一個大的 RelativeLayout ,最下面的那一排排小窗口是的實現(xiàn)方法是HorizontalScrollView加上一個開源的組件 com.jaouan.compoundlayout.RadioLayoutGroup 實現(xiàn)的,點擊下面的小窗口后,可以 把小窗口的視頻流顯示在大屏上,具體是調(diào)用 updateRemoteSurfaceView(String streamId, EMCallSurfaceView remoteView)來更新SurfaceView,具體的細(xì)節(jié)大家可以看看代碼里面的實現(xiàn) 最后會公布代碼開源地址。

      準(zhǔn)備工作

      大家得下載安裝Android Studio,配置好Android 開發(fā)環(huán)境,怎么詳細(xì)配置我就在這不再細(xì)說了 網(wǎng)上有很多的教程,大家自己可以找找看,然后大家可以看看環(huán)信多人音視頻會議的主要功能和一些基本概念介紹。

      集成

      1. 首先大家會想問怎么調(diào)用環(huán)信的SDK ,大家可以使用 遠(yuǎn)程依賴SDK包,建議大家用最新版本的遠(yuǎn)程依賴:

      com.hyphenate:hyphenate-sdk:3.6.6 ,依賴包可以放在 build.gradle里面的 dependencies 選項下面,如下圖所示:

      2.其次怎么使用環(huán)信的appkey ,可以在環(huán)信 console 后臺注冊一個 賬號申請appkey ,可以參考這里 ,獲取到 ?appkey 以后添加到AndroidManifest.xml中 ,如下圖所示:

      3.經(jīng)過以上兩個重要的前期配置準(zhǔn)備 ,接下來我們就可以開始進(jìn)行代碼開發(fā)了,首先我們先創(chuàng)建一個項目的DemoApplication類和 ? ? ?DemoHelper類,DemoApplication 類和DemoHelper類都是一個單例類 ,DemoApplication 主要功能就是進(jìn)行DemoHelper ? ? ?的初始化,而DemoHelper里面主要是主要有一些option 配置和EMClient 進(jìn)行初始化,代碼如下所示:

      public?void?init(Context?context)?{ ????????????????EMOptions?options?=?initChatOptions(context); EMClient.getInstance().init(context,?options); PreferenceManager.init(context); }

      DemoHelper還有一個重要的功能就是設(shè)置 ?EMConferenceListener 進(jìn)行會議監(jiān)聽,有關(guān) EMConferenceListener的類的詳細(xì)介紹 ,通過這個監(jiān)聽可以再加入會議的時候獲取到已經(jīng)在會議中的流和主播信息,分別是通過其中以下兩個回調(diào)獲取:

      @Override? public?void?onMemberJoined(EMConferenceMember?member){ ? } ? @Override? public?void?onStreamAdded(EMConferenceStream?stream){ ? }

      4.DemoApplication類完成以后,接下來就是怎么去登陸 環(huán)信IM 賬號和 創(chuàng)建加入會議房間了,首次安裝的時候都沒有賬號,我們使用的辦法是自動注冊一個賬號 在本地進(jìn)行保存,然后進(jìn)行登錄 ,注冊 登錄詳細(xì)接口請看 這兒, ?注冊 登錄的調(diào)用大概如下所示:

      try?{ ????????//注冊一個環(huán)信ID ????????EMClient.getInstance().createAccount(username,?password); ???????????? ????????//注冊成功進(jìn)行登錄 ????????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(); ??????} ???}??? }

      EMClient.getInstance().conferenceManager().joinRoom(currentRoomname,?currentPassword,?conferenceRole,roomConfig,?new?EMValueCallBack(){ ????????????????????@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(); ????????????????????????????????} ????????????????????????????} ????????????????????????}); ????????????????????} ????????????????});

      登錄完成以后,我們可以根據(jù)房間名創(chuàng)建并加入房間,主要代碼大概如下:

      EMClient.getInstance().conferenceManager().joinRoom(currentRoomname,?currentPassword,?conferenceRole,roomConfig,?new?EMValueCallBack(){ ????????????????????@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可以根據(jù)房間名創(chuàng)建指定會議,當(dāng)以該房間名命名的會議不存在時候,會直接創(chuàng)建,當(dāng)會議已經(jīng)創(chuàng)建好 可以根據(jù)正確的房間名和密碼加入房間 ,到這一步為止,我們已經(jīng)成功的創(chuàng)建 并加入會議。

      5.加入會議以后我們進(jìn)入到會議界面,展示從DemoHelper類 EMConferenceListener 中的 onStreamAdded 回調(diào) 和 onMemberJoined 獲取到的流和主播列表 ,在ConferenceActivity 中實現(xiàn) EMConferenceListener ,然后直接把 ConferenceActivity 注冊監(jiān)聽,用以下方法 ?EMClient.getInstance().conferenceManager().addConferenceListener(this); 這樣就可實現(xiàn) EMConferenceListener 事件的處理,比如 主播 進(jìn)出房間 :

      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)

      角色變更 ?用戶被踢 ?誰在說話等各種回調(diào),可以處理各種業(yè)務(wù)邏輯 ,詳細(xì)的請參考 項目中的實現(xiàn) ,最后會附上項目的開源地址。

      6 進(jìn)入會議房間以后如果用戶角色為主播可以進(jìn)行發(fā)布視頻流 ,觀眾只能訂閱視頻流 不能發(fā)布視頻流 ,可以調(diào)用SDK的publish接口發(fā)布流,該接口用到了EMStreamParam參數(shù),你可以自由配置,比如是否上傳視頻,是否上傳音頻,使用前置或后置攝像頭,視頻碼率,顯示視頻頁面等等,具體實現(xiàn)可以參考 中發(fā)布 訂閱視頻流的內(nèi)容, 關(guān)于以上的代碼邏輯如以 如以下:

      //發(fā)布視頻流 ?normalParam?=?new?EMStreamParam(); ?normalParam.setStreamType(EMConferenceStream.StreamType.NORMAL); ?normalParam.setVideoOff(true); ?normalParam.setAudioOff(true); ? EMClient.getInstance().conferenceManager().publish(normalParam,?new?EMValueCallBack()?{ ????????????@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()?{ ????????????@Override ????????????public?void?onSuccess(String?value)?{ ????????????} ? ????????????@Override ????????????public?void?onError(int?error,?String?errorMsg)?{ ? ????????????} ????????}); ????}

      7.有關(guān)上麥 下麥 的邏輯處理,觀眾可以請求上麥成為主播,主播可以下麥成為觀眾,上麥 下麥 是利用 EMConferenceAttribute進(jìn)行處理 ,EMConferenceAttribute ?是一個事件廣播,廣播事件是一個key-value格式,key-value 可以由開發(fā)者進(jìn)行自行定義,增添事件以后 ,服務(wù)器會把事件進(jìn)行廣播。會議中成員會收到 onAttributesUpdated回調(diào)。例如本項目中的會議上麥 下麥 代碼如下所示:

      //上麥申請?? ? EMClient.getInstance().conferenceManager().setConferenceAttribute( ????EMClient.getInstance().getCurrentUser(), ????"request_tobe_speaker",? ????new?EMValueCallBack()?{ ?????????????????@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()?{ ????????????????????????????@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); ????????????????????????????} ????????????????????????});

      上麥 下麥 請求發(fā)出以后 只能由主持人去處理,處理在 EMConferenceListener ?的回調(diào) onAttributesUpdated(EMConferenceAttribute[] attributes) 去處理 ,收到回調(diào)以后 解析attributes 然后進(jìn)行處理請求,處理的過程代碼大概如下:

      EMClient.getInstance().conferenceManager().grantRole(conference.getConferenceId() ????????????????????????,?new?EMConferenceMember(memName,?null,?null,null) ????????????????????????,?EMConferenceManager.EMConferenceRole.Talker,?new?EMValueCallBack()?{ ????????????????????????????@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進(jìn)行處理。

      9.有關(guān)退出會議 銷毀會議 普通主播 ?觀眾只能退出會議 ,主持人還可以 銷毀會議 正在進(jìn)行中的會議可以進(jìn)行銷毀,退出會議 銷毀會議 具體代碼如下:

      EMClient.getInstance().conferenceManager().exitConference(new?EMValueCallBack()?{ ????????????@Override ????????????public?void?onSuccess(Object?value)?{ ????????????????runOnUiThread(new?Runnable()?{ ????????????????????@Override ????????????????????public?void?run()?{ ????????????????????????Toast.makeText(getApplicationContext(),?"您已成功退出當(dāng)前會議!",?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(),?"您已成功銷毀當(dāng)前會議!",?Toast.LENGTH_SHORT).show(); ????????????????????} ????????????????}); ????????????????EMLog.i(TAG,?"finish?ConferenceActivity"); ????????????????finish(); ????????????}

      尾語

      至此整個多人音視頻會議開發(fā)的詳細(xì)步驟已經(jīng)完成 ,雖然比較麻煩 但是每個步驟都很清晰 ,有不太清楚的歡迎大家積極討論, 附上本項目的github地址:https://github.com/easemob/videocall-android ?歡迎大家積極參與 ,謝謝支持。

      互聯(lián)網(wǎng)音視頻

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:【技術(shù)補(bǔ)給站】第11期:左手自研,右手開源,技術(shù)揭秘華為云如何領(lǐng)跑容器市場
      下一篇:excel制作庫存表的方法步驟(excel如何制作庫存表)
      相關(guān)文章
      色偷偷尼玛图亚洲综合| 亚洲av日韩av高潮潮喷无码| 亚洲日本va午夜中文字幕一区| 相泽亚洲一区中文字幕| 亚洲精品人成无码中文毛片| 亚洲?V无码成人精品区日韩| 国产成人精品亚洲| 亚洲高清国产拍精品青青草原| 另类图片亚洲校园小说区| 丰满亚洲大尺度无码无码专线| 亚洲成av人在线观看网站| 亚洲av日韩精品久久久久久a| 亚洲AV无码专区国产乱码不卡| 亚洲AV无码一区二区三区电影| 亚洲av无码有乱码在线观看| 综合偷自拍亚洲乱中文字幕| 亚洲A丁香五香天堂网| 亚洲综合精品网站在线观看| 中文字幕不卡亚洲| 亚洲国产综合无码一区| 精品亚洲综合在线第一区| 亚洲男人第一av网站| 亚洲精品人成电影网| 亚洲色欲色欲www| 亚洲欧洲国产综合AV无码久久| 亚洲а∨精品天堂在线| 亚洲国产成人爱av在线播放| a级亚洲片精品久久久久久久| 亚洲人精品午夜射精日韩| 亚洲今日精彩视频| 亚洲精品人成电影网| 亚洲日韩一区二区一无码| 亚洲AV日韩AV无码污污网站| 亚洲欧洲久久av| 亚洲av最新在线网址| 亚洲日韩中文字幕天堂不卡 | 亚洲人成免费网站| 亚洲熟妇AV乱码在线观看| jizzjizz亚洲日本少妇| 久久青青草原亚洲av无码| 亚洲AV无码国产精品色午友在线|