不须要任何技术背景,跟着本教程绝对不会失手,让你轻松体验作程序员的快乐。html
本文选用 Agora 视频通话 SDK,在 Android 和 iOS 手机上实现一个基础的一对一视频通话。适用于零基础开发者。主要包含以下内容:java
请使用真机运行项目。模拟机可能会由于功能缺失而没法运行。android
若是你已经有一个 Android 项目,能够跳过该章节,直接阅读下文的集成 SDK。ios
而后点击 Finish。 c++
Android Studio 会花一段时间进行配置,若是有提示须要安装插件,根据屏幕提示下载便可。程序员
在工做的电脑上,链接 Android 手机或平板。点击右上方的 Sync 按钮,提示 Build: completed successdully 表示编译成功后,点击右上方的 Run app 图标。swift
等待一段时间后,Android 手机或平板上会弹出一个是否安装应用程序的弹框。赞成后,手机上就会安装上一个名为 HelloAgora 的应用。恭喜你,成功建立了第一个 App!bash
下载并解压 SDK。从声网开发者中心下载最新版的 Android 视频通话/视频直播 SDK。app
其中,libs 文件夹中包含 jar 文件和 so 文件夹。samples 文件夹中包含一对一视频通话和互动直播的代码示例程序。ide
拷贝 SDK 文件到项目目录。在项目文件夹的 app/src/main 路径下,建立一个 jniLibs 文件夹。而后将 SDK 包中的 arm64-v8a、armeabi-v7a 和 x86 文件拷贝到 jniLibs 文件夹下。
导入 jar 包。将 SDK 包中的 agora-rtc-sdk.jar 文件拷贝到你项目文件夹的 app/libs 路径下。
同步 SDK。在 Android Studio 中,将项目的页面视图切换为 Project 模式。点击右上角的 Sync Project with Gradle Files 按钮。确认 app/build.gradle 文件中有以下行,完成集成。
implementation fileTree(dir: 'libs', include: ['*.jar']) 复制代码
在 /app/src/main/AndroidManifest.xml 文件中,将 package 的名字改成你本身项目包的名字,而后添加以下 <uses-permission... /> 行,增长设备权限:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- If the app uses Bluetooth, please add Bluetooth permissions.-->
<uses-permission android:name="android.permission.BLUETOOTH" />
复制代码
在 app 模块下的 proguard-rules.pro 文件中,添加以下行,防止代码混淆:
-keep class io.agora.**{*;}
复制代码
到这里,你就将 Agora 视频通话/视频直播 SDK 集成到你的项目中,并完成了开发环境准备。
想象你和朋友正在一对一视频通话。这个视频通话的界面上会有如下元素:本地视频画面(你)、远端视频画面(你朋友)、能退出频道的按钮。下面咱们就使用 Android Studio 在新建的项目中建立这些 UI 元素吧。
设置通话界面布局
在项目的 /app/src/main/res/layout/activity_main.xml 文件里,参考以下代码,依次设置本地及远端视窗的位置、尺寸;通话界面提示文字;通话界面上结束按钮的位置等。
<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_video_chat_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<FrameLayout
android:id="@+id/remote_video_view_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white" />
<FrameLayout
android:id="@+id/local_video_view_container"
android:layout_width="160dp"
android:layout_height="284dp"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="16dp"
android:background="@android:color/darker_gray" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="16dp"
android:orientation="vertical">
<TextView
android:id="@+id/quick_tips_when_use_agora_sdk"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="40dp"
android:layout_marginLeft="16dp"
android:layout_marginStart="16dp"
android:gravity="center_vertical|start"
android:text="1. Default channel name is demoChannel1\n2. Waiting for remote users\n3. This demo only supports 1v1 video calling" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal">
<ImageView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="20"
android:onClick="onEndCallClicked"
android:scaleType="centerInside"
android:src="@drawable/btn_end_call" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
复制代码
获取通话结束按钮
为方便起见,咱们直接使用代码示例程序的 UI 元素和设计。将 Demo 中的 /app/src/main/res/drawable-xxxdpi/ 路径下的 btn_end_call.png 复制黏贴至项目的 /app/src/main/res/drawable/ 路径下。
查看并更新通话界面
在 activity_main.xml 页面,点击切换到 Design 页签,实时查看或更新设置的通话视窗布局。
到这里,一个简单的通话界面就建立好了。
视频通话场景的 API 调用流程以下图所示。在实际开发中,你还须要配合 Android 的原生 API 来实现视频通话。若是你对 Android 原生 API 不熟悉,也能够直接参考下文中的完整代码进行调用。
导入头文件
在项目的 app/src/main/java/MainActivity 文件中,package io.agora.helloagora 行的下方,黏贴以下行,导入相应的 SDK 头文件:
import io.agora.rtc.IRtcEngineEventHandler;
import io.agora.rtc.RtcEngine;
import io.agora.rtc.video.VideoCanvas;
import io.agora.rtc.video.VideoEncoderConfiguration;
复制代码
初始化 SDK
在初始化过程当中调用 create 方法获取一个 RtcEngine 实例。
<string name="agora_app_id">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</string>
行,并填入你所获取到的 App ID。private RtcEngine mRtcEngine;
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);
}
});
}
};
...
private void initializeAgoraEngine() {
try {
mRtcEngine = RtcEngine.create(getBaseContext(), getString(R.string.agora_app_id), mRtcEventHandler);
} catch (Exception e) {
throw new RuntimeException("NEED TO check rtc sdk init fatal error\n" + Log.getStackTraceString(e));
}
}
复制代码
设置视频属性
因为 Agora Video SDK 中默认不开始视频模块,所以设置视频属性包含 2 个步骤:
enableVideo
开启视频模式setVideoEncoderConfiguration
方法设置本地视频的编码属性private void setupVideoProfile() {
mRtcEngine.enableVideo();
mRtcEngine.setVideoEncoderConfiguration(new VideoEncoderConfiguration(VideoEncoderConfiguration.VD_640x360, VideoEncoderConfiguration.FRAME_RATE.FRAME_RATE_FPS_15,
VideoEncoderConfiguration.STANDARD_BITRATE,
VideoEncoderConfiguration.ORIENTATION_MODE.ORIENTATION_MODE_FIXED_PORTRAIT));
}
复制代码
设置本地视图
本地视图,指本地用户在通话界面上看到的本地的视频画面。调用 setupLocalVideo
方法设置本地看到的视频。该方法为本地视频流建立一个 View 对象,并:
setZOrderMediaOverlay
设为 true,表示新增一个图层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_FIT, 0));
}
复制代码
加入频道
调用 joinChannel
方法加入视频通话频道。你须要在该方法中传入想要加入的频道名称。App ID 和 Channel Name 均相同的用户能够加入同一个频道进行通话。
private void joinChannel() {
mRtcEngine.joinChannel(null, "demoChannel1", "Extra Optional Data", 0);
}
复制代码
设置远端视图
远端视频,只本地用户在通话界面上看到的远端用户的视频画面。该方法建立一个新的图层,同时将该视频图层与通话界面布局 /app/src/main/res/layout/activity_main.xml 文件中的 remote_video_view_container 进行绑定。
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_FIT, uid));
surfaceView.setTag(uid); // for mark purpose
View tipMsg = findViewById(R.id.quick_tips_when_use_agora_sdk); // optional UI
tipMsg.setVisibility(View.GONE);
}
复制代码
离开频道
调用 leaveChannel
方法离开当前频道。
private void leaveChannel() {
mRtcEngine.leaveChannel();
}
复制代码
完整代码
以上为 Agora 核心 API 的代码示例。你还须要为退出频道的按钮设置一个离开该页面的方法,并在 onCreate 和 onDestroy 中调用上述 API。以下展现的是完整的代码示例:
package io.agora.helloagora;
import android.support.v4.view.PagerTitleStrip;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceView;
import android.view.View;
import android.widget.FrameLayout;
import io.agora.rtc.IRtcEngineEventHandler;
import io.agora.rtc.RtcEngine;
import io.agora.rtc.video.VideoCanvas;
import io.agora.rtc.video.VideoEncoderConfiguration;
public class MainActivity extends AppCompatActivity {
private RtcEngine mRtcEngine;
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
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initializeAgoraEngine();
setupVideoProfile();
setupLocalVideo();
joinChannel();
}
protected void onDestroy() {
super.onDestroy();
leaveChannel();
RtcEngine.destroy();
mRtcEngine = null;
}
public void onEndCallClicked(View view) {
finish();
}
private void initializeAgoraEngine() {
try {
mRtcEngine = RtcEngine.create(getBaseContext(), getString(R.string.agora_app_id), mRtcEventHandler);
} catch (Exception e) {
throw new RuntimeException("NEED to check rtc sdk init fatal error\n" + Log.getStackTraceString(e));
}
}
private void setupVideoProfile() {
mRtcEngine.enableVideo();
mRtcEngine.setVideoEncoderConfiguration(new VideoEncoderConfiguration(
VideoEncoderConfiguration.VD_640x360,
VideoEncoderConfiguration.FRAME_RATE.FRAME_RATE_FPS_15,
VideoEncoderConfiguration.STANDARD_BITRATE,
VideoEncoderConfiguration.ORIENTATION_MODE.ORIENTATION_MODE_ADAPTIVE));
}
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_FIT, 0));
}
private void joinChannel() {
mRtcEngine.joinChannel(null, "demoChannel1", "Extra Optional Data", 0);
}
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_FIT, uid));
surfaceView.setTag(uid);
View tipMsg = findViewById(R.id.quick_tips_when_use_agora_sdk);
tipMsg.setVisibility(View.GONE);
}
private void leaveChannel() {
mRtcEngine.leaveChannel();
}
}
复制代码
至此,Android App 就配置好了。点击右上角的 Sync Project with Gradle Files 按钮从新进行同步。
请使用真机运行项目。模拟机可能会由于功能缺失而没法运行。
打开 Xcode,新建一个项目。
选择 Single View App 模板,点击 Next。
填入你的项目名称,公司名称等信息,选择开发团队与开发语言,点击 Next。
若是你没有添加过开发团队信息,会看到 Add account… 按钮。点击该按钮并按照屏幕提示登入 Apple ID,完成后便可选择你的帐户做为开发团队。
选择你的项目所要存放的位置,点击 Create。
若是你已经设置过开发者签名,可跳过该节。
将你的 iOS 设备链接至电脑。选中当前项目 Target ,在 General 标签页上找到 Signing,勾选 Automatically manage signing,在弹窗中点击 Enable Automatic。
等待片刻,你会看到以下状态,说明你已经设置好了开发者签名。
至此,你已经完成了项目的建立。接下来,让咱们把 Agora SDK 包添加到这个项目中。
有两种方式将 Agora SDK 添加到你的项目中:
开始前请确保你已安装 Cocoapods。参考 Cocoapods Getting Started 了解安装方法。
在 Terminal 里进入项目根目录,而后输入如下命令。项目路径下会生成一个 Podfile 文本文件。
pod init
复制代码
打开 Podfile 文件,修改文件为以下内容。注意将 Your App
替换为你的 Target 名称。
platform :ios, '9.0'
use_frameworks!
target 'Your App' do
pod 'AgoraRtcEngine_iOS'
end
复制代码
在 Terminal 内输入如下命令更新本地库版本:
pod update
复制代码
在 Terminal 内输入如下命令安装 Agora SDK:
pod install
复制代码
若是 Terminal 显示 Pod installation complete!
,则表示自动添加库已完成。此时项目文件夹中会生成一一个 xcworkspace 文件。关闭当前打开的项目,双击打开新生成的 xcworkspace 文件。
下载 Agora Video SDK for iOS ,解压后将 libs 文件夹内的 AgoraRtcEngineKit.framework 文件复制到你的项目文件夹内。
使用 Xcode 打开你的项目,而后选中当前 Target。
打开 Build Phases 页面,展开 Link Binary with Libraries 项并添加以下库。点击 + 图标开始添加。
其中,AgoraRtcEngineKit.framework 位于你的项目文件夹下。所以点击 + 后,还须要点击 Add Other… ,而后进入你的项目所在目录,选中这个文件并点击 Open。
使用 Agora SDK 前,须要对设备的麦克风和摄像头进行受权。打开 info.plist
,点击 + 图标开始添加:
打开 ViewController.swift
文件,在 import UIKit
下一行填入下面的代码。
import AgoraRtcEngineKit
复制代码
若是填入 import 代码后提示找不到文件,能够尝试在 Build Settings 页面 Framework search paths 设置中添加
$(SRCROOT)
。
如今,咱们已经将 Agora SDK 集成到项目中了。
与安卓类似,视频通话须要建立一些基本的 UI 元素:本地视频画面(你)、远端视频画面(你朋友)、能退出频道的按钮。下面咱们就在新建的项目中建立这些 UI 元素,顺便将须要用到的方法和变量写好。
在 ViewController.swift 文件中,用如下代码替代 import
行下面的内容:
class ViewController: UIViewController, AgoraRtcEngineDelegate {
var agoraKit: AgoraRtcEngineKit!
var localVideo: UIView!
var remoteVideo: UIView!
var leaveButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
initView()
initAgora()
setupVideo()
setupLocalVideo()
joinChannel()
}
func initView() {
// 设置远端视频画面
remoteVideo = UIView(frame: self.view.bounds)
self.view.addSubview(remoteVideo)
// 设置本地视频画面
localVideo = UIView(frame: CGRect(x: self.view.bounds.width - 90, y: 0, width: 90, height: 160))
self.view.addSubview(localVideo)
// 设置离开按钮
leaveButton = UIButton(type: .custom)
leaveButton.setTitleColor(UIColor.red, for: .normal)
leaveButton.frame = CGRect(x: self.view.bounds.width / 2 - 50, y: self.view.bounds.height - 50, width: 100, height: 20)
leaveButton.setTitle("Leave", for: .normal)
leaveButton.addTarget(self, action: Selector(("didClickLeave")), for: .touchUpInside)
self.view.addSubview(leaveButton)
}
}
复制代码
到这里,一个简单的通话界面就建立好了。接下来咱们须要经过调用 Agora SDK 提供的核心 API 来实现基础的视频通话功能。
视频通话场景的 API 调用流程以下图所示。你也能够直接参考下文的中完整代码进行调用。
初始化 AgoraRtcEngineKit
进入通话频道以前,调用 sharedEngineWithAppId
方法建立一个 AgoraRtcEngine 实例。
1)在 initView
方法定义后继续添加下面的代码:
func initAgora() {
agoraKit = AgoraRtcEngineKit.sharedEngine(withAppId: "YourAppId", delegate: self)
}
复制代码
2)用你刚刚在 Android 项目中填写的 App ID 替换上面代码中的 YourAppId
(注意保留双引号)。
设置视频属性
因为 Agora SDK 中默认视频模块是关闭的,所以设置视频属性包含 2 个步骤:
enableVideo
开启视频模式setVideoEncoderConfiguration
方法设置本地视频的编码属性func setupVideo() {
// 打开视频模式
agoraKit.enableVideo()
// 设置视频编码配置
agoraKit.setVideoEncoderConfiguration(AgoraVideoEncoderConfiguration(size: AgoraVideoDimension640x360,
frameRate: .fps15,
bitrate: AgoraVideoBitrateStandard,
orientationMode: .adaptative))
}
复制代码
设置本地视频视图
本地视频视图,是指用户在本地设备上看到的本地视频流的视图。
在进入频道前调用 setupLocalVideo
方法,使应用程序绑定本地视频流的显示视窗,并设置本地看到的本地视频视图。
func setupLocalVideo() {
let videoCanvas = AgoraRtcVideoCanvas()
videoCanvas.uid = 0
videoCanvas.view = localVideo
videoCanvas.renderMode = .hidden
agoraKit.setupLocalVideo(videoCanvas)
}
复制代码
加入频道
如今你能够加入频道开始视频通话了。 调用 joinChannelByToken
方法加入频道。
你须要在该方法中传入想要加入的频道名称。App ID 和频道名称均相同的用户能够加入同一个频道进行通话。
func joinChannel() {
agoraKit.joinChannel(byToken: nil, channelId: "demoChannel1", info:nil, uid:0) {(sid, uid, elapsed) -> Void in}
UIApplication.shared.isIdleTimerDisabled = true
}
复制代码
请确保你在该方法中传入的
channelId
的值与在 Android 项目该方法中传入的值是一致的。
设置远端视频视图
远端视频视图,是指用户在本地设备上看到的远端用户的视频画面。
在远端用户进入频道后,能够在远端视频首帧解码回调 firstRemoteVideoDecodedOfUid
中调用 setupRemoteVideo
方法设置本地看到的远端用户的视频视图。
func rtcEngine(_ engine: AgoraRtcEngineKit, firstRemoteVideoDecodedOfUid uid:UInt, size:CGSize, elapsed:Int) {
let videoCanvas = AgoraRtcVideoCanvas()
videoCanvas.uid = uid
videoCanvas.view = remoteVideo
videoCanvas.renderMode = .hidden
agoraKit.setupRemoteVideo(videoCanvas)
}
复制代码
离开频道
视频通话结束时,调用 leaveChannel
方法离开频道。
@IBAction func didClickLeaveButton() {
agoraKit.leaveChannel(nil)
UIApplication.shared.isIdleTimerDisabled = false
remoteVideo.removeFromSuperview()
localVideo.removeFromSuperview()
}
复制代码
完整代码
如今你的项目文件中代码应该相似下面这样:
import UIKit
import AgoraRtcEngineKit
class ViewController: UIViewController, AgoraRtcEngineDelegate {
var agoraKit: AgoraRtcEngineKit!
var localVideo: UIView!
var remoteVideo: UIView!
var leaveButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
initView()
initAgora()
setupVideo()
setupLocalVideo()
joinChannel()
}
func initView() {
// 设置远端视频画面
remoteVideo = UIView(frame: self.view.bounds)
self.view.addSubview(remoteVideo)
// 设置本地视频画面
localVideo = UIView(frame: CGRect(x: self.view.bounds.width - 90, y: 0, width: 90, height: 160))
self.view.addSubview(localVideo)
// 设置离开按钮
leaveButton = UIButton(type: .custom)
leaveButton.setTitleColor(UIColor.red, for: .normal)
leaveButton.frame = CGRect(x: self.view.bounds.width / 2 - 50, y: self.view.bounds.height - 50, width: 100, height: 20)
leaveButton.autoresizingMask = [.flexibleTopMargin, .flexibleLeftMargin, .flexibleRightMargin]
leaveButton.setTitle("Hang Up", for: .normal)
leaveButton.addTarget(self, action: Selector(("didClickLeaveButton")), for: .touchUpInside)
self.view.addSubview(leaveButton)
}
func initAgora() {
agoraKit = AgoraRtcEngineKit.sharedEngine(withAppId: "YourAppId", delegate: self)
}
func setupVideo() {
agoraKit.enableVideo()
agoraKit.setVideoEncoderConfiguration(AgoraVideoEncoderConfiguration(size: AgoraVideoDimension640x360, frameRate: .fps15, bitrate: AgoraVideoBitrateStandard, orientationMode: .adaptative))
}
func setupLocalVideo() {
let videoCanvas = AgoraRtcVideoCanvas()
videoCanvas.uid = 0
videoCanvas.view = localVideo
videoCanvas.renderMode = .hidden
agoraKit.setupLocalVideo(videoCanvas)
}
func joinChannel() {
agoraKit.joinChannel(byToken: nil, channelId: "demoChannel1", info:nil, uid:0) {(sid, uid, elapsed) -> Void in}
UIApplication.shared.isIdleTimerDisabled = true
}
func rtcEngine(_ engine: AgoraRtcEngineKit, firstRemoteVideoDecodedOfUid uid:UInt, size:CGSize, elapsed:Int) {
let videoCanvas = AgoraRtcVideoCanvas()
videoCanvas.uid = uid
videoCanvas.view = remoteVideo
videoCanvas.renderMode = .hidden
agoraKit.setupRemoteVideo(videoCanvas)
}
@IBAction func didClickLeaveButton() {
agoraKit.leaveChannel(nil)
UIApplication.shared.isIdleTimerDisabled = false
remoteVideo.removeFromSuperview()
localVideo.removeFromSuperview()
}
}
复制代码
如今咱们能够链接真机,开始 Android 和 iOS app 一对一视频通话了。
若是一切顺利的话,此时 Android 和 iOS 应用加入了同一个频道并能互相看到对方,能够进行视频通话了。