クイック スタート: UI ライブラリを使用してチャットを追加する

Azure Communication Services UI ライブラリの使用を開始して、通信エクスペリエンスをアプリケーションに迅速に統合します。 このクイック スタートでは、UI ライブラリ チャット複合をアプリケーションに統合し、アプリ ユーザーのエクスペリエンスを設定する方法について説明します。

Communication Services UI ライブラリにより、アプリケーションに完全なチャット エクスペリエンスが提供されます。 ACS チャット サービスへの接続が処理され、参加者の有無が自動的に更新されます。 開発者は、アプリのユーザー エクスペリエンス内のどこでチャット エクスペリエンスを開始するのかを検討し、必要に応じて ACS リソースのみを作成する必要があります。

Note

Web UI ライブラリに関する詳細なドキュメントとクイックスタートについては、Web UI ライブラリのストーリーブックに関するページにアクセスしてください。

前提条件

次のクイック スタートにアクセスできます

重要

Azure Communication Services のこの機能は、現在プレビュー段階にあります。

プレビューの API と SDK は、サービス レベル アグリーメントなしに提供されます。 運用環境のワークロードには使用しないことをお勧めします。 一部の機能はサポート対象ではなく、機能が制限されることがあります。

詳細については、「Microsoft Azure プレビューの追加利用規約」を確認してください。

オープンソースの Azure Communication Services の Android 用 UI ライブラリで、このクイック スタート用のサンプル Android アプリケーションを取得します。

前提条件

プロジェクトのセットアップ

次のセクションを完了して、クイック スタート プロジェクトを設定します。

新しい Android プロジェクトを作成する

次のように、Android Studio で新しいプロジェクトを作成します。

  1. [ファイル] メニューで [新規作成]>[新しいプロジェクト] を選びます。

  2. [新しいプロジェクト] で、[Empty Activity](空のアクティビティ) プロジェクト テンプレートを選択します。

    [Empty Activity](空のアクティビティ) が選択された、Android Studio の [新しいプロジェクト] ダイアログを示すスクリーンショット。

  3. [次へ] を選択します。

  4. [Empty Activity](空のアクティビティ) で、プロジェクトに UILibraryQuickStart という名前を付けます。 言語として、[Java/Kotlin] を選択します。 最小 SDK として、API 23: Android 6.0 (Marshmallow) 以上を選択します。

  5. [完了] を選択します。

    新しいプロジェクトのオプションが示され、[完了] ボタンが選択されているスクリーンショット。

パッケージのインストール

必要なアプリケーション パッケージをインストールするには、次のセクションを完了します。

依存関係を追加する

アプリ レベルの UILibraryQuickStart/app/build.gradle ファイル (app フォルダー内) に、次の依存関係を追加します。

dependencies {
    ...
    implementation 'com.azure.android:azure-communication-ui-chat:+'
    ...
}

Maven レポジトリの追加

ライブラリを統合するには、Azure パッケージ リポジトリが必要です。

リポジトリを追加するには:

  1. プロジェクトの Gradle スクリプトで、次のリポジトリが追加されていることを確認します。 Android Studio (2020.*) の場合、repositories は、dependencyResolutionManagement(Gradle version 6.8 or greater) 内の settings.gradle にあります。 以前のバージョンの Android Studio (4.*) の場合、repositories は、allprojects{} 内のプロジェクト レベルの build.gradle にあります。

    // dependencyResolutionManagement
    repositories {
        ...
        maven {
            url "https://pkgs.dev.azure.com/MicrosoftDeviceSDK/DuoSDK-Public/_packaging/Duo-SDK-Feed/maven/v1"
        }
        ...
    }
    
  2. プロジェクトを Gradle ファイルと同期します。 プロジェクトを同期するには、[ファイル] メニューの [Sync Project With Gradle Files](プロジェクトを Gradle のファイルと同期する) を選択します。

Activity_main.xml にボタンを追加する

app/src/main/res/layout/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">

    <Button
        android:id="@+id/startButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Launch"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

複合を初期化する

複合を初期化するには:

  1. MainActivity にアクセスします。

  2. 次のコードを追加して、通話用の複合コンポーネントを初期化します。 endpoint,、acsIdentitydisplayNameaccessTokenThreadId のプロパティ (kotlin) または関数 (java) の文字列値を置き換えます。 endpoint は、Azure Communication Services によって提供されるリソースの URL に置き換えます。 acsIdentity および accessToken は、アクセス トークンを作成したときに Azure Communication Services によって提供される値に置き換え、関連する displayName を使用します。 ThreadId は、スレッドを作成したときに返された値に置き換えます。 クイック スタート サンプルを実行してみる前に、REST API 呼び出しまたは az コマンド ライン インターフェイス クライアントを使用して、ユーザーをスレッドに追加することを忘れないでください。追加しないと、クライアントはスレッドに参加するためのアクセスが拒否されます。

package com.example.uilibraryquickstart

