次の方法で共有


音声通話をアプリに追加する

Calling SDK を使用して音声およびビデオ通話をアプリに追加することによって、Azure Communication Services の使用を開始します。

この記事では、Windows 用 Azure Communication Services Calling SDK を使用して通話を開始する方法について説明します。

サンプル アプリは、GitHub の Calling SDK for .NET からダウンロードできます。

前提条件

このチュートリアルを完了するには、次の前提条件を用意しておく必要があります。

設定

プロジェクトの作成

Visual Studio の [空白のアプリ (ユニバーサル Windows)] テンプレートを使用して新しいプロジェクトを作成し、シングルページ ユニバーサル Windows プラットフォーム (UWP) アプリをセットアップします。

Visual Studio 内の新しい UWP プロジェクト ウィンドウのスクリーンショット。

パッケージをインストールする

プロジェクトを右選択し、 Manage Nuget Packages に移動して Azure.Communication.Calling.WindowsClient1.4.0 以降をインストールします。 パブリック プレビューのバージョンを表示する場合は、Include Prerelease がオンになっていることを確認します。

アクセスの要求

Package.appxmanifest に移動し、Capabilities を選択します。 インターネットへの着信と発信のアクセスを取得するためめに Internet (Client)Internet (Client & Server) をオンにします。 マイクのオーディオ フィードにアクセスするために Microphone を、カメラのビデオ フィードにアクセスするために Webcam をオンにします。

Visual Studio でインターネットとマイクへのアクセスを要求する画面のスクリーンショット。

アプリのフレームワークを設定する

ロジックをアタッチするには、基本的なレイアウトを構成する必要があります。 発信通話を行うには、呼び出し先のユーザー ID を指定するための TextBox が必要です。 また、[Start/Join call](通話を開始) ボタンと [Hang up](通話終了) ボタンも必要となります。 オーディオの状態とビデオ効果を切り替える機能を示すために、このサンプルには MuteBackgroundBlur チェック ボックスも含まれています。

プロジェクトの MainPage.xaml を開き、GridPage ノードを追加します。

<Page
    x:Class="CallingQuickstart.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:CallingQuickstart"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Width="800" Height="600">

        <!-- Don't forget to replace ‘CallingQuickstart’ with your project’s name -->


    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="16*"/>
            <RowDefinition Height="30*"/>
            <RowDefinition Height="200*"/>
            <RowDefinition Height="60*"/>
            <RowDefinition Height="16*"/>
        </Grid.RowDefinitions>
        <TextBox Grid.Row="1" x:Name="CalleeTextBox" PlaceholderText="Who would you like to call?" TextWrapping="Wrap" VerticalAlignment="Center" Height="30" Margin="10,10,10,10" />

        <Grid x:Name="AppTitleBar" Background="LightSeaGreen">
            <TextBlock x:Name="QuickstartTitle" Text="Calling Quickstart sample title bar" Style="{StaticResource CaptionTextBlockStyle}" Padding="7,7,0,0"/>
        </Grid>

        <Grid Grid.Row="2">
            <Grid.RowDefinitions>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <MediaPlayerElement x:Name="LocalVideo" HorizontalAlignment="Center" Stretch="UniformToFill" Grid.Column="0" VerticalAlignment="Center" AutoPlay="True" />
            <MediaPlayerElement x:Name="RemoteVideo" HorizontalAlignment="Center" Stretch="UniformToFill" Grid.Column="1" VerticalAlignment="Center" AutoPlay="True" />
        </Grid>
        <StackPanel Grid.Row="3" Orientation="Vertical" Grid.RowSpan="2">
            <StackPanel Orientation="Horizontal">
                <Button x:Name="CallButton" Content="Start/Join call" Click="CallButton_Click" VerticalAlignment="Center" Margin="10,0,0,0" Height="40" Width="123"/>
                <Button x:Name="HangupButton" Content="Hang up" Click="HangupButton_Click" VerticalAlignment="Center" Margin="10,0,0,0" Height="40" Width="123"/>
                <CheckBox x:Name="MuteLocal" Content="Mute" Margin="10,0,0,0" Click="MuteLocal_Click" Width="74"/>
            </StackPanel>
        </StackPanel>
        <TextBox Grid.Row="5" x:Name="Stats" Text="" TextWrapping="Wrap" VerticalAlignment="Center" Height="30" Margin="0,2,0,0" BorderThickness="2" IsReadOnly="True" Foreground="LightSlateGray" />
    </Grid>
</Page>

MainPage.xaml.cs を開き、その内容を次の実装に置き換えます。

using Azure.Communication.Calling.WindowsClient;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Threading.Tasks;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Core;
using Windows.Media.Core;
using Windows.Networking.PushNotifications;
using Windows.UI;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

namespace CallingQuickstart
{
    public sealed partial class MainPage : Page
    {
        private const string authToken = "<AUTHENTICATION_TOKEN>";

        private CallClient callClient;
        private CallTokenRefreshOptions callTokenRefreshOptions = new CallTokenRefreshOptions(false);
        private CallAgent callAgent;
        private CommunicationCall call;

        private LocalOutgoingAudioStream micStream;

        #region Page initialization
        public MainPage()
        {
            this.InitializeComponent();
            // Additional UI customization code goes here
        }

        protected override async void OnNavigatedTo(NavigationEventArgs e)
        {
            await InitCallAgentAndDeviceManagerAsync();

            base.OnNavigatedTo(e);
        }
        #endregion

        #region UI event handlers
        private async void CallButton_Click(object sender, RoutedEventArgs e)
        {
            // Start a call
        }

        private async void HangupButton_Click(object sender, RoutedEventArgs e)
        {
            // Hang up a call
        }

        private async void MuteLocal_Click(object sender, RoutedEventArgs e)
        {
            // Toggle mute/unmute audio state of a call
        }
        #endregion

        #region API event handlers
        private async void OnIncomingCallAsync(object sender, IncomingCallReceivedEventArgs args)
        {
            // Handle incoming call event
        }

        private async void OnStateChangedAsync(object sender, PropertyChangedEventArgs args)
        {
            // Handle connected and disconnected state change of a call
        }
        #endregion

        #region Helper methods

        private async Task InitCallAgentAndDeviceManagerAsync()
        {
            //Initialize the call agent and search for devices
        }


        private async Task<CommunicationCall> StartCallAsync(string acsCallee)
        {
            // Start a call to an Azure Communication Services user using the CallAgent and the callee id
        }

        #endregion
    }
}

オブジェクト モデル

次の表に、Azure Communication Services Calling SDK の主要な機能の一部を処理するクラスとインターフェイスを示します。

名前 説明
CallClient CallClient は、Calling SDK へのメイン エントリ ポイントです。
CallAgent CallAgentを使用して、呼び出しを開始および管理します。
CommunicationCall CommunicationCallを使用して、継続的な通話を管理します。
CallTokenCredential CallTokenCredentialをインスタンス化するには、トークン資格情報としてCallAgentを使用します。
CallIdentifier CallIdentifierを使用してユーザーの ID を表します。UserCallIdentifierPhoneNumberCallIdentifierなど、次のいずれかのオプションを使用できます。

クライアントを認証する

通話を発信および受信できるようにするユーザー アクセス トークンで CallAgent インスタンスを初期化し、必要に応じてクライアント デバイス構成のクエリを実行するための DeviceManager インスタンスを取得します。

コードで、<AUTHENTICATION_TOKEN> をユーザー アクセス トークンに置き換えます。 使用可能なトークンがまだない場合は、 ユーザー アクセス トークンを参照してください。

SDK をブートストラップする InitCallAgentAndDeviceManagerAsync 関数を追加します。 このヘルパーは、アプリケーションの要件を満たすようにカスタマイズできます。

        private async Task InitCallAgentAndDeviceManagerAsync()
        {
            this.callClient = new CallClient(new CallClientOptions() {
                Diagnostics = new CallDiagnosticsOptions() { 
                    
                    // make sure to put your project AppName
                    AppName = "CallingQuickstart",

                    AppVersion="1.0",

                    Tags = new[] { "Calling", "ACS", "Windows" }
                    }

                });

            // Set up local audio stream using the first mic enumerated
            var deviceManager = await this.callClient.GetDeviceManagerAsync();
            var mic = deviceManager?.Microphones?.FirstOrDefault();

            micStream = new LocalOutgoingAudioStream();

            var tokenCredential = new CallTokenCredential(authToken, callTokenRefreshOptions);

            var callAgentOptions = new CallAgentOptions()
            {
                DisplayName = $"{Environment.MachineName}/{Environment.UserName}",
            };

            this.callAgent = await this.callClient.CreateCallAgentAsync(tokenCredential, callAgentOptions);

            this.callAgent.IncomingCallReceived += OnIncomingCallAsync;
        }

通話を開始する

StartCallOptions オブジェクトを取得したら、CallAgent c を使用して Azure Communication Services の呼び出しを開始できます。

        private async Task<CommunicationCall> StartCallAsync(string acsCallee)
        {
            var options = new StartCallOptions();
            var call = await this.callAgent.StartCallAsync( new [] { new UserCallIdentifier(acsCallee) }, options);
            return call;
        }

通話を終了する

エンド ユーザーが [ 切断 ] ボタンをクリックすると、現在の呼び出しを終了します。 HangupButton_Clickに実装を追加して呼び出しを終了し、プレビューストリームとビデオ ストリームを停止します。

        private async void HangupButton_Click(object sender, RoutedEventArgs e)
        {
            var call = this.callAgent?.Calls?.FirstOrDefault();
            if (call != null)
            {
                await call.HangUpAsync(new HangUpOptions() { ForEveryone = false });
            }
        }

オーディオのミュート/ミュート解除を切り替える

エンド ユーザーが [ミュート] ボタンをクリックしたときに、発信音声を ミュート します。 MuteLocal_Click に通話をミュートする実装を追加します。

        private async void MuteLocal_Click(object sender, RoutedEventArgs e)
        {
            var muteCheckbox = sender as CheckBox;

            if (muteCheckbox != null)
            {
                var call = this.callAgent?.Calls?.FirstOrDefault();

                if (call != null)
                {
                    if ((bool)muteCheckbox.IsChecked)
                    {
                        await call.MuteOutgoingAudioAsync();
                    }
                    else
                    {
                        await call.UnmuteOutgoingAudioAsync();
                    }
                }

                // Update the UI to reflect the state
            }
        }

電話の着信を受け入れる

IncomingCallReceived イベント シンクは、SDK ブートストラップ ヘルパー InitCallAgentAndDeviceManagerAsync で設定されます。

    this.callAgent.IncomingCallReceived += OnIncomingCallAsync;

ビデオやオーディオのストリームの種類などの、着信通話を受け入れる方法をアプリケーションに構成できます。

        private async void OnIncomingCallAsync(object sender, IncomingCallReceivedEventArgs args)
        {
            var incomingCall = args.IncomingCall;

            var acceptCallOptions = new AcceptCallOptions() { };

            call = await incomingCall.AcceptAsync(acceptCallOptions);
            call.StateChanged += OnStateChangedAsync;
        }

通話状態変更イベントを監視して応答する

StateChanged オブジェクトのCommunicationCall イベントは、進行中の呼び出しが 1 つの状態から別の状態に遷移したときに実行されます。 この変更により、状態の変化を反映したり、アプリケーションでビジネス ロジックを実行したりできます。

        private async void OnStateChangedAsync(object sender, PropertyChangedEventArgs args)
        {
            var call = sender as CommunicationCall;

            if (call != null)
            {
                var state = call.State;

                // Update the UI

                switch (state)
                {
                    case CallState.Connected:
                        {
                            await call.StartAudioAsync(micStream);

                            break;
                        }
                    case CallState.Disconnected:
                        {
                            call.StateChanged -= OnStateChangedAsync;

                            call.Dispose();

                            break;
                        }
                    default: break;
                }
            }
        }

通話ボタンが機能するようにする

Callee ID が null ではない、または空ではない場合、通話を開始できます。

OnStateChangedAsync アクションを使用して通話状態を変更する必要があります。


    private async void CallButton_Click(object sender, RoutedEventArgs e)
    {
        var callString = CalleeTextBox.Text.Trim();

        if (!string.IsNullOrEmpty(callString))
        {
            call = await StartCallAsync(callString);

            call.StateChanged += OnStateChangedAsync;
        }
    
        
    }

コードの実行

コードは、Visual Studio でビルドして実行できます。 ソリューション プラットフォームについては、ARM64x64x86 をサポートしています。

送信呼び出しを行うには、テキスト フィールドにユーザー ID を指定し、[ 通話の開始/参加 ] ボタンをクリックします。 8:echo123を呼び出すと、エコー ボットに接続されます。 この機能を使用して、オーディオ デバイスが動作していることを確認します。

UWP クイックスタート アプリの実行を示すスクリーンショット

この記事では、JavaScript 用 Azure Communication Services Calling SDK を使用して呼び出しを開始する方法について説明します。

サンプル コード

サンプル アプリは、GitHub から1対1の音声通話をアプリケーションに追加するをダウンロードできます。

注意

Azure Communication Services UI ライブラリを使用して、Azure Communication Services ユーザーへの発信呼び出しにアクセスします。 この UI ライブラリによって、開発者は VoIP 有効の呼び出しクライアントをわずか数行のコードでアプリケーションに追加できます。

前提条件

セットアップ

新しい Node.js アプリケーションを作成する

ターミナルまたはコマンド ウィンドウを開き、アプリ用の新しいディレクトリを作成し、そこに移動します。

mkdir calling-quickstart
cd calling-quickstart

既定の設定で npm init -y を実行して、package.json ファイルを作成します。

npm init -y

パッケージをインストールする

npm install コマンドを使用して、JavaScript 用の Azure Communication Services Calling SDK をインストールします。

npm install @azure/communication-common --save
npm install @azure/communication-calling --save

--save オプションを使用すると、package.json ファイル内の依存関係としてライブラリが表示されます。

アプリのフレームワークを設定する

この記事では、webpack を使用してアプリケーション資産をバンドルします。 次のコマンドを実行して、 webpackwebpack-cli、および webpack-dev-server npm パッケージをインストールし、 package.jsonの開発依存関係として一覧表示します。

npm install copy-webpack-plugin@^11.0.0 webpack@^5.88.2 webpack-cli@^5.1.4 webpack-dev-server@^4.15.1 --save-dev

index.html ファイルに追加する必要がある HTML を次に示します。

<!DOCTYPE html>
<html>
  <head>
    <title>Communication Client - Calling Sample</title>
  </head>
  <body>
    <h4>Azure Communication Services</h4>
    <h1>Calling Quickstart</h1>
    <input 
      id="token-input"
      type="text"
      placeholder="User access token"
      style="margin-bottom:1em; width: 200px;"
    />
    </div>
    <button id="token-submit" type="button">
        Submit
    </button>
    <input 
      id="callee-id-input"
      type="text"
      placeholder="Who would you like to call?"
      style="margin-bottom:1em; width: 200px; display: block;"
    />
    <div>
      <button id="call-button" type="button" disabled="true">
        Start Call
      </button>
      &nbsp;
      <button id="accept-call-button" type="button" disabled="true">
        Accept Call
      </button>
      &nbsp;
      <button id="hang-up-button" type="button" disabled="true">
        Hang Up
      </button>
    </div>
    <script src="./main.js"></script>
  </body>
</html>

このクイックスタートのアプリケーション ロジックを格納するために、index.js という名前のファイルを自分のプロジェクトのルート ディレクトリに作成します。 次のコードを追加して、通話クライアントをインポートし、ビジネス ロジックをアタッチできるように DOM 要素への参照を取得します。

import { CallClient } from "@azure/communication-calling";
import { AzureCommunicationTokenCredential } from '@azure/communication-common';

let call;
let incomingCall;
let callAgent;
let deviceManager;
let tokenCredential;
const userToken = document.getElementById("token-input"); 
const calleeInput = document.getElementById("callee-id-input");
const submitToken = document.getElementById("token-submit");
const callButton = document.getElementById("call-button");
const hangUpButton = document.getElementById("hang-up-button");
const acceptCallButton = document.getElementById('accept-call-button');

オブジェクト モデル

Azure Communication Services Calling SDK の主な機能のいくつかは、次のクラスとインターフェイスによって処理されます。

名前 説明
CallClient CallClient は、Calling SDK へのメイン エントリ ポイントです。
CallAgent CallAgentを使用して、呼び出しを開始および管理します。
AzureCommunicationTokenCredential AzureCommunicationTokenCredential クラスを使用して、CommunicationTokenCredentialをインスタンス化するCallAgent インターフェイスを実装します。

クライアントを認証する

テキスト フィールドにリソースの有効なユーザー アクセス トークンを入力し、[送信] をクリックする必要 があります。 使用可能なトークンがまだない場合は、 ユーザー アクセス トークンを参照してください。 CallClientを使用して、アプリが呼び出しを行って受信できるようにするCallAgentを使用して、CommunicationTokenCredential インスタンスを初期化します。

次のコードを app.js に追加します。

