转载于:Android多人视频聊天应用的开发(二)一对一聊天-玖哥的书房-51CTO博客 http://blog.51cto.com/dongfeng9ge/2095626

本系列文章结合声网官方在GitHub提供的Demo源码进行分析。声网官方在GitHub提供的Demo源码下载链接

在上一篇《Android多人视频聊天应用的开发(一)快速集成》中我们讨论了如何配置Agora Android SDK,本文我们将探索使用Agora进行一对一视频聊天的奥秘。

鉴权

APP ID鉴权

所谓APP ID,就是在 Agora创建每个项目都有的一个唯一标识。App ID 可以明确你的项目及组织身份,并在 joinChannel 方法中作为参数,连接到 Agora 实时网络中,实现实时通信或直播功能。不同的App ID在Agora实时网络中的通话是完全隔离的;Agora 提供的频道信息、计费、管理服务也都是基于 App ID。

申请APP ID的操作很简便,只要在Agora官网https://dashboard.agora.io/projects右侧栏目的“项目”中点击“添加新项目”,只需输入项目名就可生成APP ID,全过程如下图所示:

找到,把“<#YOUR APP ID#>”替换为图中的马赛克里的字符串。

<string name=“agora_app_id”><#YOUR APP ID#></string>

以上就是APP ID鉴权的全过程。

尽管App ID鉴权在最大程度上方便了开发者使用 Agora 的服务。但App ID 鉴权的安全性不佳,一旦有别有用心的人非法获取了你的 App ID,他就可以在 Agora 提供的SDK中使用你的App ID。如果你的项目对安全性要求高,或者增加用户权限设置的话,建议采用Token鉴权。

Token鉴权

在通信和直播场景中存在着多个角色,而每种角色又对应着一些默认权限。比如在直播场景中,主播可以发布流、订阅流、邀请嘉宾;观众可以订阅流、申请连麦;管理员则可以踢人或禁言。

Token鉴权的步骤比APP ID鉴权稍微复杂一些,在上文项目列表中查看 App ID 的地方,启用该项目的 App Certificate:

首先,点击激活项目右上方的 编辑 按钮。

将你的 App Certificate 保存在服务器端,且对任何客户端均不可见。当项目的 App Certificate 被启用后,你必须使用 Token。例如: 在启用 App Certificate 前,你可以使用 App ID 加入频道。但启用了 App Certificate 后,你就必须使用 Token 加入频道。后台如何用App Certificate生成Token本文不做赘述。

初始化Agora

RtcEngine 类包含应用程序调用的主要方法,调用 RtcEngine 的接口最好在同一个线程进行,不建议在不同的线程同时调用。

目前 Agora Native SDK 只支持一个 RtcEngine 实例,每个应用程序仅创建一个 RtcEngine 对象 。 RtcEngine 类的所有接口函数,如无特殊说明,都是异步调用,对接口的调用建议在同一个线程进行。所有返回值为 int 型的 API,如无特殊说明,返回值 0 为调用成功,返回值小于 0 为调用失败。

IRtcEngineEventHandler接口类用于SDK向应用程序发送回调事件通知,应用程序通过继承该接口类的方法获取 SDK 的事件通知。

接口类的所有方法都有缺省(空)实现,应用程序可以根据需要只继承关心的事件。在回调方法中,应用程序不应该做耗时或者调用可能会引起阻塞的 API(如 SendMessage),否则可能影响 SDK 的运行。

private RtcEngine mRtcEngine;

/**
 * Tutorial Step 1
 * 初始化Agora,创建 RtcEngine 对象
 */
private void initializeAgoraEngine() {
    try {
        mRtcEngine = RtcEngine.create(getBaseContext(), getString(R.string.agora_app_id), mRtcEventHandler);
    } catch (Exception e) {
        Log.e(LOG_TAG, Log.getStackTraceString(e));

throw new RuntimeException(“Agora初始化失败了,检查一下是哪儿出错了\n + Log.getStackTraceString(e));
    }
}

private final IRtcEngineEventHandler mRtcEventHandler = new IRtcEngineEventHandler() {
    @Override
    public void onFirstRemoteVideoDecoded(final int uid, int width, int height, int elapsed) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                //设置远端视频显示属性
                setupRemoteVideo(uid);
            }
        });
    }

@Override
    public void onUserOffline(int uid, int reason) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                //其他用户离开当前频道回调
                onRemoteUserLeft();
            }
        });
    }

@Override
    public void onUserMuteVideo(final int uid, final boolean muted) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                //其他用户已停发/已重发视频流回调
                onRemoteUserVideoMuted(uid, muted);
            }
        });
    }
};

private void onRemoteUserLeft() {
    FrameLayout container = (FrameLayout) findViewById(R.id.remote_video_view_container);
    container.removeAllViews();

//文案可随意定制
    View tipMsg = findViewById(R.id.quick_tips_when_use_agora_sdk);
    tipMsg.setVisibility(View.VISIBLE);
}

private void onRemoteUserVideoMuted(int uid, boolean muted) {
    FrameLayout container = (FrameLayout) findViewById(R.id.remote_video_view_container);

SurfaceView surfaceView = (SurfaceView) container.getChildAt(0);

Object tag = surfaceView.getTag();
    if (tag != null && (Integer) tag == uid) {
        surfaceView.setVisibility(muted ? View.GONE : View.VISIBLE);
    }
}

打开视频模式

enableVideo()方法用于打开视频模式。可以在加入频道前或者通话中调用,在加入频道前调用,则自动开启视频模式,在通话中调用则由音频模式切换为视频模式。调用 disableVideo() 方法可关闭视频模式。

setVideoProfile()方法设置视频编码属性(Profile)。每个属性对应一套视频参数,如分辨率、帧率、码率等。 当设备的摄像头不支持指定的分辨率时,SDK 会自动选择一个合适的摄像头分辨率,但是编码分辨率仍然用 setVideoProfile() 指定的。

该方法仅设置编码器编出的码流属性,可能跟最终显示的属性不一致,例如编码码流分辨率为 640x480,码流的旋转属性为 90 度,则显示出来的分辨率为竖屏模式。

/**
 * Tutorial Step 2
 * 打开视频模式并设置本地视频属性
 */
private void setupVideoProfile() {
    //打开视频模式
    mRtcEngine.enableVideo();
    //设置本地视频属性
    mRtcEngine.setVideoProfile(Constants.VIDEO_PROFILE_360P, false);
}

设置本地视频显示属性

setupLocalVideo( VideoCanvas local )方法用于设置本地视频显示信息。应用程序通过调用此接口绑定本地视频流的显示视窗(view),并设置视频显示模式。 在应用程序开发中,通常在初始化后调用该方法进行本地视频设置,然后再加入频道。退出频道后,绑定仍然有效,如果需要解除绑定,可以调用 setupLocalVideo(null) 。

/**
 * Tutorial Step 3
 * 设置本地视频显示属性
 */
private void setupLocalVideo() {
    FrameLayout container = (FrameLayout) findViewById(R.id.local_video_view_container);
    SurfaceView surfaceView = RtcEngine.CreateRendererView(getBaseContext());
    surfaceView.setZOrderMediaOverlay(true);
    container.addView(surfaceView);
    mRtcEngine.setupLocalVideo(new VideoCanvas(surfaceView, VideoCanvas.RENDER_MODE_ADAPTIVE, 0));
}

加入一个频道

joinChannel(String token,String channelName,String optionalInfo,int optionalUid )方法让用户加入通话频道,在同一个频道内的用户可以互相通话,多个用户加入同一个频道,可以群聊。 使用不同 App ID 的应用程序是不能互通的。如果已在通话中,用户必须调用 leaveChannel() 退出当前通话,才能进入下一个频道。

/**
 * Tutorial Step 4
 * 加入一个频道
 */
private void joinChannel() {
    //如果不指定UIDAgroa将自动生成并分配一个UID
    mRtcEngine.joinChannel(null, “demoChannel1”, “Extra Optional Data”, 0);
}

设置远端视频显示属性

setupRemoteVideo( VideoCanvas remote)方法用于绑定远程用户和显示视图,即设定 uid 指定的用户用哪个视图显示。调用该接口时需要指定远程视频的 uid,一般可以在进频道前提前设置好。

如果应用程序不能事先知道对方的 uid,可以在 APP 收到 onUserJoined 事件时设置。如果启用了视频录制功能,视频录制服务会做为一个哑客户端加入频道,因此其他客户端也会收到它的 onUserJoined 事件,APP 不应给它绑定视图(因为它不会发送视频流),如果 APP 不能识别哑客户端,可以在 onFirstRemoteVideoDecoded 事件时再绑定视图。解除某个用户的绑定视图可以把 view 设置为空。退出频道后,SDK 会把远程用户的绑定关系清除掉。

/**
 * Tutorial Step 5
 * 设置远端视频显示属性
 */
private void setupRemoteVideo(int uid) {
    FrameLayout container = (FrameLayout) findViewById(R.id.remote_video_view_container);

if (container.getChildCount() >= 1) {
        return;
    }

SurfaceView surfaceView = RtcEngine.CreateRendererView(getBaseContext());
    container.addView(surfaceView);
    mRtcEngine.setupRemoteVideo(new VideoCanvas(surfaceView, VideoCanvas.RENDER_MODE_ADAPTIVE, uid));

surfaceView.setTag(uid);
    //文案可随意定制
    View tipMsg = findViewById(R.id.quick_tips_when_use_agora_sdk);
    tipMsg.setVisibility(View.GONE);
}

离开当前频道

leaveChannel()方法用于离开频道,即挂断或退出通话。

当调用 joinChannel() API 方法后,必须调用 leaveChannel() 结束通话,否则无法开始下一次通话。 不管当前是否在通话中,都可以调用 leaveChannel(),没有副作用。该方法会把会话相关的所有资源释放掉。该方法是异步操作,调用返回时并没有真正退出频道。在真正退出频道后,SDK 会触发 onLeaveChannel 回调。

/**
 * Tutorial Step 6
 * 离开当前频道
 */
private void leaveChannel() {
    mRtcEngine.leaveChannel();
}

public void onEncCallClicked(View view) {
    finish();
}

@Override
protected void onDestroy() {
    super.onDestroy();

leaveChannel();
    RtcEngine.destroy();
    mRtcEngine = null;
}

管理摄像头

switchCamera()方法用于在前置/后置摄像头间切换。除此以外Agora还提供了一下管理摄像头的方法:例如setCameraTorchOn(boolean isOn)设置是否打开闪光灯、setCameraAutoFocusFaceModeEnabled(boolean enabled)设置是否开启人脸对焦功能等等。

/**
 * Tutorial Step 7
 * 切换前置/后置摄像头
 */
public void onSwitchCameraClicked(View view) {
    mRtcEngine.switchCamera();
}

将自己静音

muteLocalAudioStream(boolean muted)方法用于静音/取消静音。该方法可以允许/禁止往网络发送本地音频流。但该方法并没有禁用麦克风,不影响录音状态。

/**
 * Tutorial Step 8
 * 将自己静音
 */
public void onLocalAudioMuteClicked(View view) {
    ImageView iv = (ImageView) view;
    if (iv.isSelected()) {
        iv.setSelected(false);
        iv.clearColorFilter();
    } else {
        iv.setSelected(true);
        iv.setColorFilter(getResources().getColor(R.color.colorPrimary), PorterDuff.Mode.MULTIPLY);
    }

mRtcEngine.muteLocalAudioStream(iv.isSelected());
}

暂停本地视频流

muteLocalVideoStream(boolean muted)方法用于暂停发送本地视频流,但该方法并没有禁用摄像头,不影响本地视频流获取。

/**
 * Tutorial Step 9
 * 暂停本地视频流
 */
public void onLocalVideoMuteClicked(View view) {
    ImageView iv = (ImageView) view;
    if (iv.isSelected()) {
        iv.setSelected(false);
        iv.clearColorFilter();
    } else {
        iv.setSelected(true);
        iv.setColorFilter(getResources().getColor(R.color.colorPrimary), PorterDuff.Mode.MULTIPLY);
    }

mRtcEngine.muteLocalVideoStream(iv.isSelected());

FrameLayout container = (FrameLayout) findViewById(R.id.local_video_view_container);
    SurfaceView surfaceView = (SurfaceView) container.getChildAt(0);
    surfaceView.setZOrderMediaOverlay(!iv.isSelected());
    surfaceView.setVisibility(iv.isSelected() ? View.GONE : View.VISIBLE);
}

运行效果

拿两部手机安装编译好的App,如果能看见两个自己,说明你成功了

通过本文的学习,我们已经掌握了利用Agora进行一对一聊天的技巧,接下来的文章中,我将继续介绍多人聊天室等知识。

                </div>

(Agora声网)多人视频聊天应用的开发(二)一对一聊天相关推荐

  1. (Agora声网)多人视频聊天应用的开发(三)多人聊天

    转载于:Android多人视频聊天应用的开发(三)多人聊天-玖哥的书房-51CTO博客 http://blog.51cto.com/dongfeng9ge/2104587 本系列文章结合声网官方在Gi ...

  2. (Agora声网)多人视频聊天应用的开发(一)快速集成

    转载于:Android多人视频聊天应用的开发(一)快速集成-玖哥的书房-51CTO博客 http://blog.51cto.com/dongfeng9ge/2095621 本系列文章结合声网官方在Gi ...

  3. 基于声网的音视频SDK和FreeSWITCH开发WebRTC2SIP Gateway 方案和思路

    为什么做这个? 今年初接到一个项目任务,客户要求在自己的音视频平台系统中集成webrtc功能(原系统是基于SIP协议开发的,已经稳定运行多年,有很多客户).在比对了多家RTC产品的效果后,.他们对声网 ...

  4. Unity Metaverse(八)、RTC Engine 基于Agora声网SDK实现音视频通话

    文章目录 简介 创建应用 构建应用场景 API调用与回调事件 测试 简介 本文介绍如何在Unity中接入声网SDK,它可以应用的场景有许多,例如直播.电商.游戏.社交等,音视频通话是其实时互动的基础能 ...

  5. Agora声网-Uniapp拉流(Vue拉流)

    /** * agora声网解决方案* 1. 创建 AgoraClient 对象* 2. join进入相应频道* 3. on 监听 user-published 拿到远端用户对象 AgoraRTCRem ...

  6. 使用声网sdk音视频时,播放本地音频心得

    注意: 使用声网sdk音视频时,需要使用声网sdk内部的播放音频api 否则在iOS12系统上,通过avplayer播放时,使用replaceItem的方式切换AVPlayerItem时会出现声音消失 ...

  7. [跳舞吧多人视频空间]ADS集成开发环境先容

    [跳舞吧多人视频空间]ADS集成开发环境先容 2012年01月11日 [b]跳舞吧[/b][b]视频空间美女主播聊天交友,尽在[/b][b]同城聊天室[/b][b]跳舞吧 [/b] ADS全称为ARM ...

  8. vue项目Agora声网实现一对一视频聊天Demo示例(Agora声网实战及agora-rtc-vue使用,新增在线预览地址)

    最终效果 在线预览地址 一.声网简介---->请查看官网 二.声网注册---->请自行百度(创建音视频连接需要在Agora注册属于您的appid) 三.具体实现视频聊天步骤 1. 实现音视 ...

  9. 使用声网的RTM SDK轻松给angular应用加上实时聊天功能

    作者:陈畏民 源起 今年寒假的前半段时间, 在家捣鼓了一个情侣类web应用, 基于aspnetcore和angular搭建的; 寒假中实现了'告白', '相册', '说说', '纪念日'这些功能, 然 ...

最新文章

  1. Vim 命令、操作、快捷键全集
  2. html画布显示PPT,【Web前端问题】有没有办法让HTML5 canvas显示/预览word/excel/powerpoint 文档?...
  3. hdu 1565 方格取数(1)(状态压缩dp)
  4. python 环境常用指令(updating...)
  5. nginx服务器配置安全维护,Nginx服务器相关的一些安全配置建议
  6. mysql 参数化分页_LR12 DataWizard从Mysql数据取参数化数据
  7. Excel图表快捷操作小技巧
  8. KCF算法数学推导及算法流程图
  9. u盘插上电脑显示计算机无响应,为什么u盘连接电脑没反应,u盘在电脑上显示不出来...
  10. 1999-2019,互联网失落者
  11. sp-api对接过程详解
  12. Mathematica学习(2)-mathematica命令
  13. (四)万能的搜索 —— 2. 解救小哈
  14. android主线程报ANR的问题!
  15. [需求管理-2]:什么是需求以及需求的收集与识别
  16. Ubuntu下如何下载linux内核源码
  17. 【Git】团队协作(终于学会了)
  18. c语言用空格分隔和用逗号分隔,c语言程序设计课呵件第02章简单程序设计.ppt
  19. 本地k8s环境搭建工具kind、microk8s安装;windows 包管理工具Chocolatey;lens k8s可视化工具
  20. 可以提高效率优化界面的WebStorm插件完整版在此

热门文章

  1. RocketMQ 发送消息的基本案例
  2. P1089津津的储蓄计划-C++编程解析-分支
  3. C/C++浮点数格式——IEEE754标准
  4. linux shell的for循环语法是怎样的?
  5. strstr函数[转]
  6. 设置超过DIV高度范围隐藏结尾... 点击查看全文显示全部
  7. 02- HashMap 底层实现原理是什么?JDK 8 做了哪些优化?
  8. 所有的事情都会趋于平淡
  9. 使用Windows原生命令一键清空剪贴板
  10. 1月14日科技资讯|京东回应「被薅 7000 万、项目组全体开除」;微信朋友圈屏蔽支付宝集五福;MySQL 8.0.19 发布