import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import com.azure.android.communication.common.CommunicationTokenCredential
import com.azure.android.communication.common.CommunicationTokenRefreshOptions
import com.azure.android.communication.common.CommunicationUserIdentifier
import com.azure.android.communication.ui.chat.ChatAdapter
import com.azure.android.communication.ui.chat.ChatAdapterBuilder
import com.azure.android.communication.ui.chat.presentation.ChatThreadView

class MainActivity : AppCompatActivity() {
    private lateinit var chatAdapter: ChatAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val startButton = findViewById<Button>(R.id.startButton)
        startButton.setOnClickListener { l: View? ->
            val communicationTokenRefreshOptions =
                CommunicationTokenRefreshOptions(
                    { accessToken }, true
                )
            val communicationTokenCredential =
                CommunicationTokenCredential(communicationTokenRefreshOptions)
            chatAdapter = ChatAdapterBuilder()
                .endpoint(endpoint)
                .credential(communicationTokenCredential)
                .identity(CommunicationUserIdentifier(acsIdentity))
                .displayName(displayName)
                .threadId(threadId)
                .build()
            try {
                chatAdapter.connect(this@MainActivity).get()
                val chatView: View = ChatThreadView(this@MainActivity, chatAdapter)
                addContentView(
                    chatView,
                    ViewGroup.LayoutParams(
                        ViewGroup.LayoutParams.MATCH_PARENT,
                        ViewGroup.LayoutParams.MATCH_PARENT
                    )
                )
            } catch (e: Exception) {
                var messageCause: String? = "Unknown error"
                if (e.cause != null && e.cause!!.message != null) {
                    messageCause = e.cause!!.message
                }
                showAlert(messageCause)
            }
        }
    }

    /**
     *
     * @return String endpoint URL from ACS Admin UI, "https://example.domain.com/"
     */
    private val endpoint: String?
        get() = "https://example.domain.com/"

    /**
     *
     * @return String identity of the user joining the chat
     * Looks like "8:acs:a6aada1f-0b1e-47ac-866a-91aae00a1c01_00000015-45ee-bad7-0ea8-923e0d008a89"
     */
    private val acsIdentity: String?
        get() = ""

    /**
     *
     * @return String display name of the user joining the chat
     */
    private val displayName: String?
        get() = ""

    /**
     *
     * @return String secure ACS access token for the current user
     */
    private val accessToken: String?
        get() = ""

    /**
     *
     * @return String id of ACS chat thread to join
     * Looks like "19:AVNnEll25N4KoNtKolnUAhAMu8ntI_Ra03saj0Za0r01@thread.v2"
     */
    private val threadId: String?
        get() = ""

    fun showAlert(message: String?) {
        runOnUiThread {
            AlertDialog.Builder(this@MainActivity)
                .setMessage(message)
                .setTitle("Alert")
                .setPositiveButton(
                    "OK"
                ) { _, i -> }
                .show()
        }
    }
}

コードの実行

Android Studio で、次のようにアプリケーションをビルドして起動します。

  1. [開始操作] を選択します。
  2. チャット クライアントがチャット スレッドに参加し、メッセージの入力と送信を開始できます
  3. クライアントがスレッドに参加できず、chatJoin 失敗エラーが表示された場合は、REST API 呼び出しまたは az コマンド ライン インターフェイスを使用して、ユーザーのアクセス トークンが有効であり、ユーザーがチャット スレッドに追加されていることを確認します。

プロジェクトが Android デバイスでどのように実行されるのかを示す例を示す GIF アニメーション。

重要

Azure Communication Services のこの機能は、現在プレビュー段階にあります。

プレビューの API と SDK は、サービス レベル アグリーメントなしに提供されます。 運用環境のワークロードには使用しないことをお勧めします。 一部の機能はサポート対象ではなく、機能が制限されることがあります。

詳細については、「Microsoft Azure プレビューの追加利用規約」を確認してください。

オープンソースの Azure Communication Services の iOS 用 UI ライブラリで、このクイック スタート用のサンプル iOS アプリケーションを取得します。

前提条件

プロジェクトのセットアップ

次のセクションを完了して、クイック スタート プロジェクトを設定します。

新しい Xcode プロジェクトを作成する

Xcode で新しいプロジェクトを作成します。

  1. [ファイル] メニューで、[新規作成]>[プロジェクト] の順に選択します。

  2. [新しいプロジェクトのテンプレートを選択する] で、[iOS] プラットフォームを選択し、[アプリ] アプリケーション テンプレートを選択します。 クイック スタートでは、UIKit ストーリーボードを使用します。

    [iOS] と [アプリ] テンプレートが選択された、Xcode の新規プロジェクト ダイアログを示すスクリーンショット。

  3. [Choose options for your new project] で、製品名に「UILibraryQuickStart」と入力します。 [Interface] で、[Storyboard] を選択します。 クイック スタートではテストは作成されないため、[Include Tests] (テストを含める) チェック ボックスはオフにしてかまいません。

    Xcode で新しいプロジェクトの設定オプションを示すスクリーンショット。

パッケージとその依存関係をインストールする

  1. (省略可能) MacBook M1 の場合は、Xcode で Rosetta をインストールし、有効にしてください。

  2. プロジェクトのルートディレクトリで、pod init を実行して Podfile を作成します。 エラーが発生した場合は、 CocoaPods を現在のバージョンに更新します。

  3. Podfile に次のコードを追加します。 UILibraryQuickStart を実際のプロジェクト名に置き換えます。

    platform :ios, '14.0'
    
    target 'UILibraryQuickStart' do
        use_frameworks!
        pod 'AzureCommunicationUIChat', '1.0.0-beta.3'
    end
    
  4. pod install --repo-update を実行します。

  5. Xcode で、生成された xcworkspace ファイルを開きます。

ビットコードをオフにする

Xcode プロジェクトの [ビルド設定] で、[Bitcode を有効にする] オプションを [いいえ] に設定します。 設定を見つけるには、フィルターを [Basic] から [すべて] に変更するか、検索バーを使用します。

Bitcode をオフにする [ビルド設定] オプションを示すスクリーンショット。

複合を初期化する

複合を初期化するには:

  1. ViewController にアクセスします。

  2. 次のコードを追加して、チャット用の複合コンポーネントを初期化します。 <USER_ID> をユーザー識別子に置き換えます。 <USER_ACCESS_TOKEN> は、アクセス トークンに置き換えます。 <ENDPOINT_URL> を実際のエンドポイント URL に置き換えます。 <THREAD_ID> は、実際のチャット スレッド ID に置き換えます。 <DISPLAY_NAME> をユーザー名で置き換えます。 (<DISPLAY_NAME> の文字列の長さの制限は 256 文字です)。

    import UIKit
    import AzureCommunicationCommon
    import AzureCommunicationUIChat
    
    class ViewController: UIViewController {
        var chatAdapter: ChatAdapter?
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            let button = UIButton()
            button.contentEdgeInsets = UIEdgeInsets(top: 10.0, left: 20.0, bottom: 10.0, right: 20.0)
            button.layer.cornerRadius = 10
            button.backgroundColor = .systemBlue
            button.setTitle("Start Experience", for: .normal)
            button.addTarget(self, action: #selector(startChatComposite), for: .touchUpInside)
    
            button.translatesAutoresizingMaskIntoConstraints = false
            self.view.addSubview(button)
            button.widthAnchor.constraint(equalToConstant: 200).isActive = true
            button.heightAnchor.constraint(equalToConstant: 50).isActive = true
            button.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
            button.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        }
    
        @objc private func startChatComposite() {
            let communicationIdentifier = CommunicationUserIdentifier("<USER_ID>")
            guard let communicationTokenCredential = try? CommunicationTokenCredential(
                token: "<USER_ACCESS_TOKEN>") else {
                return
            }
    
            self.chatAdapter = ChatAdapter(
                endpoint: "<ENDPOINT_URL>", identifier: communicationIdentifier,
                credential: communicationTokenCredential,
                threadId: "<THREAD_ID>",
                displayName: "<DISPLAY_NAME>")
    
            Task { @MainActor in
                guard let chatAdapter = self.chatAdapter else {
                    return
                }
                try await chatAdapter.connect()
                let chatCompositeViewController = ChatCompositeViewController(
                    with: chatAdapter)
    
                let closeItem = UIBarButtonItem(
                    barButtonSystemItem: .close,
                    target: nil,
                    action: #selector(self.onBackBtnPressed))
                chatCompositeViewController.title = "Chat"
                chatCompositeViewController.navigationItem.leftBarButtonItem = closeItem
    
                let navController = UINavigationController(rootViewController: chatCompositeViewController)
                navController.modalPresentationStyle = .fullScreen
    
                self.present(navController, animated: true, completion: nil)
            }
        }
    
        @objc func onBackBtnPressed() {
            self.dismiss(animated: true, completion: nil)
            Task { @MainActor in
                self.chatAdapter?.disconnect(completionHandler: { [weak self] result in
                    switch result {
                    case .success:
                        self?.chatAdapter = nil
                    case .failure(let error):
                        print("disconnect error \(error)")
                    }
                })
            }
        }
    }
    
    
  3. 画面サイズよりも小さいフレームにチャット ビューを配置する場合、推奨される最小幅は 250、推奨される最小高さは 300 です。

コードの実行

iOS シミュレーターでアプリをビルドして実行するには、[製品]>[実行] の順に選択するか、(⌘-R) キーボード ショートカットを使用します。 次に、シミュレーターでチャット エクスペリエンスを試します。

  1. [開始操作] を選択します。
  2. チャット クライアントがチャット スレッドに参加し、メッセージの入力と送信を開始できます。
  3. クライアントがスレッドに参加できず、chatJoin 失敗エラーが表示された場合は、REST API 呼び出しまたは az コマンド ライン インターフェイスを使用して、ユーザーのアクセス トークンが有効であり、ユーザーがチャット スレッドに追加されていることを確認します。

クイックスタート iOS アプリの最終的な外観を示す GIF アニメーション。

リソースをクリーンアップする

Communication Services サブスクリプションをクリーンアップして解除する場合は、リソースまたはリソース グループを削除できます。

リソース グループを削除すると、それに関連付けられている他のリソースも削除されます。

詳細については、リソースのクリーンアップに関する記事を参照してください。