Android多人视频聊天应用的开发(三)多人聊天

在上一篇《Android多人视频聊天应用的开发(二)一对一聊天》中我们学习了如何使用声网Agora SDK进行一对一的聊天,本篇主要讨论如何使用Agora SDK进行多人聊天。主要需要实现以下功能:

1、上一篇已经实现过的聊天功能

2、随着加入人数和他们的手机摄像头分辨率的变化,显示不同的UI,即所谓的“分屏”

3、点击分屏中的小窗,可以放大显示该聊天窗

分屏

根据前期技术调研,分屏显示最好的方式是采用瀑布流结合动态聊天窗实现,这样比较方便的能够适应UI的变化。所谓瀑布流,就是目前比较流行的一种列表布局,会在界面上呈现参差不齐的多栏布局。我们先实现一个瀑布流:

瀑布流的实现方式很多,本文采用结合GridLayoutManager的RecyclerView来实现。我们首先自定义一个RecyclerView,命名为GridVideoViewContainer。核心代码如下:


int count = uids.size();
if (count <= 2) {
    // 只有本地视频或聊天室内只有另外一个人
    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));
}

根据上面的代码可以看出,在聊天室里只有自己的本地视频或者只有另外一个人的时候,采用LinearLayoutManager,这样的布局其实与前文的一对一聊天类似;而在真正意义的多人聊天室里,则采用GridLayoutManager实现瀑布流,其中itemSpanCount就是瀑布流的列数。

有了一个可用的瀑布流之后,下面我们就可以实现动态聊天窗了:

动态聊天窗的要点在于item的大小由视频的宽高比决定,因此Adapter及其对应的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;
    }
}

以上代码根据视频的数量确定了列数和行数,然后根据列数和屏幕宽度确定了视频的宽度,接着根据视频的宽高比和视频宽度确定了视频高度。同时也考虑了手机的横竖屏情况(就是if (width > height)这行代码)。

该Adapter对应的layout的代码如下:


<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/user_control_mask"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

<ImageView
        android:id="@+id/default_avatar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:visibility="gone"
        android:src="@drawable/icon_default_avatar"
        android:contentDescription="DEFAULT_AVATAR" />

<ImageView
        android:id="@+id/indicator"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="@dimen/video_indicator_bottom_margin"
        android:contentDescription="VIDEO_INDICATOR" />

<LinearLayout
        android:id="@+id/video_info_container"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_marginTop="24dp"
        android:layout_marginStart="15dp"
        android:layout_marginLeft="15dp"
        android:visibility="gone"
        android:orientation="vertical">

<TextView
            android:id="@+id/video_info_metadata"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:singleLine="true"
            style="@style/NotificationUIText" />
    </LinearLayout>

</RelativeLayout>

我们可以看到,layout中有关尺寸的属性都是wrap_content,这就使得item大小随视频宽高比变化成为可能。

把分屏的布局写好之后,我们就可以在每一个item上播放聊天视频了。

播放聊天视频

在Agora SDK中一个远程视频的显示只和该用户的UID有关,所以使用的数据源只需要简单定义为包含UID和对应的SurfaceView即可,就像这样:


private final HashMap<Integer, SurfaceView> mUidsList = new HashMap<>();

每当有人加入了我们的聊天频道,都会触发onFirstRemoteVideoDecoded(int uid, int width, int height, int elapsed)方法,第一个uid就是他们的UID;接下来我们要为每个item新建一个SurfaceView并为其创建渲染视图,最后将它们加入刚才创建好的mUidsList里并调用setupRemoteVideo( VideoCanvas remote )方法播放这个聊天视频。这个过程的完整代码如下:


@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);
            }
        }
    });
}

以上代码与前文中播放一对一视频的代码如出一撤,但是细心的读者可能已经发现我们并没有将生成的SurfaceView放在界面里,这正是与一对一视频的不同之处:我们要在一个抽象的VideoViewAdapter类里将SurfaceView放出来,关键代码如下:


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

一般Android工程师看见holderView就明白这是ViewHolder的layout的根layout了,而user是哪儿来的,详见文末的代码,文中不做赘述。

这样在多人聊天的时候我们就能使用分屏的方式播放用户聊天视频了,如果想放大某一个用户的视频该怎么办呢?

全屏和小窗

当用户双击某一个item的时候,他希望对应的视频能够全屏显示,而其他的视频则变成小窗口,那么我们先定义一个双击事件接口:


public interface VideoViewEventListener {
    void onItemDoubleClick(View v, Object item);
}

具体实现方式如下:


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<Integer, SurfaceView> slice = new HashMap<>(1);
    slice.put(bigBgUid, mUidsList.get(bigBgUid));
    Iterator<SurfaceView> 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());
}

小窗列表要注意移除全屏的那个UID,此外一切都和正常瀑布流视图相同,包括双击小窗的item将其全屏播放。

到了这里我们就已经使用Agora SDK完成了一个有基本功能的简单多人聊天demo,要产品化还有很多的东西要做,在这里先做一个简单的总结吧!

Agora SDK使用总结

声网Agora提供了高质量的视频通信SDK,不仅覆盖了主流的操作系统,集成效率也比较高,而且还支持包括聊天,会议,直播等功能在内的多个模式的视频通话。SDK中API设计基本能够满足大部分的开发需要,而且隐藏了底层开发,只需要提供SurfaceView和UID即可播放视频,这样对于App层的开发者来说十分友好。非常适合有视频聊天开发需求的开发者。在视频领域创业大爆发的今天,建议更多的想要从事该领域的开发者可以尝试下。

当然声网Agora也并非尽善尽美,有些地方还有改进的空间,我有两个建议,以往厂商可以考虑下:

1、Agora支持Kotlin,目前Kotlin现在已经成为Google官方建议的Android开发语言,支持Kotlin有助于跟上时代的步伐。但Agora并没有把Kotlin的demo放在官网上。

2、希望可以提供带基础UI的SDK,就像UMeng的分享SDK一样或者AMap的导航SDK,一套带简单UI的SDK不仅能直接应用到项目中,还允许开发者进一步定制,这样更容易收到App层的开发者技术选型时的青睐,他们的集成效率也会更高。

原文地址:http://blog.51cto.com/dongfeng9ge/2104587

时间: 2024-10-28 21:20:38

Android多人视频聊天应用的开发(三)多人聊天的相关文章

Android WebRTC 音视频开发总结

www.cnblogs.com/lingyunhu/p/3621057.html 前面介绍了WebRTCDemo的基本结构,本节主要介绍WebRTC音视频服务端的处理,,转载请说明出处(博客园RTC.Blacker). 通过前面的例子我们知道运行WebRTCDemo即可看到P2P的效果,实际应用中我们不可能让用户自己去里面设置对方的IP和音视频端口, 而且即使设置了对方的IP和端口也不一定能运行起来,因为P2P如果双方不在同一个网段则还需穿透NAT,那服务端具体该如何部署呢? 1.信令服务: 想

开个多人视频聊天软件需要多少钱?

首先,不知道你开发的是哪一种产品,因为多人视频聊天软件很多种,像我们雅顾合作就起码有几十种产品,这边给你们推荐下我们最主要的三种: 一.人气娱乐视频聊天软件 雅顾推荐人气娱乐视频聊天软件.以房间为单位,有共同兴趣爱好的网友可以欢聚一室.房间设计可供多元化选择,如经典款竖二屏,经典款竖三屏:清新版横三屏:风尚版竖二屏等, 让您娱乐更加随心所欲!清晰的视频画面,丰富的视频特效,专业的音响效果,网友可通过音视频的方式尽情展示个性风采,观看精彩互动节目. 二.人气会员视频聊天软件 所谓人气会员就是和qq

C#实现多人视频聊天

在 <C#实现多人语音聊天>一文发布后,很多朋友建议我也实现一个视频聊天室给他们参考一下,其实,视频聊天室与语音聊天室的原理是差不多的,由于加入了摄像头.视频的处理,逻辑会繁杂一些,本文就实现一个简单的多人视频聊天系统,让多个人可以进入同一个房间进行语音视频沟通.先看看3个人进行视频聊天的运行效果截图:       上面两张截图分别是:登录界面.标注了各个控件的视频聊天室的主界面. 一. C/S结构 很明显,我这个语音聊天室采用的是C/S结构,整个项目结构相对比较简单,如下所示: 同语音聊天室

Android WebRTC 音视频开发总结(一)

Android WebRTC 音视频开发总结(一) https://github.com/gandg/webrtc-ios 接触Android WebRTC有一段时间了,现在将研究过程中的一些经验和知识总结出来,希望大家有所帮助.本章主要介绍下面四点: 一.WebRTC是什么? WebRTC是Google提供的一个跨平台的音视频开源解决方案,旨在使其成为音视频通讯的标准.其实在Google将WebRTC开源之前,微软和苹果各自的通讯产品已占用很大市场份额(如Skype),估计Google也是为了

Android WebRTC 音视频开发总结(五)

这几天用WebRTC做了个视频监控的功能,分享出来,供想了解这方面内容的朋友参考. 一.基本模块: 1.视频采集端:相当于是客户端,用来采集视频,只需要发送视频,不需要接收. 2.视频监控端:接收采集端传入的视频数据,相当于监控客户端,不需要发送视频数据给客户端. 3.服务端:负责客户端注册.信令控制.数据包转发.UDP打洞等,支持TCP,UDP连接. 二.环境要求: 1.两台Andorid4.0 以上的手机,分别做采集端和监控端. 2.一台PC 做服务端. 3.PC.手机在同一个局域网内.理论

Android中直播视频技术探究之---基础核心类ByteBuffer解析

一.前言 前一篇文章我们介绍了Android中直播视频技术的基础大纲知识,这里就开始一一讲解各个知识点,首先主要来看一下视频直播中的一个重要的基础核心类:ByteBuffer,这个类看上去都知道了,是字节缓冲区处理字节的,这个类的功能非常强大,也在各个场景都有用到,比如网络数据底层处理,特别是结合网络通道信息处理的时候,还有就是后面要说到的OpenGL技术也要用到,当然在视频处理中也是很重要的,因为要处理视频流信息,比如在使用MediaCodec进行底层的视频流编码的时候,处理的就是字节,我们如

Android平台第三方应用分享到微信开发

[转载]Android平台第三方应用分享到微信开发 一.申请APPID 微信公共平台和微博分享一样,也需要申请一个ID,来作为调起微信.分享到微信的唯一标识. 申请微信APPID可以到微信平台http://open.weixin.qq.com/app/list/?lang=zh_CN上申请.具体的申请流程网站上有很详细的介绍,我这里就仅列出一些注意事项: (1)申请APPID时的应用名字审核通过之后将不允许更改,所以申请时的应用名字一定要提前确定好.微信官方也有详细说明,如下图: (2)应用签名

Android中直播视频技术探究之---基础知识大纲介绍

一.前言 最近各种视频直播app到处都是,各种霸屏,当然我们也是需要体验的,关于视频直播的软件这里就不介绍了,在不是技术的人来看,直播是一种潮流,是一种娱乐方式,但是作为一个高技术的,我们除了看看,更重要的是学习技术,其实Android中的视频技术没什么说的,因为网上的资料很多,但是之前的视频技术大部分都出现在了视频播放,就是主流的视频播放器,那个最重要的一个技术就是视频的编解码,这个也会在后续文章中详细介绍视频的处理技术.但是现在直播的技术是在之前的视频技术上又有了一个要求就是视频录制,现在录

区块链社交直播聊天app软件开发,币圈微信开发商

区块链社交应用能够利用节点间的信任,在进行广告投放,智能履行合约时,可以自动实行资金托管:媒体在进行广告点击付费时,能够真正为获客点击而付费:同时,用户在为生态创造大量的用户和内容流量时,系统会自动给予虚拟资产奖励并支持变现.区块链社交开发T:前面138中间2315后面3201 区块链社交软件系统的优势 多人视频直播,直播打赏区块链资产,不断创新提升用户体验 致力于打造良好的区块链社区服务,娱乐于一体的社交软件 手机端方便快捷,随时随地与好友聊天,群聊,发红包打赏区块链资产. 朋友圈分享动态,互