submitToken.addEventListener("click", async () => {
  const callClient = new CallClient();
  const userTokenCredential = userToken.value;
    try {
      tokenCredential = new AzureCommunicationTokenCredential(userTokenCredential);
      callAgent = await callClient.createCallAgent(tokenCredential);
      deviceManager = await callClient.getDeviceManager();
      await deviceManager.askDevicePermission({ audio: true });
      callButton.disabled = false;
      submitToken.disabled = true;
      // Listen for an incoming call to accept.
      callAgent.on('incomingCall', async (args) => {
        try {
          incomingCall = args.incomingCall;
          acceptCallButton.disabled = false;
          callButton.disabled = true;
        } catch (error) {
          console.error(error);
        }
      });
    } catch(error) {
      window.alert("Please submit a valid token!");
    }
})

通話を開始する

エンド ユーザーが callButtonをクリックしたときに呼び出しを開始するイベント ハンドラーを追加します。

callButton.addEventListener("click", () => {
  // start a call
  const userToCall = calleeInput.value;
  call = callAgent.startCall(
      [{ id: userToCall }],
      {}
  );
  // toggle button states
  hangUpButton.disabled = false;
  callButton.disabled = true;
});

通話を終了する

エンド ユーザーが hangUpButtonをクリックしたときに、現在の呼び出しを終了するイベント リスナーを追加します。

hangUpButton.addEventListener("click", () => {
  // end the current call
  // The `forEveryone` property ends the call for all call participants.
  call.hangUp({ forEveryone: true });

  // toggle button states
  hangUpButton.disabled = true;
  callButton.disabled = false;
  submitToken.disabled = false;
  acceptCallButton.disabled = true;
});

電話の着信を受け入れる

acceptCallButtonへの着信呼び出しを受け入れるイベント リスナーを追加します。

acceptCallButton.onclick = async () => {
  try {
    call = await incomingCall.accept();
    acceptCallButton.disabled = true;
    hangUpButton.disabled = false;
  } catch (error) {
    console.error(error);
  }
}

webpack ローカル サーバー コードを追加する

このクイック スタートのローカル サーバー ロジックを含む webpack.config.js という名前のファイルをプロジェクトのルート ディレクトリに作成します。 webpack.config.js に次のコードを追加します。

const path = require('path');
const CopyPlugin = require("copy-webpack-plugin");

module.exports = {
    mode: 'development',
    entry: './index.js',
    output: {
        filename: 'main.js',
        path: path.resolve(__dirname, 'dist'),
    },
    devServer: {
        static: {
            directory: path.join(__dirname, './')
        },
    },
    plugins: [
        new CopyPlugin({
            patterns: [
                './index.html'
            ]
        }),
    ]
};

コードの実行

コマンド npx webpack serve --config webpack.config.js を使ってアプリケーションを実行します。

ブラウザーを開き、http://localhost:8080/. に移動します 次の画面が表示されます。

完成した JavaScript アプリケーションのスクリーンショット。

発信 VOIP 通話を行うには、有効なユーザー アクセス トークンとユーザー ID を対応するテキスト フィールドに指定し、 [Start Call](通話の開始) ボタンをクリックします。

8:echo123を呼び出すとエコー ボットに接続されます。これにより、オーディオ デバイスが動作していることを開始して確認できます。 {id: '8:echo123'}CallAgent.startCall() API に渡してエコー ボットを呼び出します。

Azure Communication Services 通信のユーザーを呼び出すには、{communicationUserId: 'ACS_USER_ID'}CallAgent.startCall() API に渡します。

この記事では、Android 用 Azure Communication Services Calling SDK を使用して通話を開始する方法について説明します。

サンプル コード

サンプル アプリは、Android アプリへの 音声通話の追加に関するページの GitHub からダウンロードできます。

前提条件

セットアップ

空のアクティビティで Android アプリを作成する

Android Studio で、[ 新しい Android Studio プロジェクトの開始 ] を選択します。

Android Studio で [Start a new Android Studio project]\(新しい Android Studio プロジェクトを開始する\) ボタンが選択された状態を示すスクリーンショット。

[電話とタブレット] の [空のビューアクティビティ] プロジェクト テンプレートを選択します。

プロジェクト テンプレート画面で [Empty Activity]\(空のアクティビティ\) オプションが選択された状態を示すスクリーンショット。

最小 SDK はAPI 26: Android 8.0(Oreo)以上を選択してください。

プロジェクト テンプレート画面 2 で [Empty Activity]\(空のアクティビティ\) オプションが選択された状態を示すスクリーンショット。

パッケージをインストールする

プロジェクト settings.gradle.kts を見つけて、mavenCentral()pluginManagement で、リポジトリの一覧に dependencyResolutionManagement が表示されていることを確認します。

pluginManagement {
    repositories {
    ...
        mavenCentral()
    ...
    }
}

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
    ...
        mavenCentral()
    }
}

次に、モジュール レベルの build.gradle で、依存関係と android セクションに次の行を追加します。

android {
    ...
    
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    ...
    implementation ("com.azure.android:azure-communication-calling:2.6.0")
    ...
}

アプリケーション マニフェストにアクセス許可を追加する

呼び出しに必要なアクセス許可を要求するには、アプリケーション マニフェスト (app/src/main/AndroidManifest.xml) で宣言する必要があります。 ファイルの内容を次のコードに置き換えます。

    <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.contoso.acsquickstart">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <!--Our Calling SDK depends on the Apache HTTP SDK.
When targeting Android SDK 28+, this library needs to be explicitly referenced.
See https://developer.android.com/about/versions/pie/android-9.0-changes-28#apache-p-->
        <uses-library android:name="org.apache.http.legacy" android:required="false"/>
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
    

アプリのレイアウトを設定する

必要な入力は、通話先 ID のテキスト入力と電話を掛けるためのボタンの 2 つです。 これらの入力は、デザイナーを使用するかレイアウトの xml を編集して追加できます。 ID に call_button、テキスト入力に callee_id を使用してボタンを作成します。 (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/call_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="16dp"
        android:text="Call"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

    <EditText
        android:id="@+id/callee_id"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:ems="10"
        android:hint="Callee Id"
        android:inputType="textPersonName"
        android:minHeight="48dp"
        app:layout_constraintBottom_toTopOf="@+id/call_button"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

メイン アクティビティのスキャフォールディングとバインドを作成する

レイアウトが完了したら、アクティビティのバインドと基本的なスキャフォールディングを追加できます。 このアクティビティを使用して、実行時のアクセス許可の要求、通話エージェントの作成、ボタンが押されたときの通話の発信を行います。 それぞれについては、その独自のセクションに説明があります。 onCreate メソッドがオーバーライドされて、getAllPermissionscreateAgent が呼び出され、通話ボタンのバインドが追加されます。 このイベントは、アクティビティの作成時に 1 回だけ行われます。 詳細については、 onCreateの「 アクティビティライフサイクルについて」を参照してください。

MainActivity.java に移動し、内容を次のコードに置き換えます。

package com.contoso.acsquickstart;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import android.media.AudioManager;
import android.Manifest;
import android.content.pm.PackageManager;

import android.os.Bundle;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import com.azure.android.communication.common.CommunicationUserIdentifier;
import com.azure.android.communication.common.CommunicationTokenCredential;
import com.azure.android.communication.calling.CallAgent;
import com.azure.android.communication.calling.CallClient;
import com.azure.android.communication.calling.StartCallOptions;


import java.util.ArrayList;
import java.util.Arrays;

public class MainActivity extends AppCompatActivity {
    
    private CallAgent callAgent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        getAllPermissions();
        createAgent();
        
        // Bind call button to call `startCall`
        Button callButton = findViewById(R.id.call_button);
        callButton.setOnClickListener(l -> startCall());
        
        setVolumeControlStream(AudioManager.STREAM_VOICE_CALL);
    }

    /**
     * Request each required permission if the app doesn't already have it.
     */
    private void getAllPermissions() {
        // See section on requesting permissions
    }

    /**
      * Create the call agent for placing calls
      */
    private void createAgent() {
        // See section on creating the call agent
    }

    /**
     * Place a call to the callee id provided in `callee_id` text input.
     */
    private void startCall() {
        // See section on starting the call
    }
}

実行時にアクセス許可を要求する

Android 6.0 以上 (API レベル 23) と targetSdkVersion 23 以上では、アプリのインストール時ではなく、実行時にアクセス許可が付与されます。 これをサポートするために、getAllPermissions を実装して、必要なアクセス許可ごとに ActivityCompat.checkSelfPermissionActivityCompat.requestPermissions を呼び出すことができます。

/**
 * Request each required permission if the app doesn't already have it.
 */
private void getAllPermissions() {
    String[] requiredPermissions = new String[]{android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAMERA, android.Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_PHONE_STATE};

    ArrayList<String> permissionsToAskFor = new ArrayList<>();

    for (String permission : requiredPermissions) {
        if (ActivityCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
            permissionsToAskFor.add(permission);
        }
    }

    if (!permissionsToAskFor.isEmpty()) {
        ActivityCompat.requestPermissions(this, permissionsToAskFor.toArray(new String[0]), 1);
    }
}

注意

アプリを設計するときは、これらのアクセス許可を要求するタイミングを検討してください。 アクセス許可は、事前ではなく、必要に応じて要求する必要があります。 詳細については、「 Android のアクセス許可」を参照してください。

オブジェクト モデル

Azure Communication Services Calling SDK の主な機能のいくつかは、次のクラスとインターフェイスによって処理されます。

名前 説明
allClient CallClient は、Calling SDK へのメイン エントリ ポイントです。
CallAgent CallAgentを使用して、呼び出しを開始および管理します。
CommunicationTokenCredential CommunicationTokenCredentialをインスタンス化するには、トークン資格情報としてCallAgentを使用します。
CommunicationIdentifier 通話の一部となる可能性のあるさまざまな種類の参加者には、 CommunicationIdentifier を使用します。

ユーザー アクセス トークンからエージェントを作成する

認証された通話エージェントは、ユーザー トークンを使用してインスタンス化できます。 このトークンは、アプリケーションに固有の認証を持つサービスから生成されます。 詳細については、「 ユーザー アクセス トークン」を参照してください。

この記事では、 <User_Access_Token> を、Azure Communication Service リソース用に生成されたユーザー アクセス トークンに置き換えます。


/**
 * Create the call agent for placing calls
 */
private void createAgent() {
    String userToken = "<User_Access_Token>";

    try {
            CommunicationTokenCredential credential = new CommunicationTokenCredential(userToken);
            callAgent = new CallClient().createCallAgent(getApplicationContext(), credential).get();
    } catch (Exception ex) {
        Toast.makeText(getApplicationContext(), "Failed to create call agent.", Toast.LENGTH_SHORT).show();
    }
}

通話エージェントを使用して通話を開始する

呼び出し先 ID と呼び出しオプションの一覧を指定する必要がある通話エージェントを介して通話を発信できます。 この記事では、ビデオのない既定の通話オプションと、テキスト入力からの 1 つの呼び出し先 ID を使用します。

/**
 * Place a call to the callee id provided in `callee_id` text input.
 */
private void startCall() {
    EditText calleeIdView = findViewById(R.id.callee_id);
    
    String calleeId = calleeIdView.getText().toString();

    StartCallOptions options = new StartCallOptions();

    callAgent.startCall(
            getApplicationContext(),
            Arrays.asList(new CommunicationUserIdentifier[]{new CommunicationUserIdentifier(calleeId)}),
            options);
}

アプリを起動してエコー ボットを呼び出す

ツール バーの [アプリの実行] ボタン (Shift + F10) を使用して アプリ を起動できます。 8:echo123を呼び出して通話できることを確認します。 録音済みのメッセージが再生され、メッセージが繰り返されます。

完成したアプリケーションを示すスクリーンショット。

この記事では、iOS 用 Azure Communication Services Calling SDK を使用して呼び出しを開始する方法について説明します。

サンプル コード

サンプル アプリは、 GitHub の Calling SDK for iOS からダウンロードできます。

前提条件

このチュートリアルを完了するには、次の前提条件を用意しておく必要があります。

設定

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

Xcode で、新しい iOS プロジェクトを作成し、 [App](アプリ) テンプレートを選択します。 このチュートリアルでは SwiftUI フレームワークを使用します。そのため、 [言語][Swift] に設定し、 [ユーザー インターフェイス][SwiftUI] に設定する必要があります。 このクイック スタートでは、テストは作成しません。 [Include Tests](テストを含める) チェック ボックスはオフにしてかまいません。

Xcode 内で新しいプロジェクトを作成するウィンドウのスクリーンショット。

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

  1. アプリケーションのポッドファイルを作成するために、ターミナルを開いてプロジェクト フォルダーに移動し、次を実行します。

    pod init

  2. ポッドファイルに次のコードを追加して保存します ("target" がプロジェクトの名前と一致していることを確認してください)。

    platform :ios, '13.0'
    use_frameworks!
    
    target 'AzureCommunicationCallingSample' do
      pod 'AzureCommunicationCalling', '~> 1.0.0'
    end
    
  3. pod install を実行します。

  4. Xcode を使用して .xcworkspace を開きます。

マイクへのアクセスを要求する

デバイスのマイクにアクセスするには、アプリの情報プロパティ リストを NSMicrophoneUsageDescription によって更新する必要があります。 関連する値を、ユーザーからのアクセスを要求するためにシステムによって使用されるダイアログに含まれていた string に設定します。

プロジェクト ツリーの Info.plist のエントリを右クリックし、 [Open As](形式を指定して開く)>[Source Code](ソース コード) の順に選択します。 最上位の <dict> セクションに以下の行を追加してから、ファイルを保存します。

<key>NSMicrophoneUsageDescription</key>
<string>Need microphone access for VOIP calling.</string>

アプリのフレームワークを設定する

プロジェクトの ContentView. swift ファイルを開き、ファイルの先頭に import 宣言を追加して AzureCommunicationCalling library をインポートします。 さらに、AVFoundation をインポートします。このコードは、コード内のオーディオ アクセス許可要求に必要になります。

import AzureCommunicationCalling
import AVFoundation

ContentView 構造体の実装を、ユーザーが通話を開始して終了できるようにする、いくつかの単純な UI コントロールに置き換えます。 このクイック スタートでは、これらのコントロールにビジネス ロジックをアタッチします。

struct ContentView: View {
    @State var callee: String = ""
    @State var callClient: CallClient?
    @State var callAgent: CallAgent?
    @State var call: Call?

    var body: some View {
        NavigationView {
            Form {
                Section {
                    TextField("Who would you like to call?", text: $callee)
                    Button(action: startCall) {
                        Text("Start Call")
                    }.disabled(callAgent == nil)
                    Button(action: endCall) {
                        Text("End Call")
                    }.disabled(call == nil)
                }
            }
            .navigationBarTitle("Calling Quickstart")
        }.onAppear {
            // Initialize call agent
        }
    }

    func startCall() {
        // Ask permissions
        AVAudioSession.sharedInstance().requestRecordPermission { (granted) in
            if granted {
                // Add start call logic
            }
        }
    }

    func endCall() {
        // Add end call logic
    }
}

オブジェクト モデル

Azure Communication Services Calling SDK の主な機能のいくつかは、次のクラスとインターフェイスによって処理されます。

名前 説明
CallClient CallClient は、Calling SDK へのメイン エントリ ポイントです。
CallAgent CallAgent は、通話を開始および管理するために使用されます。
CommunicationTokenCredential CommunicationTokenCredential は、CallAgent をインスタンス化するためのトークン資格情報として使用されます。
CommunicationUserIdentifier CommunicationUserIdentifierは、ユーザーの ID を表すために使用されます。CommunicationUserIdentifierPhoneNumberIdentifier、または次のいずれかのオプションを使用できます。CallingApplication.

クライアントを認証する

ユーザー アクセス トークンを使用して CallAgent インスタンスを初期化します。これにより、電話をかけたり受けたりすることができるようになります。

次のコードでは、<USER ACCESS TOKEN> をリソース用の有効なユーザー アクセス トークンに置き換える必要があります。 まだトークンを入手していない場合は、ユーザー アクセス トークンに関するドキュメントを参照してください。

onAppear コールバックに次のコードを追加します。

var userCredential: CommunicationTokenCredential?
do {
    userCredential = try CommunicationTokenCredential(token: "<USER ACCESS TOKEN>")
} catch {
    print("ERROR: It was not possible to create user credential.")
    return
}

self.callClient = CallClient()

// Creates the call agent
self.callClient?.createCallAgent(userCredential: userCredential!) { (agent, error) in
    if error != nil {
        print("ERROR: It was not possible to create a call agent.")
        return
    }
    else {
        self.callAgent = agent
        print("Call agent successfully created.")
    }
}

通話を開始する

startCall メソッドは、[通話を開始] ボタンがタップされたときに実行されるアクションとして設定されます。 ASACallAgent を使用して通話を開始するように実装を更新します。

func startCall()
{
    // Ask permissions
    AVAudioSession.sharedInstance().requestRecordPermission { (granted) in
        if granted {
            // start call logic
            let callees:[CommunicationIdentifier] = [CommunicationUserIdentifier(self.callee)]
            self.callAgent?.startCall(participants: callees, options: StartCallOptions()) { (call, error) in
                if (error == nil) {
                    self.call = call
                } else {
                    print("Failed to get call object")
                }
            }
        }
    }
}

StartCallOptions のプロパティを使用して、通話の初期オプションを設定することもできます (つまり、マイクをミュートした状態で通話を開始できます)。

通話を終了する

endCall メソッドを実装して、 [通話の終了] ボタンがタップされたときに現在の通話を終了します。

func endCall()
{    
    self.call!.hangUp(options: HangUpOptions()) { (error) in
        if (error != nil) {
            print("ERROR: It was not possible to hangup the call.")
        }
    }
}

コードの実行

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

クイック スタート アプリの最終的な外観

発信 VOIP 通話を行うには、テキスト フィールドにユーザー ID を指定し、 [Start Call](通話の開始) ボタンをタップします。 8:echo123 を呼び出すとエコー ボットに接続されます。この機能は、オーディオ デバイスを起動し、デバイスが機能していることを確認する場合に役立ちます。

注意

通話を初めて行うと、マイクへのアクセスを求めるメッセージが表示されます。 運用アプリケーションでは、 AVAudioSession API を使用して アクセス許可の状態を確認し、アクセス許可 が付与されていない場合のアプリケーションの動作を適切に更新する必要があります。

この記事では、Unity 用 Azure Communication Services Calling SDK を使用して呼び出しを開始する方法について説明します。

サンプル アプリは、GitHub の Calling SDK for .NET からダウンロードできます。

前提条件

設定

プロジェクトの作成

Unity Hub で、2D Core テンプレートを使用して新しいプロジェクトを作成し、Unity プロジェクトを設定します。

Unity エディター内の [New Unity Project] (新しい Unity プロジェクト) ウィンドウを示すスクリーンショット。

パッケージをインストールする

Unity 用の Azure Communication Calling SDK をインストールするには、2 つの方法があります。

  1. パブリック npm フィードから SDK をダウンロードし、Unity エディターのパッケージ マネージャー ([Windows] タブの下にある) でインポートします。

  2. Microsoft からMixed Reality Feature Tool をダウンロードし、Mixed Reality ツール マネージャーを使用してインストールします。

アプリのフレームワークを設定する

ロジックをアタッチするには、基本的なレイアウトを構成する必要があります。 発信通話を行うには、呼び出し先のユーザー ID を指定するための TextBox が必要です。 また、[Start/Join call](通話を開始) ボタンと [Hang up](通話終了) ボタンも必要となります。

プロジェクトで Main という名前の新しいシーンを作成します。

Main.unity ファイルを開き、その内容を次の実装に置き換えます。

Main.Unity コード

Main.unity

%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!29 &1
OcclusionCullingSettings:
m_ObjectHideFlags: 0
serializedVersion: 2
m_OcclusionBakeSettings:
  smallestOccluder: 5
  smallestHole: 0.25
  backfaceThreshold: 100
m_SceneGUID: 00000000000000000000000000000000
m_OcclusionCullingData: {fileID: 0}
--- !u!104 &2
RenderSettings:
m_ObjectHideFlags: 0
serializedVersion: 9
m_Fog: 0
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
m_FogMode: 3
m_FogDensity: 0.01
m_LinearFogStart: 0
m_LinearFogEnd: 300
m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
m_AmbientIntensity: 1
m_AmbientMode: 3
m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
m_SkyboxMaterial: {fileID: 0}
m_HaloStrength: 0.5
m_FlareStrength: 1
m_FlareFadeSpeed: 3
m_HaloTexture: {fileID: 0}
m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
m_DefaultReflectionMode: 0
m_DefaultReflectionResolution: 128
m_ReflectionBounces: 1
m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 0}
m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1}
m_UseRadianceAmbientProbe: 0
--- !u!157 &3
LightmapSettings:
m_ObjectHideFlags: 0
serializedVersion: 12
m_GIWorkflowMode: 1
m_GISettings:
  serializedVersion: 2
  m_BounceScale: 1
  m_IndirectOutputScale: 1
  m_AlbedoBoost: 1
  m_EnvironmentLightingMode: 0
  m_EnableBakedLightmaps: 0
  m_EnableRealtimeLightmaps: 0
m_LightmapEditorSettings:
  serializedVersion: 12
  m_Resolution: 2
  m_BakeResolution: 40
  m_AtlasSize: 1024
  m_AO: 0
  m_AOMaxDistance: 1
  m_CompAOExponent: 1
  m_CompAOExponentDirect: 0
  m_ExtractAmbientOcclusion: 0
  m_Padding: 2
  m_LightmapParameters: {fileID: 0}
  m_LightmapsBakeMode: 1
  m_TextureCompression: 1
  m_FinalGather: 0
  m_FinalGatherFiltering: 1
  m_FinalGatherRayCount: 256
  m_ReflectionCompression: 2
  m_MixedBakeMode: 2
  m_BakeBackend: 0
  m_PVRSampling: 1
  m_PVRDirectSampleCount: 32
  m_PVRSampleCount: 500
  m_PVRBounces: 2
  m_PVREnvironmentSampleCount: 500
  m_PVREnvironmentReferencePointCount: 2048
  m_PVRFilteringMode: 2
  m_PVRDenoiserTypeDirect: 0
  m_PVRDenoiserTypeIndirect: 0
  m_PVRDenoiserTypeAO: 0
  m_PVRFilterTypeDirect: 0
  m_PVRFilterTypeIndirect: 0
  m_PVRFilterTypeAO: 0
  m_PVREnvironmentMIS: 0
  m_PVRCulling: 1
  m_PVRFilteringGaussRadiusDirect: 1
  m_PVRFilteringGaussRadiusIndirect: 5
  m_PVRFilteringGaussRadiusAO: 2
  m_PVRFilteringAtrousPositionSigmaDirect: 0.5
  m_PVRFilteringAtrousPositionSigmaIndirect: 2
  m_PVRFilteringAtrousPositionSigmaAO: 1
  m_ExportTrainingData: 0
  m_TrainingDataDestination: TrainingData
  m_LightProbeSampleCountMultiplier: 4
m_LightingDataAsset: {fileID: 0}
m_LightingSettings: {fileID: 0}
--- !u!196 &4
NavMeshSettings:
serializedVersion: 2
m_ObjectHideFlags: 0
m_BuildSettings:
  serializedVersion: 2
  agentTypeID: 0
  agentRadius: 0.5
  agentHeight: 2
  agentSlope: 45
  agentClimb: 0.4
  ledgeDropHeight: 0
  maxJumpAcrossDistance: 0
  minRegionArea: 2
  manualCellSize: 0
  cellSize: 0.16666667
  manualTileSize: 0
  tileSize: 256
  accuratePlacement: 0
  maxJobWorkers: 0
  preserveTilesOutsideBounds: 0
  debug:
    m_Flags: 0
m_NavMeshData: {fileID: 0}
--- !u!1 &247756367
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 247756370}
- component: {fileID: 247756369}
- component: {fileID: 247756368}
m_Layer: 0
m_Name: EventSystem
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &247756368
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 247756367}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3}
m_Name: 
m_EditorClassIdentifier: 
m_SendPointerHoverToParent: 1
m_HorizontalAxis: Horizontal
m_VerticalAxis: Vertical
m_SubmitButton: Submit
m_CancelButton: Cancel
m_InputActionsPerSecond: 10
m_RepeatDelay: 0.5
m_ForceModuleActive: 0
--- !u!114 &247756369
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 247756367}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3}
m_Name: 
m_EditorClassIdentifier: 
m_FirstSelected: {fileID: 0}
m_sendNavigationEvents: 1
m_DragThreshold: 10
--- !u!4 &247756370
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 247756367}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 2
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &293984669
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 293984671}
- component: {fileID: 293984670}
m_Layer: 0
m_Name: AppManager
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &293984670
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 293984669}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 7c7d18b32fdb6b14e857ebb6d9627958, type: 3}
m_Name: 
m_EditorClassIdentifier: 
callStatus: {fileID: 1529611528}
videoPlayer: {fileID: 0}
--- !u!4 &293984671
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 293984669}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &438770860
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 438770861}
- component: {fileID: 438770863}
- component: {fileID: 438770862}
m_Layer: 5
m_Name: Text (TMP)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &438770861
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 438770860}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1732033234}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &438770862
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 438770860}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name: 
m_EditorClassIdentifier: 
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
  m_PersistentCalls:
    m_Calls: []
m_text: Start Call
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
  serializedVersion: 2
  rgba: 4281479730
m_fontColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
  topLeft: {r: 1, g: 1, b: 1, a: 1}
  topRight: {r: 1, g: 1, b: 1, a: 1}
  bottomLeft: {r: 1, g: 1, b: 1, a: 1}
  bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
  serializedVersion: 2
  rgba: 4294967295
m_fontSize: 24
m_fontSizeBase: 24
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 2
m_VerticalAlignment: 512
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_enableWordWrapping: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 1
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!222 &438770863
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 438770860}
m_CullTransparentMesh: 1
--- !u!1 &519420028
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 519420032}
- component: {fileID: 519420031}
- component: {fileID: 519420029}
m_Layer: 0
m_Name: Main Camera
m_TagString: MainCamera
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!81 &519420029
AudioListener:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 519420028}
m_Enabled: 1
--- !u!20 &519420031
Camera:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 519420028}
m_Enabled: 1
serializedVersion: 2
m_ClearFlags: 2
m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
m_projectionMatrixMode: 1
m_GateFitMode: 2
m_FOVAxisMode: 0
m_SensorSize: {x: 36, y: 24}
m_LensShift: {x: 0, y: 0}
m_FocalLength: 50
m_NormalizedViewPortRect:
  serializedVersion: 2
  x: 0
  y: 0
  width: 1
  height: 1
near clip plane: 0.3
far clip plane: 1000
field of view: 60
orthographic: 1
orthographic size: 5
m_Depth: -1
m_CullingMask:
  serializedVersion: 2
  m_Bits: 4294967295
m_RenderingPath: -1
m_TargetTexture: {fileID: 0}
m_TargetDisplay: 0
m_TargetEye: 0
m_HDR: 1
m_AllowMSAA: 0
m_AllowDynamicResolution: 0
m_ForceIntoRT: 0
m_OcclusionCulling: 0
m_StereoConvergence: 10
m_StereoSeparation: 0.022
--- !u!4 &519420032
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 519420028}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: -10}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &857336305
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 857336306}
- component: {fileID: 857336309}
- component: {fileID: 857336308}
- component: {fileID: 857336307}
m_Layer: 5
m_Name: Placeholder
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &857336306
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 857336305}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1787936407}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &857336307
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 857336305}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3}
m_Name: 
m_EditorClassIdentifier: 
m_IgnoreLayout: 1
m_MinWidth: -1
m_MinHeight: -1
m_PreferredWidth: -1
m_PreferredHeight: -1
m_FlexibleWidth: -1
m_FlexibleHeight: -1
m_LayoutPriority: 1
--- !u!114 &857336308
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 857336305}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name: 
m_EditorClassIdentifier: 
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
  m_PersistentCalls:
    m_Calls: []
m_text: Who Would you like to call?
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
  serializedVersion: 2
  rgba: 2150773298
m_fontColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 0.5}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
  topLeft: {r: 1, g: 1, b: 1, a: 1}
  topRight: {r: 1, g: 1, b: 1, a: 1}
  bottomLeft: {r: 1, g: 1, b: 1, a: 1}
  bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
  serializedVersion: 2
  rgba: 4294967295
m_fontSize: 14
m_fontSizeBase: 14
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 2
m_HorizontalAlignment: 1
m_VerticalAlignment: 256
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_enableWordWrapping: 0
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 1
m_enableExtraPadding: 1
checkPaddingRequired: 0
m_isRichText: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!222 &857336309
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 857336305}
m_CullTransparentMesh: 1
--- !u!1 &963546686
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 963546687}
- component: {fileID: 963546690}
- component: {fileID: 963546689}
- component: {fileID: 963546688}
m_Layer: 5
m_Name: InputField (TMP)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &963546687
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 963546686}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 1787936407}
m_Father: {fileID: 1843906927}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0.00002861, y: 327}
m_SizeDelta: {x: 1337.7578, y: 71.4853}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &963546688
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 963546686}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 2da0c512f12947e489f739169773d7ca, type: 3}
m_Name: 
m_EditorClassIdentifier: 
m_Navigation:
  m_Mode: 3
  m_WrapAround: 0
  m_SelectOnUp: {fileID: 0}
  m_SelectOnDown: {fileID: 0}
  m_SelectOnLeft: {fileID: 0}
  m_SelectOnRight: {fileID: 0}
m_Transition: 1
m_Colors:
  m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
  m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
  m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
  m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
  m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
  m_ColorMultiplier: 1
  m_FadeDuration: 0.1
m_SpriteState:
  m_HighlightedSprite: {fileID: 0}
  m_PressedSprite: {fileID: 0}
  m_SelectedSprite: {fileID: 0}
  m_DisabledSprite: {fileID: 0}
m_AnimationTriggers:
  m_NormalTrigger: Normal
  m_HighlightedTrigger: Highlighted
  m_PressedTrigger: Pressed
  m_SelectedTrigger: Selected
  m_DisabledTrigger: Disabled
m_Interactable: 1
m_TargetGraphic: {fileID: 963546689}
m_TextViewport: {fileID: 1787936407}
m_TextComponent: {fileID: 1676708954}
m_Placeholder: {fileID: 857336308}
m_VerticalScrollbar: {fileID: 0}
m_VerticalScrollbarEventHandler: {fileID: 0}
m_LayoutGroup: {fileID: 0}
m_ScrollSensitivity: 1
m_ContentType: 0
m_InputType: 0
m_AsteriskChar: 42
m_KeyboardType: 0
m_LineType: 0
m_HideMobileInput: 0
m_HideSoftKeyboard: 0
m_CharacterValidation: 0
m_RegexValue: 
m_GlobalPointSize: 14
m_CharacterLimit: 0
m_OnEndEdit:
  m_PersistentCalls:
    m_Calls: []
m_OnSubmit:
  m_PersistentCalls:
    m_Calls: []
m_OnSelect:
  m_PersistentCalls:
    m_Calls: []
m_OnDeselect:
  m_PersistentCalls:
    m_Calls: []
m_OnTextSelection:
  m_PersistentCalls:
    m_Calls: []
m_OnEndTextSelection:
  m_PersistentCalls:
    m_Calls: []
m_OnValueChanged:
  m_PersistentCalls:
    m_Calls:
    - m_Target: {fileID: 293984670}
      m_TargetAssemblyTypeName: CallClientHost, Assembly-CSharp
      m_MethodName: set_CalleeIdentity
      m_Mode: 0
      m_Arguments:
        m_ObjectArgument: {fileID: 0}
        m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
        m_IntArgument: 0
        m_FloatArgument: 0
        m_StringArgument: 
        m_BoolArgument: 0
      m_CallState: 2
m_OnTouchScreenKeyboardStatusChanged:
  m_PersistentCalls:
    m_Calls: []
m_CaretColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
m_CustomCaretColor: 0
m_SelectionColor: {r: 0.65882355, g: 0.80784315, b: 1, a: 0.7529412}
m_Text: 
m_CaretBlinkRate: 0.85
m_CaretWidth: 1
m_ReadOnly: 0
m_RichText: 1
m_GlobalFontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_OnFocusSelectAll: 1
m_ResetOnDeActivation: 1
m_RestoreOriginalTextOnEscape: 1
m_isRichTextEditingAllowed: 0
m_LineLimit: 0
m_InputValidator: {fileID: 0}
--- !u!114 &963546689
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 963546686}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name: 
m_EditorClassIdentifier: 
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
  m_PersistentCalls:
    m_Calls: []
m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!222 &963546690
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 963546686}
m_CullTransparentMesh: 1
--- !u!1 &1184525248
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1184525249}
- component: {fileID: 1184525251}
- component: {fileID: 1184525250}
m_Layer: 5
m_Name: Status Header
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1184525249
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1184525248}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1843906927}
m_RootOrder: 3
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: -23, y: -303}
m_SizeDelta: {x: 159.05, y: 33.5037}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &1184525250
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1184525248}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name: 
m_EditorClassIdentifier: 
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
  m_PersistentCalls:
    m_Calls: []
m_text: Status
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
  serializedVersion: 2
  rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
  topLeft: {r: 1, g: 1, b: 1, a: 1}
  topRight: {r: 1, g: 1, b: 1, a: 1}
  bottomLeft: {r: 1, g: 1, b: 1, a: 1}
  bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
  serializedVersion: 2
  rgba: 4294967295
m_fontSize: 24
m_fontSizeBase: 24
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 1
m_VerticalAlignment: 256
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_enableWordWrapping: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 1
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 2.5243988, z: 10.097656, w: -2.5243645}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!222 &1184525251
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1184525248}
m_CullTransparentMesh: 1
--- !u!1 &1332239153
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1332239154}
- component: {fileID: 1332239157}
- component: {fileID: 1332239156}
- component: {fileID: 1332239155}
m_Layer: 5
m_Name: Hang Up Button
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1332239154
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1332239153}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 1917486034}
m_Father: {fileID: 1843906927}
m_RootOrder: 2
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: -277, y: -329}
m_SizeDelta: {x: 212.1357, y: 53.698}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &1332239155
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1332239153}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
m_Name: 
m_EditorClassIdentifier: 
m_Navigation:
  m_Mode: 3
  m_WrapAround: 0
  m_SelectOnUp: {fileID: 0}
  m_SelectOnDown: {fileID: 0}
  m_SelectOnLeft: {fileID: 0}
  m_SelectOnRight: {fileID: 0}
m_Transition: 1
m_Colors:
  m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
  m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
  m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
  m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
  m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
  m_ColorMultiplier: 1
  m_FadeDuration: 0.1
m_SpriteState:
  m_HighlightedSprite: {fileID: 0}
  m_PressedSprite: {fileID: 0}
  m_SelectedSprite: {fileID: 0}
  m_DisabledSprite: {fileID: 0}
m_AnimationTriggers:
  m_NormalTrigger: Normal
  m_HighlightedTrigger: Highlighted
  m_PressedTrigger: Pressed
  m_SelectedTrigger: Selected
  m_DisabledTrigger: Disabled
m_Interactable: 1
m_TargetGraphic: {fileID: 1332239156}
m_OnClick:
  m_PersistentCalls:
    m_Calls:
    - m_Target: {fileID: 293984670}
      m_TargetAssemblyTypeName: AppManager, Assembly-CSharp
      m_MethodName: HangupButton_Click
      m_Mode: 1
      m_Arguments:
        m_ObjectArgument: {fileID: 0}
        m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
        m_IntArgument: 0
        m_FloatArgument: 0
        m_StringArgument: 
        m_BoolArgument: 0
      m_CallState: 2
--- !u!114 &1332239156
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1332239153}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name: 
m_EditorClassIdentifier: 
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
  m_PersistentCalls:
    m_Calls: []
m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!222 &1332239157
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1332239153}
m_CullTransparentMesh: 1
--- !u!1 &1529611526
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1529611527}
- component: {fileID: 1529611529}
- component: {fileID: 1529611528}
m_Layer: 5
m_Name: Status
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1529611527
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1529611526}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1843906927}
m_RootOrder: 4
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: -2.525, y: -344.75}
m_SizeDelta: {x: 200, y: 50}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &1529611528
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1529611526}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name: 
m_EditorClassIdentifier: 
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
  m_PersistentCalls:
    m_Calls: []
m_text: Disconnected
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
  serializedVersion: 2
  rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
  topLeft: {r: 1, g: 1, b: 1, a: 1}
  topRight: {r: 1, g: 1, b: 1, a: 1}
  bottomLeft: {r: 1, g: 1, b: 1, a: 1}
  bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
  serializedVersion: 2
  rgba: 4294967295
m_fontSize: 30
m_fontSizeBase: 30
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 1
m_VerticalAlignment: 256
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_enableWordWrapping: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 1
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: -25.861023, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!222 &1529611529
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1529611526}
m_CullTransparentMesh: 1
--- !u!1 &1676708952
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1676708953}
- component: {fileID: 1676708955}
- component: {fileID: 1676708954}
m_Layer: 5
m_Name: Text
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1676708953
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1676708952}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1787936407}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &1676708954
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1676708952}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name: 
m_EditorClassIdentifier: 
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
  m_PersistentCalls:
    m_Calls: []
m_text: "\u200B"
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
  serializedVersion: 2
  rgba: 4281479730
m_fontColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
  topLeft: {r: 1, g: 1, b: 1, a: 1}
  topRight: {r: 1, g: 1, b: 1, a: 1}
  bottomLeft: {r: 1, g: 1, b: 1, a: 1}
  bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
  serializedVersion: 2
  rgba: 4294967295
m_fontSize: 14
m_fontSizeBase: 14
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 1
m_VerticalAlignment: 256
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_enableWordWrapping: 0
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 1
m_enableExtraPadding: 1
checkPaddingRequired: 0
m_isRichText: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!222 &1676708955
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1676708952}
m_CullTransparentMesh: 1
--- !u!1 &1732033233
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1732033234}
- component: {fileID: 1732033237}
- component: {fileID: 1732033236}
- component: {fileID: 1732033235}
m_Layer: 5
m_Name: Start Call Button
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1732033234
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1732033233}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 438770861}
m_Father: {fileID: 1843906927}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: -525.52, y: -329}
m_SizeDelta: {x: 212.1357, y: 53.698}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &1732033235
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1732033233}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
m_Name: 
m_EditorClassIdentifier: 
m_Navigation:
  m_Mode: 3
  m_WrapAround: 0
  m_SelectOnUp: {fileID: 0}
  m_SelectOnDown: {fileID: 0}
  m_SelectOnLeft: {fileID: 0}
  m_SelectOnRight: {fileID: 0}
m_Transition: 1
m_Colors:
  m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
  m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
  m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
  m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
  m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
  m_ColorMultiplier: 1
  m_FadeDuration: 0.1
m_SpriteState:
  m_HighlightedSprite: {fileID: 0}
  m_PressedSprite: {fileID: 0}
  m_SelectedSprite: {fileID: 0}
  m_DisabledSprite: {fileID: 0}
m_AnimationTriggers:
  m_NormalTrigger: Normal
  m_HighlightedTrigger: Highlighted
  m_PressedTrigger: Pressed
  m_SelectedTrigger: Selected
  m_DisabledTrigger: Disabled
m_Interactable: 1
m_TargetGraphic: {fileID: 1732033236}
m_OnClick:
  m_PersistentCalls:
    m_Calls:
    - m_Target: {fileID: 293984670}
      m_TargetAssemblyTypeName: CallClientHost, Assembly-CSharp
      m_MethodName: CallButton_Click
      m_Mode: 1
      m_Arguments:
        m_ObjectArgument: {fileID: 0}
        m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
        m_IntArgument: 0
        m_FloatArgument: 0
        m_StringArgument: 
        m_BoolArgument: 0
      m_CallState: 2
--- !u!114 &1732033236
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1732033233}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name: 
m_EditorClassIdentifier: 
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
  m_PersistentCalls:
    m_Calls: []
m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!222 &1732033237
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1732033233}
m_CullTransparentMesh: 1
--- !u!1 &1787936406
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1787936407}
- component: {fileID: 1787936408}
m_Layer: 5
m_Name: Text Area
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1787936407
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1787936406}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 857336306}
- {fileID: 1676708953}
m_Father: {fileID: 963546687}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: -0.4999962}
m_SizeDelta: {x: -20, y: -13}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &1787936408
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1787936406}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3312d7739989d2b4e91e6319e9a96d76, type: 3}
m_Name: 
m_EditorClassIdentifier: 
m_Padding: {x: -8, y: -5, z: -8, w: -5}
m_Softness: {x: 0, y: 0}
--- !u!1 &1843906923
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1843906927}
- component: {fileID: 1843906926}
- component: {fileID: 1843906925}
- component: {fileID: 1843906924}
m_Layer: 5
m_Name: Canvas
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &1843906924
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1843906923}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3}
m_Name: 
m_EditorClassIdentifier: 
m_IgnoreReversedGraphics: 1
m_BlockingObjects: 0
m_BlockingMask:
  serializedVersion: 2
  m_Bits: 4294967295
--- !u!114 &1843906925
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1843906923}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3}
m_Name: 
m_EditorClassIdentifier: 
m_UiScaleMode: 0
m_ReferencePixelsPerUnit: 100
m_ScaleFactor: 1
m_ReferenceResolution: {x: 800, y: 600}
m_ScreenMatchMode: 0
m_MatchWidthOrHeight: 0
m_PhysicalUnit: 3
m_FallbackScreenDPI: 96
m_DefaultSpriteDPI: 96
m_DynamicPixelsPerUnit: 1
m_PresetInfoIsWorld: 0
--- !u!223 &1843906926
Canvas:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1843906923}
m_Enabled: 1
serializedVersion: 3
m_RenderMode: 0
m_Camera: {fileID: 0}
m_PlaneDistance: 100
m_PixelPerfect: 0
m_ReceivesEvents: 1
m_OverrideSorting: 0
m_OverridePixelPerfect: 0
m_SortingBucketNormalizedSize: 0
m_AdditionalShaderChannelsFlag: 25
m_SortingLayerID: 0
m_SortingOrder: 0
m_TargetDisplay: 0
--- !u!224 &1843906927
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1843906923}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 0, y: 0, z: 0}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 963546687}
- {fileID: 1732033234}
- {fileID: 1332239154}
- {fileID: 1184525249}
- {fileID: 1529611527}
m_Father: {fileID: 0}
m_RootOrder: 3
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0, y: 0}
--- !u!1 &1917486033
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1917486034}
- component: {fileID: 1917486036}
- component: {fileID: 1917486035}
m_Layer: 5
m_Name: Text (TMP)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1917486034
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1917486033}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1332239154}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &1917486035
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1917486033}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name: 
m_EditorClassIdentifier: 
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
  m_PersistentCalls:
    m_Calls: []
m_text: Hang Up
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
  serializedVersion: 2
  rgba: 4281479730
m_fontColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
  topLeft: {r: 1, g: 1, b: 1, a: 1}
  topRight: {r: 1, g: 1, b: 1, a: 1}
  bottomLeft: {r: 1, g: 1, b: 1, a: 1}
  bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
  serializedVersion: 2
  rgba: 4294967295
m_fontSize: 24
m_fontSizeBase: 24
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 2
m_VerticalAlignment: 512
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_enableWordWrapping: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 1
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!222 &1917486036
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1917486033}
m_CullTransparentMesh: 1


Unity エディターで AppManager.cs という名前のスクリプトを作成し、AppManager オブジェクトにリンクします。 その内容を次の実装に置き換えます。

using Azure.Communication.Calling.UnityClient;
using System.Runtime.InteropServices.ComTypes;
using System;
using UnityEngine;
using System.Linq;
using UnityEngine.UI;
using UnityEngine.Video;
using TMPro;

/// <summary>
/// A singleton which hosts an Azure Communication calling client. This calling client 
/// is then shared across the application.
/// </summary>

public class AppManager : MonoBehaviour
{
    private CallClient callClient;
    private CallAgent callAgent;
    private DeviceManager deviceManager;
    private CommunicationCall call;
    private LocalOutgoingAudioStream micStream;

    public string CalleeIdentity { get; set; }

    public TMP_Text callStatus;

    public static AppManager Instance;

    private void Awake()
    {
        // start of new code
        if (Instance != null)
        {
            Destroy(gameObject);
            return;
        }
        // end of new code

        callClient = new CallClient();

        Instance = this;
        DontDestroyOnLoad(gameObject);

        InitCallAgentAndDeviceManagerAsync();
    }

    public async void CallButton_Click()
    {
        // Start a call
    }

    public async void HangupButton_Click()
    {
        // Hang up a call
    }

    private async void OnIncomingCallAsync(object sender, IncomingCallReceivedEventArgs args)
    {
        // Handle incoming call event
    }

    private void OnStateChangedAsync(object sender, Azure.Communication.Calling.UnityClient.PropertyChangedEventArgs args)
    {
        // Handle connected and disconnected state change of a call
    }

    //Used For Updating the UI
    private void Update()
    {
        if (call != null)
        {
            switch (call.State)
            {
                case CallState.Connected:
                    if (callStatus.text != "Connected")
                        callStatus.text = "Connected";
                    break;
                case CallState.Disconnected:
                    if (callStatus.text != "Disconnected")
                        callStatus.text = "Disconnected";
                    break;
            }
        }
    }
}

AppManager という名前の GameObject のスクリプト コンポーネントに、新しく作成したスクリプトをドラッグします。 また、Status テキスト オブジェクトを [Call Status] テキスト フィールドにドラッグして、Call 状態の UI の更新を有効にします。

オブジェクト モデル

次の表に、Azure Communication Services Calling SDK の主要な機能の一部を処理するクラスとインターフェイスを示します。

名前 説明
CallClient CallClient は、Calling SDK へのメイン エントリ ポイントです。
CallAgent CallAgentを使用して、呼び出しを開始および管理します。
Call CommunicationCallを使用して、継続的な通話を管理します。
CallTokenCredential CallTokenCredentialをインスタンス化するには、トークン資格情報としてCallAgentを使用します。
CallIdentifier CallIdentifierを使用してユーザーの ID を表します。UserCallIdentifierPhoneNumberCallIdentifierなど、次のいずれかのオプションを使用できます。

クライアントを認証する

通話を発信および受信できるようにするユーザー アクセス トークンで CallAgent インスタンスを初期化し、必要に応じてクライアント デバイス構成のクエリを実行するための DeviceManager インスタンスを取得します。

コードで、<AUTHENTICATION_TOKEN> をユーザー アクセス トークンに置き換えます。 使用可能なトークンがまだない場合は、 ユーザー アクセス トークンを参照してください。

SDK をブートストラップする InitCallAgentAndDeviceManagerAsync 関数を追加します。 このヘルパーは、アプリケーションの要件を満たすようにカスタマイズできます。

private async void InitCallAgentAndDeviceManagerAsync()
{

    deviceManager = await callClient.GetDeviceManager();

    var tokenCredential = new CallTokenCredential(<AUTHENTICATION_TOKEN>);

    var callAgentOptions = new CallAgentOptions()
    {
        DisplayName = $"{Environment.MachineName}/{Environment.UserName}",
    };

    callAgent = await callClient.CreateCallAgent(tokenCredential, callAgentOptions);
    callAgent.IncomingCallReceived += OnIncomingCallAsync;
}

通話を開始する

StartCallOptions オブジェクトが取得されたら、CallAgent を使用して Azure Communication Services 通話を開始できます。

public async void CallButton_Click()
{
    var startCallOptions = new StartCallOptions();
    startCallOptions = new StartCallOptions();

    var callee = new UserCallIdentifier(CalleeIdentity);

    call = await callAgent.StartCallAsync(new CallIdentifier[] { callee }, startCallOptions);
    // Set up handler for call StateChanged event
    call.StateChanged += OnStateChangedAsync;
}

通話を終了する

[Hang up](通話終了) ボタンがクリックされたら、現在の通話を終了します。 通話を終了し、プレビューとビデオのストリームを停止する実装を HangupButton_Click に追加します。

public async void HangupButton_Click()
{
    if (call != null)
    {
        try
        {
            await call.HangUpAsync(new HangUpOptions() { ForEveryone = false });
        }
        catch (Exception ex)
        {
        }
    }
}

電話の着信を受け入れる

IncomingCallReceived イベント シンクは、SDK ブートストラップ ヘルパー InitCallAgentAndDeviceManagerAsync で設定されます。

callAgent.IncomingCallReceived += OnIncomingCallAsync;

ビデオやオーディオのストリームの種類などの、着信通話を受け入れる方法をアプリケーションに構成できます。

private async void OnIncomingCallAsync(object sender, IncomingCallReceivedEventArgs args)
{
    var incomingCall = args.IncomingCall;

    var acceptCallOptions = new AcceptCallOptions()
    {
        IncomingVideoOptions = new IncomingVideoOptions()
        {
            StreamKind = VideoStreamKind.RemoteIncoming
        }
    };

    call = await incomingCall.AcceptAsync(acceptCallOptions);
    // Set up handler for incoming call StateChanged event
    call.StateChanged += OnStateChangedAsync;
}

通話状態変更イベントを監視して応答する

StateChanged オブジェクトの Call イベントは、進行中の通話トランザクションがある状態から別の状態に変化したときに発生します。 アプリケーションには、UI に状態の変更を反映したり、ビジネス ロジックを挿入したりする機会が用意されています。

private async void OnStateChangedAsync(object sender, PropertyChangedEventArgs args)
{
    var call = sender as CommunicationCall;

    if (call != null)
    {
        var state = call.State;
        switch (state)
        {
            case CallState.Connected:
                {
                    await call.StartAudioAsync(micStream);

                    break;
                }
            case CallState.Disconnected:
                {
                    call.StateChanged -= OnStateChangedAsync;

                    call.Dispose();

                    break;
                }
            default: break;
        }
    }
}

コードの実行

このコードをビルドし、Unity エディターまたは Unity を使用するデバイスで実行できます。

発信通話を行うには、テキスト フィールドにユーザー ID を指定し、[Start Call/Join](通話を開始) ボタンをクリックします。 8:echo123呼び出すとエコー ボットに接続されます。この機能を使用すると、オーディオ デバイスが動作していることを開始して確認できます。

Unity クイックスタート アプリの実行を示すスクリーンショット。

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

Communication Services サブスクリプションをクリーンアップして解除する場合は、リソースまたはリソース グループを削除できます。 リソース グループを削除すると、それに関連付けられている他のリソースも削除されます。 詳細については、リソースのクリーンアップに関する記事を参照してください。

次の手順