国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Android端實(shí)現(xiàn)多人音視頻聊天應(yīng)用(二):實(shí)現(xiàn)多人通話

The question / 1970人閱讀

摘要:我們先實(shí)現(xiàn)一個(gè)瀑布流瀑布流的實(shí)現(xiàn)方式很多,本文采用結(jié)合的來(lái)實(shí)現(xiàn)。有了一個(gè)可用的瀑布流之后,下面我們就可以實(shí)現(xiàn)動(dòng)態(tài)聊天窗了動(dòng)態(tài)聊天窗的要點(diǎn)在于的大小由視頻的寬高比決定,因此及其對(duì)應(yīng)的就該注意不要寫死尺寸。

作者:聲網(wǎng)用戶,資深A(yù)ndroid工程師吳東洋
本系列文章分享了基于Agora SDK 2.1實(shí)現(xiàn)多人視頻通話的實(shí)踐經(jīng)驗(yàn)。

在上一篇《Android 多人視頻聊天應(yīng)用的開(kāi)發(fā)(一)一對(duì)一聊天》中我們學(xué)習(xí)了如何使用聲網(wǎng)Agora SDK 進(jìn)行一對(duì)一的聊天,本篇主要討論如何使用 Agora SDK 進(jìn)行多人聊天。主要需要實(shí)現(xiàn)以下功能:

上一篇已經(jīng)實(shí)現(xiàn)過(guò)的聊天功能

隨著加入人數(shù)和他們的手機(jī)攝像頭分辨率的變化,顯示不同的UI,即所謂的“分屏”

點(diǎn)擊分屏中的小窗,可以放大顯示該聊天窗

分屏

根據(jù)前期技術(shù)調(diào)研,分屏顯示最好的方式是采用瀑布流結(jié)合動(dòng)態(tài)聊天窗實(shí)現(xiàn),這樣比較方便的能夠適應(yīng)UI的變化。所謂瀑布流,就是目前比較流行的一種列表布局,會(huì)在界面上呈現(xiàn)參差不齊的多欄布局。我們先實(shí)現(xiàn)一個(gè)瀑布流:

瀑布流的實(shí)現(xiàn)方式很多,本文采用結(jié)合 GridLayoutManager的RecyclerView 來(lái)實(shí)現(xiàn)。我們首先自定義一個(gè) RecyclerView,命名為 GridVideoViewContainer。核心代碼如下:

int count = uids.size();
if (count <= 2) { 
    // 只有本地視頻或聊天室內(nèi)只有另外一個(gè)人
    this.setLayoutManager(new LinearLayoutManager(activity.getApplicationContext(), orientation, false));
} else if (count > 2) {
    // 多人聊天室
    int itemSpanCount = getNearestSqrt(count);
    this.setLayoutManager(new GridLayoutManager(activity.getApplicationContext(), itemSpanCount, orientation, false));
}

根據(jù)上面的代碼可以看出,在聊天室里只有自己的本地視頻或者只有另外一個(gè)人的時(shí)候,采用 LinearLayoutManager,這樣的布局其實(shí)與前文的一對(duì)一聊天類似;而在真正意義的多人聊天室里,則采用 GridLayoutManager 實(shí)現(xiàn)瀑布流,其中 itemSpanCount 就是瀑布流的列數(shù)。

有了一個(gè)可用的瀑布流之后,下面我們就可以實(shí)現(xiàn)動(dòng)態(tài)聊天窗了:
動(dòng)態(tài)聊天窗的要點(diǎn)在于 item 的大小由視頻的寬高比決定,因此 Adapter 及其對(duì)應(yīng)的 layout 就該注意不要寫死尺寸。在 Adapter 里控制 item 具體尺寸的代碼如下:

if (force || mItemWidth == 0 || mItemHeight == 0) {
    WindowManager windowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
    DisplayMetrics outMetrics = new DisplayMetrics();
    windowManager.getDefaultDisplay().getMetrics(outMetrics);

    int count = uids.size();
    int DividerX = 1;
    int DividerY = 1;

    if (count == 2) {
        DividerY = 2;
    } else if (count >= 3) {
        DividerX = getNearestSqrt(count);
        DividerY = (int) Math.ceil(count * 1.f / DividerX);
    }

    int width = outMetrics.widthPixels;
    int height = outMetrics.heightPixels;

    if (width > height) {
        mItemWidth = width / DividerY;
        mItemHeight = height / DividerX;
    } else {
        mItemWidth = width / DividerX;
        mItemHeight = height / DividerY;
    }
}

以上代碼根據(jù)視頻的數(shù)量確定了列數(shù)和行數(shù),然后根據(jù)列數(shù)和屏幕寬度確定了視頻的寬度,接著根據(jù)視頻的寬高比和視頻寬度確定了視頻高度。同時(shí)也考慮了手機(jī)的橫豎屏情況(就是if (width > height)這行代碼)。

該 Adapter 對(duì)應(yīng)的 layout 的代碼如下:



    

    

    

        
    

我們可以看到,layout 中有關(guān)尺寸的屬性都 是wrap_content,這就使得 item 大小隨視頻寬高比變化成為可能。

把分屏的布局寫好之后,我們就可以在每一個(gè) item 上播放聊天視頻了。

播放聊天視頻

在 Agora SDK 中一個(gè)遠(yuǎn)程視頻的顯示只和該用戶的 UID 有關(guān),所以使用的數(shù)據(jù)源只需要簡(jiǎn)單定義為包含 UID 和對(duì)應(yīng)的 SurfaceView 即可,就像這樣:

 private final HashMap mUidsList = new HashMap<>();

每當(dāng)有人加入了我們的聊天頻道,都會(huì)觸發(fā)onFirstRemoteVideoDecoded(int uid, int width, int height, int elapsed)方法,第一個(gè) uid 就是他們的 UID;接下來(lái)我們要為每個(gè) item 新建一個(gè) SurfaceView 并為其創(chuàng)建渲染視圖,最后將它們加入剛才創(chuàng)建好的mUidsList里并調(diào)用setupRemoteVideo( VideoCanvas remote )方法播放這個(gè)聊天視頻。這個(gè)過(guò)程的完整代碼如下:

@Override
public void onFirstRemoteVideoDecoded(int uid, int width, int height, int elapsed) {
   doRenderRemoteUi(uid);
}

private void doRenderRemoteUi(final int uid) {
   runOnUiThread(new Runnable() {
       @Override
       public void run() {
           if (isFinishing()) {
               return;
           }

           if (mUidsList.containsKey(uid)) {
               return;
           }

           SurfaceView surfaceV = RtcEngine.CreateRendererView(getApplicationContext());
           mUidsList.put(uid, surfaceV);

           boolean useDefaultLayout = mLayoutType == LAYOUT_TYPE_DEFAULT;

           surfaceV.setZOrderOnTop(true);
           surfaceV.setZOrderMediaOverlay(true);

           rtcEngine().setupRemoteVideo(new VideoCanvas(surfaceV, VideoCanvas.RENDER_MODE_HIDDEN, uid));

           if (useDefaultLayout) {
               log.debug("doRenderRemoteUi LAYOUT_TYPE_DEFAULT " + (uid & 0xFFFFFFFFL));
               switchToDefaultVideoView();
           } else {
               int bigBgUid = mSmallVideoViewAdapter == null ? uid : mSmallVideoViewAdapter.getExceptedUid();
               log.debug("doRenderRemoteUi LAYOUT_TYPE_SMALL " + (uid & 0xFFFFFFFFL) + " " + (bigBgUid & 0xFFFFFFFFL));
               switchToSmallVideoView(bigBgUid);
           }
       }
   });
}

以上代碼與前文中播放一對(duì)一視頻的代碼如出一撤,但是細(xì)心的讀者可能已經(jīng)發(fā)現(xiàn)我們并沒(méi)有將生成的 SurfaceView 放在界面里,這正是與一對(duì)一視頻的不同之處:我們要在一個(gè)抽象的 VideoViewAdapter 類里將 SurfaceView 放出來(lái),關(guān)鍵代碼如下:

SurfaceView target = user.mView;
VideoViewAdapterUtil.stripView(target);
holderView.addView(target, 0, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));

一般 Android 工程師看見(jiàn) holderView 就明白這是 ViewHolder 的 layout 的根 layout 了,而 user 是哪兒來(lái)的,詳見(jiàn)文末的代碼,文中不做贅述。

這樣在多人聊天的時(shí)候我們就能使用分屏的方式播放用戶聊天視頻了,如果想放大某一個(gè)用戶的視頻該怎么辦呢?

全屏和小窗

當(dāng)用戶雙擊某一個(gè) item 的時(shí)候,他希望對(duì)應(yīng)的視頻能夠全屏顯示,而其他的視頻則變成小窗口,那么我們先定義一個(gè)雙擊事件接口:

public interface VideoViewEventListener {
    void onItemDoubleClick(View v, Object item);
}
具體實(shí)現(xiàn)方式如下:
mGridVideoViewContainer.setItemEventHandler(new VideoViewEventListener() {
    @Override
    public void onItemDoubleClick(View v, Object item) {
        log.debug("onItemDoubleClick " + v + " " + item + " " + mLayoutType);

        if (mUidsList.size() < 2) {
            return;
        }

        UserStatusData user = (UserStatusData) item;
        int uid = (user.mUid == 0) ? config().mUid : user.mUid;

        if (mLayoutType == LAYOUT_TYPE_DEFAULT && mUidsList.size() != 1) {
            switchToSmallVideoView(uid);
        } else {
            switchToDefaultVideoView();
        }
    }
});

將被選中的視頻全屏播放的方法很容易理解,我們只看生成小窗列表的方法:

private void switchToSmallVideoView(int bigBgUid) {
    HashMap slice = new HashMap<>(1);
    slice.put(bigBgUid, mUidsList.get(bigBgUid));
    Iterator iterator = mUidsList.values().iterator();
    while (iterator.hasNext()) {
        SurfaceView s = iterator.next();
        s.setZOrderOnTop(true);
        s.setZOrderMediaOverlay(true);
    }

    mUidsList.get(bigBgUid).setZOrderOnTop(false);
    mUidsList.get(bigBgUid).setZOrderMediaOverlay(false);

    mGridVideoViewContainer.initViewContainer(this, bigBgUid, slice, mIsLandscape);

    bindToSmallVideoView(bigBgUid);

    mLayoutType = LAYOUT_TYPE_SMALL;

    requestRemoteStreamType(mUidsList.size());
}

小窗列表要注意移除全屏的那個(gè) UID,此外一切都和正常瀑布流視圖相同,包括雙擊小窗的item將其全屏播放。

到了這里我們就已經(jīng)使用 Agora SDK 完成了一個(gè)有基本功能的簡(jiǎn)單多人聊天 demo,要產(chǎn)品化還有很多的東西要做,在這里先做一個(gè)簡(jiǎn)單的總結(jié)吧!

總結(jié)

聲網(wǎng)Agora 提供了高質(zhì)量的視頻通信 SDK,不僅覆蓋了主流的操作系統(tǒng),集成效率也比較高,而且還支持包括聊天,會(huì)議,直播等功能在內(nèi)的多個(gè)模式的視頻通話。SDK 中 API 設(shè)計(jì)基本能夠滿足大部分的開(kāi)發(fā)需要,而且隱藏了底層開(kāi)發(fā),只需要提供 SurfaceView 和 UID 即可播放視頻,這樣對(duì)于 App 層的開(kāi)發(fā)者來(lái)說(shuō)十分友好。非常適合有視頻聊天開(kāi)發(fā)需求的開(kāi)發(fā)者。在視頻領(lǐng)域創(chuàng)業(yè)大爆發(fā)的今天,建議更多的想要從事該領(lǐng)域的開(kāi)發(fā)者可以嘗試下。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/69135.html

相關(guān)文章

  • Android實(shí)現(xiàn)多人視頻聊天應(yīng)用(一)

    作者:聲網(wǎng)Agora用戶,資深A(yù)ndroid開(kāi)發(fā)者吳東洋。本系列文章分享了基于Agora SDK 2.1實(shí)現(xiàn)多人視頻通話的實(shí)踐經(jīng)驗(yàn)。 自從2016年,鼓吹互聯(lián)網(wǎng)寒冬的論調(diào)甚囂塵上,2017年亦有愈演愈烈之勢(shì)。但連麥直播、在線抓娃娃、直播問(wèn)答、遠(yuǎn)程狼人殺等類型的項(xiàng)目卻異軍突起,成了投資人的風(fēng)口,創(chuàng)業(yè)者的藍(lán)海和用戶的必裝App,而這些方向的項(xiàng)目都有一個(gè)共同的特點(diǎn)——都依賴視頻通話和全互動(dòng)直播技術(shù)。 聲...

    raoyi 評(píng)論0 收藏0
  • 從0到1搭建視頻通話系統(tǒng),我1天就搞定了

    摘要:上述就是本文根據(jù)騰訊云官方文檔指引,以為例總結(jié)的從零搭建視頻通話服務(wù)的主要步驟,如有遇到其他問(wèn)題,歡迎留言。 歡迎大家前往騰訊云+社區(qū),獲取更多騰訊海量技術(shù)實(shí)踐干貨哦~ 本文由騰訊云視頻發(fā)表于云+社區(qū)專欄 showImg(https://segmentfault.com/img/remote/1460000016553455?w=1081&h=755); 本文作者,ericxwli,...

    tianlai 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<