Vcubeで通話処理をするためのサンプルアプリを作成したので、記録に残します。
動作環境
- Android studio 4.1.2
- Windows 10 Pro 20H2
agora consoleにてApp idを取得
- agora console にアクセスする
- 会員登録を行い、consoleを表示する
実装
agora SDKを利用するための準備
- ダウンロードページからAndroid VideoSDKをダウンロードし、libsフォルダをプロジェクト内にコピーする
-
AndroidStudioでプロジェクトを開き、app/src/main/build.gradleファイルにsourceSetsとfileTreeを追記する
app/build.gradleandroid { sourceSets{ main{ jniLibs.srcDirs = ['../../../libs'] } } } dependencies { implementation fileTree(dir: '../../../libs', includes: ['*.jar']) }
-
カメラ/マイクの利用を許可する為、AndroidManifest.xmlを修正する
app/AndroidManifest.xml<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.BLUETOOTH" />
-
VideoSDKをプロジェクトに統合する
app/build.gradleallprojects { repositories { ... maven { url 'https://www.jitpack.io' } } }
画面の作成
-
UIの作成
activity_main.xml<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <FrameLayout android:id="@+id/local_video_view_container" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/white" /> <FrameLayout android:id="@+id/remote_video_view_container" android:layout_width="160dp" android:layout_height="160dp" 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" /> </androidx.constraintlayout.widget.ConstraintLayout>
機能の作成
-
Androidクラスをインポート
MainActivity.ktimport androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import android.Manifest; import android.content.pm.PackageManager; import android.view.SurfaceView; import android.widget.FrameLayout;
-
パーミッションの設定
MainActivity.ktprivate val PERMISSION_REQ_ID_RECORD_AUDIO = 22 private val PERMISSION_REQ_ID_CAMERA = PERMISSION_REQ_ID_RECORD_AUDIO + 1 private fun checkSelfPermission(permission: String, requestCode: Int): Boolean { if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, arrayOf(permission), requestCode) return false } return true }
-
Agoraクラスをインポートします。
MainActivity.ktimport io.agora.rtc.IRtcEngineEventHandler; import io.agora.rtc.RtcEngine; import io.agora.rtc.video.VideoCanvas;
-
ビデオハングアウトチャネルのコールバックを作成
MainActivity.kt/Fill the App ID of your project generated on Agora Console./ private val APP_ID = "取得したapp id" /Fill the channel name./ private val CHANNEL = "任意のチャンネル名" /Fill the temp token generated on Agora Console./ private val TOKEN = "" private var mRtcEngine: RtcEngine ?= null private val mRtcEventHandler = object : IRtcEngineEventHandler() { / Listen for the remote user joining the channel to get the uid of the user. / override fun onUserJoined(uid: Int, elapsed: Int) { runOnUiThread { / Call setupRemoteVideo to set the remote video view after getting uid from the onUserJoined callback. / setupRemoteVideo(uid) } } }
-
チャネルに参加するためのコアメソッドを呼び出しを作成
MainActivity.ktprivate fun initializeAndJoinChannel() { try { mRtcEngine = RtcEngine.create(baseContext, APP_ID, mRtcEventHandler) } catch (e: Exception) { } / By default, video is disabled, and you need to call enableVideo to start a video stream. / mRtcEngine!!.enableVideo() val localContainer = findViewById(R.id.local_video_view_container) as FrameLayout / Call CreateRendererView to create a SurfaceView object and add it as a child to the FrameLayout. / val localFrame = RtcEngine.CreateRendererView(baseContext) localContainer.addView(localFrame) / Pass the SurfaceView object to Agora so that it renders the local video. / mRtcEngine!!.setupLocalVideo(VideoCanvas(localFrame, VideoCanvas.RENDER_MODE_FIT, 0)) / Join the channel with a token. / mRtcEngine!!.joinChannel(TOKEN, CHANNEL, "", 0) }
-
リモートユーザーがチャネルに参加するときに、リモートインターフェイスを追加する
MainActivity.ktprivate fun setupRemoteVideo(uid: Int) { val remoteContainer = findViewById(R.id.remote_video_view_container) as FrameLayout val remoteFrame = RtcEngine.CreateRendererView(baseContext) remoteFrame.setZOrderMediaOverlay(true) remoteContainer.addView(remoteFrame) mRtcEngine!!.setupRemoteVideo(VideoCanvas(remoteFrame, VideoCanvas.RENDER_MODE_FIT, uid)) }
-
アプリを開始処理を作成
MainActivity.ktoverride fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // If all the permissions are granted, initialize the RtcEngine object and join a channel. if (checkSelfPermission(Manifest.permission.RECORD_AUDIO, PERMISSION_REQ_ID_RECORD_AUDIO) && checkSelfPermission( Manifest.permission.CAMERA, PERMISSION_REQ_ID_CAMERA )) { initializeAndJoinChannel() } }
-
アプリを閉じたら通話を終了するように作成
MainActivity.ktoverride fun onDestroy() { super.onDestroy() mRtcEngine?.leaveChannel() RtcEngine.destroy() }