本文介绍如何使用 Agora 语音通话 SDK 快速实现语音通话。
本节介绍如何创建项目,将 Agora 音频 SDK 集成进你的项目中,并添加相应的设备权限。
参考以下步骤创建一个 Android 项目。若已有 Android 项目,可以直接查看集成 SDK。
然后点击 Finish。根据屏幕提示,安装可能需要的插件。
选择如下任意一种方式将 Agora 音频 SDK 集成到你的项目中。
方法一:使用 JCenter 自动集成
在项目的 /app/build.gradle 文件中,添加如下行:
...
dependencies {
...
// x.y.z 请填写具体版本号,如:3.0.0
// 可通过 SDK 发版说明取得最新版本号
implementation 'io.agora.rtc:voice-sdk:x.y.z'
}
方法二:手动复制 SDK 文件
文件或文件夹 | 项目路径 |
---|---|
agora-rtc-sdk.jar 文件 | /app/libs/ |
arm64-v8a 文件夹 | /app/src/main/jniLibs/ |
armeabi-v7a 文件夹 | /app/src/main/jniLibs/ |
include 文件夹 | /app/src/main/jniLibs/ |
x86 文件夹 | /app/src/main/jniLibs/ |
x86_64 文件夹 | /app/src/main/jniLibs/ |
libagora-crypto.so
文件。extension
的库是可选项,请按需集成。你可以在发版说明中查看扩展库对应的功能。根据场景需要,在 /app/src/main/AndroidManifest.xml 文件中添加如下行,获取相应的设备权限:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.agora.tutorials1v1acall">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
// 如果你的场景中涉及读取外部存储,需添加如下权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
// 如果你使用的是 Android 10.0 及以上设备,还需要添加如下权限:
<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
...
</manifest>
如果你的 targetSdkVersion
≥ 29,还需要在 AndroidManifest.xml 文件的 <application>
区域添加如下行:
<application
android:requestLegacyExternalStorage="true">
...
</application>
在 app/proguard-rules.pro 文件中添加如下行,防止混淆 Agora SDK 的代码:
-keep class io.agora.**{*;}
本节介绍如何实现语音通话。语音通话的 API 调用时序见下图:
根据场景需要,为你的项目创建语音通话的用户界面。若已有界面,可以直接查看导入类。
你可以参考 Agora-Android-Voice-Tutorial-1to1 示例项目的 activity_voice_chat_view.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_voice_chat_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="io.agora.tutorials1v1acall.VoiceChatViewActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="@dimen/activity_vertical_margin"
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="@dimen/activity_horizontal_margin"
android:layout_marginStart="@dimen/activity_horizontal_margin"
android:gravity="center_vertical|start"
android:text="1. Default channel name is voiceDemoChannel1\n2. Waiting for remote users\n3. This demo only supports 1v1 voice 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="onLocalAudioMuteClicked"
android:scaleType="centerInside"
android:src="@drawable/btn_mute" />
<ImageView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="20"
android:onClick="onSwitchSpeakerphoneClicked"
android:scaleType="centerInside"
android:src="@drawable/btn_speaker" />
<ImageView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="20"
android:onClick="onEncCallClicked"
android:scaleType="centerInside"
android:src="@drawable/btn_end_call" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
在项目的 Activity 文件中添加如下行:
import io.agora.rtc.IRtcEngineEventHandler;
import io.agora.rtc.RtcEngine;
调用 checkSelfPermission
方法,在开启 Activity 时检查并获取 Android 移动设备的麦克风使用权限。
// Java
private static final int PERMISSION_REQ_ID_RECORD_AUDIO = 22;
// App 运行时确认麦克风的使用权限。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_voice_chat_view);
// 获取权限后,初始化 RtcEngine,并加入频道。
if (checkSelfPermission(Manifest.permission.RECORD_AUDIO, PERMISSION_REQ_ID_RECORD_AUDIO)) {
initAgoraEngineAndJoinChannel();
}
}
private void initAgoraEngineAndJoinChannel() {
initializeAgoraEngine();
joinChannel();
}
public boolean checkSelfPermission(String permission, int requestCode) {
Log.i(LOG_TAG, "checkSelfPermission " + permission + " " + requestCode);
if (ContextCompat.checkSelfPermission(this,
permission)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{permission},
requestCode);
return false;
}
return true;
}
// Kotlin
// app 运行时确认麦克风的使用权限。
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_voice_chat_view)
// 获取权限后,初始化 RtcEngine,并加入频道。
if (checkSelfPermission(Manifest.permission.RECORD_AUDIO, PERMISSION_REQ_ID_RECORD_AUDIO)) {
initAgoraEngineAndJoinChannel()
}
}
private fun initAgoraEngineAndJoinChannel() {
initializeAgoraEngine()
joinChannel()
}
private fun checkSelfPermission(permission. String, requestCode: Int): Boolean {
Log.i(LOG_TAG, "checkSelfPermission $permission $reuqestCode")
if (ContextCompat.checkSelfPermission(this,
permission) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermission(this
arrayOf(permission),
requestCode)
return false
}
return true
}
在调用其他 Agora API 前,需要创建并初始化 RtcEngine 对象。
将获取到的 App ID 添加到 string.xml
文件中的 agora_app_id
一栏。调用 create
方法,传入获取到的 App ID,即可初始化 RtcEngine。
你还根据场景需要,在初始化时注册想要监听的回调事件,如远端用户下线或静音回调。注意不要在这些回调中进行 UI 操作。
// Java
private RtcEngine mRtcEngine;
private final IRtcEngineEventHandler mRtcEventHandler = new IRtcEngineEventHandler() {
// 注册 onUserOffline 回调。远端用户离开频道后,会触发该回调。
@Override
public void onUserOffline(final int uid, final int reason) {
runOnUiThread(new Runnable() {
@Override
public void run() {
onRemoteUserLeft(uid, reason);
}
});
}
// 注册 onUserMuteAudio 回调。远端用户静音后,会触发该回调。
@Override
public void onUserMuteAudio(final int uid, final boolean muted) {
runOnUiThread(new Runnable() {
@Override
public void run() {
onRemoteUserVoiceMuted(uid, muted);
}
});
}
};
...
// 调用 Agora SDK 的方法初始化 RtcEngine。
private void initializeAgoraEngine() {
try {
mRtcEngine = RtcEngine.create(getBaseContext(), getString(R.string.agora_app_id), mRtcEventHandler);
mRtcEngine.setChannelProfile(Constants.CHANNEL_PROFILE_COMMUNICATION);
} catch (Exception e) {
Log.e(LOG_TAG, Log.getStackTraceString(e));
throw new RuntimeException("NEED TO check rtc sdk init fatal error\n" + Log.getStackTraceString(e));
}
}
// Kotlin
private var mRtcEngine: RtcEngine? = null
private val mRtcEventHandler = object : IRtcEngineEventHandler() {
// 注册 onUserOffline 回调。远端用户离开频道后,会触发该回调。
override fun onUserOffline(uid: Int, reason: Int) {
runOnUiThread { onRemoteUserLeft() }
}
// 注册 onUserMuteAudio 回调。远端用户静音后,会触发该回调。
override fun onUserMuteAudio(uid: Int, muted: Boolean) {
runOnUiThread { onRemoteUserVoiceMuted(uid, muted)}
}
}
...
// 调用 Agora SDK 的方法初始化 RtcEngine。
private fun initializeAgoraEngine() {
try {
mRtcEngine = RtcEngine.create(baseContext, getString(R.string.agora_app_id), mRtcEventHandler)
} catch (e: Exception) {
Log.e(LOG_TAG, Log.getStackTraceString(e))
throw RuntimeException("NEED TO check rtc sdk init fatal error\n" + Log.getStackTraceString(e))
}
}
完成初始化后,你就可以调用 joinChannel
方法加入频道。你需要在该方法中传入如下参数:
token
:传入用于鉴权的 Token,可设为如下一个值:
token
设为 ""。channelName:传入能标识频道的频道 ID。App ID 相同、频道 ID 相同的用户会进入同一个频道。
uid: 本地用户的 ID。数据类型为整型,且频道内每个用户的 uid 必须是唯一的。若将 uid 设为 0,则 SDK 会自动分配一个 uid,并在 onJoinChannelSuccess
回调中报告。
mute
方法实现。更多的参数设置注意事项请参考 joinChannel
接口中的参数描述。
// Java
private void joinChannel() {
String accessToken = getString(R.string.agora_access_token);
if (TextUtils.equals(accessToken, "") || TextUtils.equals(accessToken, "#YOUR ACCESS TOKEN#")) {
accessToken = null;
}
// 调用 Agora SDK 的 joinChannel 方法加入频道。未指定 uid,SDK 会自动分配一个。
mRtcEngine.joinChannel(accessToken, "voiceDemoChannel1", "Extra Optional Data", 0);
}
// Kotlin
private fun joinChannel() {
// 调用 Agora SDK 的 joinChannel 方法加入频道。未指定 uid,SDK 会自动分配一个。
mRtcEngine!!.joinChannel(token, "demoChannel1", "Extra Optional Data", 0)
}
根据场景需要,如结束通话、关闭 App 或 App 切换至后台时,调用 leaveChannel
离开当前通话频道。
// Java
private void leaveChannel() {
mRtcEngine.leaveChannel();
}
// Kotlin
private fun leaveChannel() {
mRtcEngine!!.leaveChannel()
}
你可以在 Agora-Android-Voice-Tutorial-1to1 示例项目的 VoiceChatViewActivity.java 文件中查看完整的源码和代码逻辑。
在 Android 设备中运行该项目。当成功开始语音通话时,你可以听到对方的说话声音。
我们在 GitHub 上提供一个开源的一对多语音通话示例项目 Group-Voice-Call。如果你需要实现一对多群聊场景,可以前往下载或查看源代码。
使用 Agora 语音通话 SDK 开发过程中,你还可以参考如下文档: