LoginSignup
3
0

More than 3 years have passed since last update.

AndroidでAmazon Chime SDKを使ってみた(アプリ実装編)

Last updated at Posted at 2021-05-09

はじめに

前回のつづきです。今回は実際にAndroidで実装していきます。開発にはamazon-chime-sdk-androidを用います。

SDKの導入方法

基本的には公式のガイドラインがあるのでその内容通りにセットアップすればOKです。

まずはバイナリファイルの最新のreleaseのもの(amazon-chime-sdkamazon-chime-sdk-media)をダウンロードします。ダウンロードしたファイルは/app/libsにおいておきます。
次にroot projectのbuild.gradleに以下の設定を書き加えます。

build.gradle
...
allprojects {
   repositories {
      jcenter()
      flatDir {
        dirs 'libs'
      }
   }
}
...

あとはappの中のbuild.gradledependencies配下に以下を書き加えます。

build.gradle
implementation(name: 'amazon-chime-sdk', ext: 'aar')
implementation(name: 'amazon-chime-sdk-media', ext: 'aar')

また、compileOptionsが以下のようになっているかも確認しておいてください。

build.gradle
compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}

この設定を行えばSDKの導入は完了です。

アプリについて

アプリの外観は↓のような感じです。ソースコードはこちらで公開しています。

スクリーンショット.jpg

かなり簡素に作ったのであまり実用的ではありませんが、最低限のビデオ通話の機能を使うことができます。
今回はルームのIDを固定してルームを作成して(前回つくったサーバーを使用しています)、その中でユーザー同士の通話機能を実装しています。
ちなみにAmazon Chime SDKの機能をフルに使ったサンプルコードは公式のデモアプリで公開されているので、そちらを参考にするといいと思います。

Amazon Chimeとの通信を開始する

ルームとユーザーの作成を行うAPIを叩くための関数をcoroutinegsonを使って実装しました。

private val gson = Gson()
private val logger = ConsoleLogger(LogLevel.DEBUG)

private val TAG = "apiRequest"

suspend fun joinMeeting(
    ioDispatcher: CoroutineDispatcher,
    meetingUrl: String,
    meetingId: String?,
    attendeeName: String?
): String? {
    return withContext(ioDispatcher) {
        val url = if (meetingUrl.endsWith("/")) meetingUrl else "$meetingUrl/"
        val serverUrl = URL("${url}join")
        try {
            val response = StringBuffer()
            with(serverUrl.openConnection() as HttpURLConnection) {
                requestMethod = "POST"
                doInput = true
                doOutput = true

                val body = gson.toJson(mutableMapOf(
                    "title" to meetingId,
                    "name" to attendeeName
                ))

                setRequestProperty("Content-type", "application/json; charset=utf-8")
                outputStream.use {
                    val input = body.toByteArray()
                    it.write(input, 0, input.size)
                }

                BufferedReader(InputStreamReader(inputStream)).use {
                    var inputLine = it.readLine()
                    while (inputLine != null) {
                        response.append(inputLine)
                        inputLine = it.readLine()
                    }
                    it.close()
                }

                if (responseCode == 200) {
                    response.toString()
                } else {
                    logger.error(TAG, "Unable to join meeting. Response code: $responseCode")
                    null
                }
            }
        } catch (exception: Exception) {
            logger.error(TAG, "There was an exception while joining the meeting: $exception")
            null
        }
    }
}

joinMeetingで返ってきたレスポンスを使ってAmazon Chimeとの通信を行います。このあたりの実装はAmazon Chime SDKを使うことでWebRTCなどの難しい技術を理解せずにアプリケーションを実装することができます。以下はそのコード例です(公式ページより拝借)

// joinMeeting()で返ってきたレスポンスのデータ構造
data class JoinMeetingResponse(
    @SerializedName("JoinInfo") val joinInfo: MeetingInfo)

data class MeetingInfo(
    @SerializedName("Meeting") val meetingResponse: MeetingResponse,
    @SerializedName("Attendee") val attendeeResponse: AttendeeResponse)

data class MeetingResponse(
    @SerializedName("Meeting") val meeting: Meeting)

data class AttendeeResponse(
    @SerializedName("Attendee") val attendee: Attendee)

// Gsonを使ってレスポンスデータをパースする
val joinMeetingResponse = Gson().fromJson(
    response.toString(),
    JoinMeetingResponse::class.java
)

val configuration = MeetingSessionConfiguration(
    CreateMeetingResponse(joinMeetingResponse.joinInfo.meetingResponse.meeting),
    CreateAttendeeResponse(joinMeetingResponse.joinInfo.attendeeResponse.attendee)
)

// DefaultMeetingSessionを実行することでAmazon Chimeとの通信が実行できる
val meetingSession = DefaultMeetingSession(configuration, ConsoleLogger(), applicationContext)

meetingSessionviewModelで管理するといいと思います。あとはmeetingSessionで以下を実行するとビデオ通話が開始されます。(これも公式より抜粋

val audioVideo = meetingSession.audioVideo

// Start audio and video clients.
audioVideo.start()

// Start receiving remote video.
audioVideo.startRemoteVideo()

// Start sending local video.
audioVideo.startLocalVideo()

// Switch camera for local video between front and back.
audioVideo.switchCamera()

ビデオタイルを描画する

ビデオタイル(ビデオチャットアプリの各カメラ映像)をビューに表示させるためにVideoRenderViewを使います。このviewへのビデオ映像のbindを行うために.bindVideoView(videoRenderView, tileId)を実行します。以下のような感じで実装しました。

audioVideo.addVideoTileObserver(this)

private fun showVideoTile(tileState: VideoTileState) {
    val activity = activity as Context
    val defaultVideoRenderView = DefaultVideoRenderView(activity)
    val layout = view?.findViewById<LinearLayout>(R.id.meeting_layout)
    layout?.addView(defaultVideoRenderView, ViewGroup.LayoutParams(500, 500))
    audioVideo.bindVideoView(defaultVideoRenderView,tileState.tileId)
}

override fun onVideoTileAdded(tileState: VideoTileState) {
    showVideoTile(tileState)
}

override fun onVideoTileRemoved(tileState: VideoTileState) {
    audioVideo.unbindVideoView(tileState.tileId)
}

簡単のため、viewの作成のところ(showVideoTile)は結構雑な実装をしています。onVideoTileAddedonVideoTileRemovedは最初にオブザーバの登録(ここではaudioVideo.addVideoTileObserver(this))を行うことで呼ばれるようになります。
ルームに新しくユーザーが参加するとonVideoTileAddedが呼ばれてそのtileIdが取得できます。この情報を使ってdefaultVideoRenderViewをbindさせることで、ユーザーがルームに入るたびにビデオタイルも追加する形のものが実装できます。

さいごに

Androidでビデオチャットアプリを作るのは(そもそも私自身がAndroidの実装経験が乏しいのも含めて)難しいイメージを持っていたのですが、Amazon Chime SDKを使うと難しい通信周りを意識せずにUIへの実装のみに集中してビデオチャットアプリを作ることができました。
とはいえほんの一部の機能を使っただけなので、他の機能(特にCustomVideo)も触ってみたいですね。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0