快速入門:將語音通話新增至您的應用程式

使用通話 SDK 將語音和視訊通話新增至您的應用程式,以開始使用 Azure 通訊服務。

在本快速入門中,您將瞭解如何使用適用於 Windows 的 Azure 通訊服務 呼叫 SDK 來啟動通話。

您可以從 GitHub 下載範例應用程式

必要條件

若要完成本教學課程,您需要下列必要條件:

設定

建立專案

在 Visual Studio 中,使用空白應用程式 (通用 Windows) 範本建立新專案,以設定單頁 通用 Windows 平台 (UWP) 應用程式。

Screenshot showing the New UWP Project window within Visual Studio.

Install the package

以滑鼠右鍵按兩下您的項目,然後移至安裝 Manage Nuget PackagesAzure.Communication.Calling.WindowsClient1.2.0-beta.1 或更上層。 請確定已核取 [包含預先發行]。

要求存取

移至 並Package.appxmanifest選擇 。 Capabilities 檢查 Internet (Client)Internet (Client & Server) 取得因特網的輸入和輸出存取權。 檢查 Microphone 以存取麥克風的音訊摘要,以及 Webcam 存取相機的視訊摘要。

Screenshot showing requesting access to Internet and Microphone in Visual Studio.

設定應用程式架構

我們需要設定基本版面配置來附加邏輯。 若要撥打輸出通話,我們需要 提供 TextBox 被呼叫者的使用者標識碼。 我們也需要按鈕 Start/Join callHang up 按鈕。 此範例中也包含 A MuteBackgroundBlur 複選框,以示範切換音訊狀態和視訊效果的功能。

MainPage.xaml開啟專案的 ,並將Grid節點新增至 :Page

<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">

    <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;
        private LocalOutgoingVideoStream cameraStream;

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

        protected override async void OnNavigatedTo(NavigationEventArgs e)
        {
            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
    }
}

物件模型

下表列出類別和介面會處理 Azure 通訊服務 呼叫 SDK 的一些主要功能:

名稱 描述
CallClient CallClient是呼叫 SDK 的主要進入點。
CallAgent CallAgent用來啟動和管理話務。
CommunicationCall CommunicationCall用來管理進行中的呼叫。
CallTokenCredential CallTokenCredential會當做權杖認證來具現化 CallAgent
CallIdentifier CallIdentifier用來代表使用者的身分識別,它可以是下列其中一個選項:UserCallIdentifierPhoneNumberCallIdentifier 等等。

驗證用戶端

使用 CallAgent 使用者存取令牌初始化實例,以讓我們進行和接收呼叫,並選擇性地取得 DeviceManager 實例來查詢用戶端裝置組態。

在程式代碼中,將 取代 <AUTHENTICATION_TOKEN> 為使用者存取令牌。 如果您還沒有可用的令牌,請參閱使用者存取令牌檔。

新增 InitCallAgentAndDeviceManagerAsync 函式,以啟動 SDK。 您可以自定義此協助程式,以符合應用程式的需求。

        private async Task InitCallAgentAndDeviceManagerAsync()
        {
            this.callClient = new CallClient(new CallClientOptions() {
                Diagnostics = new CallDiagnosticsOptions() { 
                    AppName = "CallingQuickstart",
                    AppVersion="1.0",
                    Tags = new[] { "Calling", "ACS", "Windows" }
                    }
                });

            // Set up local video stream using the first camera enumerated
            var deviceManager = await this.callClient.GetDeviceManagerAsync();
            var camera = deviceManager?.Cameras?.FirstOrDefault();
            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即可用來起始 Azure 通訊服務 呼叫:

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

結束通話

按兩下按鈕時 Hang up 結束目前的呼叫。 將實作新增至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 });
            }
        }

在音訊上切換靜音/取消靜音

按兩下按鈕時 Mute ,將傳出音訊設為靜音。 將實作新增至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 事件。 應用程式有機會反映 UI 上的狀態變更,或插入商業規則。

        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;
                }
            }
        }

執行程式碼

您可以在 Visual Studio 上建置並執行程式代碼。 針對解決方案平台,我們支援 ARM64x64x86

您可以在文字欄位中提供使用者識別碼,然後按下 Start Call/Join 按鈕,以進行輸出通話。 呼叫 8:echo123 會使用 Echo Bot 來連線您,這項功能非常適合開始使用並驗證音訊裝置是否正常運作。

Screenshot showing running the UWP quickstart app

在本快速入門中,您將瞭解如何使用適用於 JavaScript 的 Azure 通訊服務 呼叫 SDK 來啟動呼叫。

範例指令碼

您可以從 GitHub 下載範例應用程式

注意

您可以使用 Azure 通訊服務 UI 連結庫來存取 Azure 通訊服務 使用者的輸出呼叫。 UI 連結庫可讓開發人員僅使用幾行程式代碼,將啟用 VoIP 的呼叫用戶端新增至其應用程式中。

必要條件

  • 具有有效訂用帳戶的 Azure 帳戶。 免費建立帳戶

  • 您需要Node.js 18。 您可以使用 msi 安裝程式來安裝它。

  • 使用中的通訊服務資源。 建立通訊服務資源。 您必須記錄本快速入門的 連接字串。

  • 用來具現化呼叫用戶端的使用者存取令牌。 瞭解如何 建立和管理使用者存取令牌。 您也可以使用 Azure CLI,搭配 連接字串 執行 命令,以建立使用者和存取令牌。

    az communication identity token issue --scope voip --connection-string "yourConnectionString"
    

    如需詳細資訊,請參閱 使用 Azure CLI 建立和管理存取令牌

設定

建立新的Node.js應用程式

開啟終端機或命令視窗,為您的應用程式建立新的目錄,然後流覽至該目錄。

mkdir calling-quickstart
cd calling-quickstart

執行 npm init -y 以使用預設設定建立 package.json 檔案。

npm init -y

Install the package

npm install使用 命令來安裝 Azure 通訊服務呼叫 SDK for JavaScript。

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

選項--save會將連結庫列為package.json檔案中的相依性。

設定應用程式架構

本快速入門會使用 Webpack 來組合應用程式資產。 執行下列命令以安裝webpack、 和 webpack-dev-server npm 套件,webpack-cli並將其列為開發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

以下是 html,我們需要新增至我們建立的 index.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 通訊服務 呼叫 SDK 的一些主要功能:

名稱 描述
CallClient CallClient是呼叫 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/. 您應該會看到下列畫面:

Screenshot of the completed JavaScript Application.

您可以在對應的文字欄位中提供有效的使用者存取令牌和使用者識別碼,然後按兩下 [開始通話] 按鈕,以進行輸出 VOIP 通話

呼叫 8:echo123 會將您與回應 Bot 連線,這非常適合開始使用並驗證音訊裝置是否正常運作。 傳遞 {id: '8:echo123'} 至 CallAgent.startCall() API 以呼叫 echo Bot。 若要呼叫 Azure 通訊服務 通訊使用者,請傳遞{communicationUserId: 'ACS_USER_ID'}CallAgent.startCall() API。

在本快速入門中,您將瞭解如何使用適用於 Android 的 Azure 通訊服務 呼叫 SDK 來啟動通話。

範例程式碼

您可以從 GitHub 下載範例應用程式

必要條件

設定

建立具有空白活動的Android應用程式

從 Android Studio 中,選取 [啟動新的 Android Studio 專案]。

Screenshot showing the 'Start a new Android Studio Project' button selected in Android Studio.

選取 [電話 和平板計算機] 底下的 [空白活動] 項目範本。

Screenshot showing the 'Empty Activity' option selected in the Project Template Screen.

選取 [API 26:Android 8.0(Oreo)] 或更新版本的 [最低 SDK]。

Screenshot showing the 'Empty Activity' option selected in the Project Template Screen 2.

Install the package

找出您的專案層級 build.gradle,並確定將 新增 mavenCentral() 至 和 下的 buildscript 存放庫清單 allprojects

buildscript {
    repositories {
    ...
        mavenCentral()
    ...
    }
}
allprojects {
    repositories {
    ...
        mavenCentral()
    ...
    }
}

然後,在您的模組層級 build.gradle 中,將下列幾行新增至相依性和 android 區段

android {
    ...
    packagingOptions {
        pickFirst  'META-INF/*'
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    ...
    implementation 'com.azure.android:azure-communication-calling:1.0.0-beta.8'
    ...
}

將許可權新增至應用程式指令清單

若要要求呼叫所需的許可權,必須在應用程式指令清單 (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>
    

設定應用程式的版面配置

需要兩個輸入:被呼叫端標識符的文字輸入,以及放置呼叫的按鈕。 您可以透過設計工具或編輯版面配置 xml 來新增這些輸入。 建立標識碼為 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"
        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>

建立主要活動 Scaffolding 和系結

建立版面配置之後,即可新增系結,以及活動的基本 Scaffolding。 活動會處理要求運行時間許可權、建立呼叫代理程式,並在按下按鈕時放置呼叫。 每個都包含在自己的區段中。 方法 onCreate 會覆寫以叫 getAllPermissions 用 和 , createAgent 並新增呼叫按鈕的系結。 只有在建立活動時,才會發生此事件。 如需 詳細資訊,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;

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[]{Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA, 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 通訊服務 呼叫 SDK 的一些主要功能:

名稱 描述
allClient CallClient是呼叫 SDK 的主要進入點。
CallAgent CallAgent用來啟動和管理話務。
CommunicationTokenCredential CommunicationTokenCredential會當做權杖認證來具現化 CallAgent
CommunicationIdentifier CommunicationIdentifier會當做屬於通話一部分的不同參與者類型使用。

從使用者存取令牌建立代理程式

使用使用者令牌時,可以具現化已驗證的呼叫代理程式。 一般而言,此令牌是從具有應用程式特定驗證的服務產生。 如需使用者存取令牌的詳細資訊,請參閱 使用者存取令牌 指南。

針對快速入門,請將 取代 <User_Access_Token> 為您 Azure 通訊服務資源產生的使用者存取令牌。


/**
 * 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();
    }
}

使用通話代理程序啟動通話

撥打通話可以透過通話代理程式完成,只需要提供被呼叫端標識碼和通話選項的清單。 針對快速入門,會使用不含視訊的默認通話選項,並使用來自文字輸入的單一被呼叫端標識符。

/**
 * 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(),
        new CommunicationUserIdentifier[] {new CommunicationUserIdentifier(calleeId)},
        options);
}

啟動應用程式並呼叫 Echo Bot

現在可以使用工具列上的 [執行應用程式] 按鈕來啟動應用程式(Shift+F10)。 藉由呼叫 8:echo123來確認您能夠撥打電話。 預先錄製的訊息會播放,然後重複訊息給您。

Screenshot showing the completed application.

在本快速入門中,您將瞭解如何使用適用於 iOS 的 Azure 通訊服務 通話 SDK 來啟動通話。

範例程式碼

您可以從 GitHub 下載範例應用程式

必要條件

若要完成本教學課程,您需要下列必要條件:

設定

建立 Xcode 專案

在 Xcode 中,建立新的 iOS 專案,然後選取應用程式範本。 本教學課程使用 SwiftUI 架構,因此您應該將 Language 設定為 Swift,並將使用者介面設定為 SwiftUI。 您不會在此快速入門期間建立測試。 請隨意取消核取 [包含測試]。

Screenshot showing the New Project window within Xcode.

使用 CocoaPods 安裝套件和相依性

  1. 若要為您的應用程式建立 Podfile,請開啟終端機並瀏覽至專案資料夾並執行:

    pod init

  2. 將下列程式代碼新增至 Podfile 並儲存 (請確定 “target” 符合項目的名稱):

    platform :ios, '13.0'
    use_frameworks!
    
    target 'AzureCommunicationCallingSample' do
      pod 'AzureCommunicationCalling', '~> 1.0.0'
    end
    
  3. 執行 pod install

  4. .xcworkspace使用 Xcode 開啟 。

要求存取麥克風

若要存取裝置的麥克風,您必須使用 NSMicrophoneUsageDescription更新您 app 的資訊屬性清單。 您會將相關聯的值設定為 string 系統用來要求使用者存取權之對話框中所包含的 。

以滑鼠右鍵按兩下Info.plist專案樹狀結構的項目,然後選取 [開啟為>原始程式碼]。 在最上層 <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 通訊服務 呼叫 SDK 的一些主要功能:

名稱 描述
CallClient CallClient是呼叫 SDK 的主要進入點。
CallAgent CallAgent用來啟動和管理話務。
CommunicationTokenCredential CommunicationTokenCredential會當做權杖認證來具現化 CallAgent
CommunicationUserIdentifier CommunicationUserIdentifier用來代表使用者的身分識別,可以是下列其中一個選項: CommunicationUserIdentifierPhoneNumberIdentifierCallingApplication.

驗證用戶端

CallAgent使用使用者存取令牌初始化實例,這可讓我們進行和接收呼叫。

在下列程式代碼中,您必須將 取代 <USER ACCESS TOKEN> 為資源的有效使用者存取令牌。 如果您還沒有可用的令牌,請參閱使用者存取令牌檔。

將下列程式代碼新增至 onAppear ContentView.swift 中的回呼:

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.")
        }
    }
}

執行程式碼

您可以選取 [產品>執行] 或使用 [⌘-R] 鍵盤快捷方式,在 iOS 模擬器上建置並執行您的應用程式。

Final look and feel of the quick start app

您可以在文字欄位中提供使用者標識碼,然後點選 [開始通話] 按鈕,進行輸出 VOIP 通話 。 呼叫 8:echo123 會使用 Echo Bot 來連線您,這項功能非常適合開始使用並驗證音訊裝置是否正常運作。

注意

第一次撥打電話時,系統會提示您存取麥克風。 在生產應用程式中,您應該使用 AVAudioSession API 來 檢查許可權狀態 ,並在未授與許可權時正常更新應用程式的行為。

在本快速入門中,您將瞭解如何使用 Azure 通訊服務 呼叫 SDK for Unity 來啟動呼叫。

您可以從 GitHub 下載範例應用程式

必要條件

若要完成本教學課程,您需要下列必要條件:

設定

建立專案

在 Unity 中樞中,使用 2D 核心 範本建立新專案,以設定 Unity 專案。

Screenshot showing the New Unity Project window within Unity Editor.

Install the package

有兩種方式可以安裝適用於 Unity 的 Azure 通訊通話 SDK。

  1. 從公用 npm 摘要下載 SDK,並將其匯入 Unity 編輯器的套件管理員,其位於 Windows 索引卷標底下。

  2. 從 Microsoft 下載混合實境功能工具,並透過混合實境工具管理員進行安裝。

設定應用程式架構

我們需要設定基本版面配置來附加邏輯。 若要撥打輸出通話,我們需要 提供 TextBox 被呼叫者的使用者標識碼。 我們也需要按鈕 Start/Join callHang 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: 3
  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
  buildHeightMesh: 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: a3a77da2e7bbf604c8b001e299ec9185, type: 3}
m_Name: 
m_EditorClassIdentifier: 
callStatus: {fileID: 1529611528}
--- !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_Iso: 200
m_ShutterSpeed: 0.005
m_Aperture: 16
m_FocusDistance: 10
m_FocalLength: 50
m_BladeCount: 5
m_Curvature: {x: 2, y: 11}
m_BarrelClipping: 0.25
m_Anamorphism: 0
m_SensorSize: {x: 36, y: 24}
m_LensShift: {x: 0, y: 0}
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: 5
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: 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: -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: 6
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: 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: -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_VertexColorAlwaysGammaSpace: 0
m_AdditionalShaderChannelsFlag: 25
m_UpdateRectTransformForStandalone: 0
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


建立名為 AppManager.cs 的腳本,並將其連結至 Unity 編輯器中的 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 Call 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, 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 中,將新建立的腳本拖曳到其腳本元件中。 此外,將 [狀態] 文字物件拖曳至 [通話狀態] 文字欄位,以啟用通話狀態的UI更新。

物件模型

下表列出類別和介面會處理 Azure 通訊服務 呼叫 SDK 的一些主要功能:

名稱 描述
CallClient CallClient是呼叫 SDK 的主要進入點。
CallAgent CallAgent用來啟動和管理話務。
Call CommunicationCall用來管理進行中的呼叫。
CallTokenCredential CallTokenCredential會當做權杖認證來具現化 CallAgent
CallIdentifier CallIdentifier用來代表使用者的身分識別,它可以是下列其中一個選項:UserCallIdentifierPhoneNumberCallIdentifier 等等。

驗證用戶端

使用 CallAgent 使用者存取令牌初始化實例,以讓我們進行和接收呼叫,並選擇性地取得 DeviceManager 實例來查詢用戶端裝置組態。

在程式代碼中,將 取代 <AUTHENTICATION_TOKEN> 為使用者存取令牌。 如果您還沒有可用的令牌,請參閱使用者存取令牌檔。

新增 InitCallAgentAndDeviceManagerAsync 函式,以啟動 SDK。 您可以自定義此協助程式,以符合應用程式的需求。

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 通訊服務 呼叫:

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 Call;

    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 的裝置上建置和執行程式代碼。

您可以在文字欄位中提供使用者識別碼,然後按下 Start Call/Join 按鈕,以進行輸出通話。 呼叫 8:echo123 會使用 Echo Bot 來連線您,這項功能非常適合開始使用並驗證音訊裝置是否正常運作。

Screenshot showing running the Unity quickstart app.

清除資源

如果您想要清除並移除通訊服務訂用帳戶,您可以刪除資源或資源群組。 刪除資源群組也會刪除與其相關聯的任何其他資源。 深入瞭解清除 資源

下一步

如需詳細資訊,請參閱下列文章: