Aracılığıyla paylaş


Çağrı hero örneğini kullanmaya başlama

Azure İletişim Hizmetleri Grup Çağrısı Hero Örneği, İletişim Hizmetleri Arama Web SDK'sının grup arama deneyimi oluşturmak için nasıl kullanılabileceğini gösterir.

Bu Örnek hızlı başlangıçta, örneği yerel makinenizde çalıştırmadan ve ardından kendi Azure İletişim Hizmetleri kaynaklarınızı kullanarak örneği Azure'a dağıtmadan önce örneğin nasıl çalıştığını öğreneceksiniz.

Kodu indirin

GitHub'da bu örneğe yönelik projeyi bulun. Teams Birlikte Çalışma ve Arama Kaydı gibi genel önizleme aşamasında olan özellikleri içeren bir örnek sürümü ayrı bir dalda bulunabilir.

Azure’a dağıtın

Genel bakış

Örnekte hem istemci tarafı uygulaması hem de sunucu tarafı uygulaması vardır. İstemci tarafı uygulaması , Microsoft'un Fluent UI çerçevesini kullanan bir React/Redux web uygulamasıdır. Bu uygulama, istemci tarafı uygulamasının Azure'a bağlanmasına yardımcı olan bir ASP.NET Core sunucu tarafı uygulamasına istek gönderir.

Örnek şöyle görünür:

Örnek uygulamanın giriş sayfasını gösteren ekran görüntüsü.

"Arama başlat" düğmesine bastığınızda, web uygulaması sunucu tarafı uygulamasından bir kullanıcı erişim belirteci getirir. Bu belirteç daha sonra istemci uygulamasını Azure İletişim Hizmetleri bağlamak için kullanılır. Belirteç alındıktan sonra kullanmak istediğiniz kamerayı ve mikrofonu belirtmeniz istenir. İki durumlu denetimlerle cihazlarınızı devre dışı bırakabilir/etkinleştirebilirsiniz:

Örnek uygulamanın arama öncesi ekranını gösteren ekran görüntüsü.

Görünen adınızı ve cihazlarınızı yapılandırdıktan sonra arama oturumuna katılabilirsiniz. Çekirdek arama deneyiminin bulunduğu ana arama tuvalini görürsünüz.

Örnek uygulamanın ana ekranını gösteren ekran görüntüsü.

Ana arama ekranının bileşenleri:

  • Medya Galerisi: Katılımcıların gösterildiği ana aşama. Bir katılımcının kamerası etkinse video akışı burada gösterilir. Her katılımcının görünen adını ve video akışını (varsa) gösteren tek bir kutucuğu vardır
  • Üst bilgi: Birincil arama denetimleri, ayarları ve katılımcı yan çubuğunu değiştirmek, videoyu açıp kapatmak, ekranı paylaşmak ve aramayı bırakmak için burada bulunur.
  • Yan Çubuk: Üst bilgideki denetimler kullanılarak geçiş yapıldığında katılımcılar ve ayarlar bilgileri burada gösterilir. Bileşen sağ üst köşedeki 'X' kullanılarak kapatılabilir. Katılımcılar yan çubuğunda katılımcıların listesi ve sohbete daha fazla kullanıcı davet etmek için bir bağlantı gösterilir. Ayarlar yan çubuğu mikrofon ve kamera ayarlarını yapılandırmanıza olanak tanır.

Aşağıda önkoşullar ve örneği ayarlama adımları hakkında daha fazla bilgi bulabilirsiniz.

Önkoşullar

Örneği ilk kez çalıştırmadan önce

  1. PowerShell, Windows Terminal, Komut İstemi veya eşdeğer bir örneği açın ve örneği kopyalamak istediğiniz dizine gidin.

    git clone https://github.com/Azure-Samples/communication-services-web-calling-hero.git
    
  2. Connection String Azure portalından veya Azure CLI kullanarak alın.

    az communication list-key --name "<acsResourceName>" --resource-group "<resourceGroup>"
    

    bağlantı dizesi hakkında daha fazla bilgi için bkz. Azure İletişim Kaynakları oluşturma

  3. öğesini aldıktan Connection Stringsonra bağlantı dizesi samples/Server/appsetting.json dosyasına ekleyin. bağlantı dizesi şu değişkene giriş: ResourceConnectionString.

  4. Endpoint string Azure portalından veya Azure CLI kullanarak alın.

    az communication list-key --name "<acsResourceName>" --resource-group "<resourceGroup>"
    

    Uç nokta dizeleri hakkında daha fazla bilgi için bkz. Azure İletişim Kaynakları oluşturma

  5. öğesini aldıktan Endpoint Stringsonra uç nokta dizesini samples/Server/appsetting.json dosyasına ekleyin. Uç nokta dizenizi değişkene girin EndpointUrl

Yerel çalıştırma

  1. Bağımlılıkları yükleme

    npm run setup
    
  2. Arama uygulamasını başlatma

    npm run start
    

    Bu, web sitesi dosyalarına hizmet veren 3000 numaralı bağlantı noktasında bir istemci sunucusu ve çağrı katılımcıları için belirteç hazırlama gibi işlevler gerçekleştiren 8080 numaralı bağlantı noktasında bir API sunucusu açar.

Sorun giderme

  • Uygulama bir "Desteklenmeyen tarayıcı" ekranı gösteriyor ancak desteklenen bir tarayıcıdayım.

    Uygulamanız localhost dışında bir ana bilgisayar adı üzerinden sunulursa trafiği http üzerinden değil https üzerinden sunmanız gerekir.

Azure'a Yayımlama

  1. npm run setup
  2. npm run build
  3. npm run package
  4. Azure uzantısını kullanın ve Çağrı/dağıtım dizinini uygulama hizmetinize dağıtın

Kaynakları temizleme

İletişim Hizmetleri aboneliğini temizlemek ve kaldırmak istiyorsanız, kaynağı veya kaynak grubunu silebilirsiniz. Kaynak grubunun silinmesi, kaynak grubuyla ilişkili diğer tüm kaynakları da siler. Kaynakları temizleme hakkında daha fazla bilgi edinin.

Sonraki adımlar

Daha fazla bilgi için aşağıdaki makaleleri inceleyin:

Ek okuma

  • Örnekler - Örneklere genel bakış sayfamızda daha fazla örnek ve örnek bulabilirsiniz.
  • Redux - İstemci tarafı durum yönetimi
  • FluentUI - Microsoft tarafından desteklenen kullanıcı arabirimi kitaplığı
  • React - Kullanıcı arabirimleri oluşturmak için kitaplık
  • ASP.NET Core - Web uygulamaları oluşturmaya yönelik çerçeve

iOS için Azure İletişim Hizmetleri Grup Çağrısı Hero Örneği, ses ve video içeren bir grup arama deneyimi oluşturmak için İletişim Hizmetleri Çağrı iOS SDK'sının nasıl kullanılabileceğini gösterir. Bu örnek hızlı başlangıçta örneği ayarlamayı ve çalıştırmayı öğreneceksiniz. Bağlam için örneğe genel bir bakış sağlanır.

Kodu indirin

GitHub'da bu örneğe yönelik projeyi bulun.

Genel bakış

Örnek, hem sesli hem de görüntülü arama özelliğine sahip bir arama deneyimi oluşturmak için Azure İletişim Hizmetleri iOS SDK'larını kullanan yerel bir iOS uygulamasıdır. Uygulama, daha sonra Azure İletişim Hizmetleri SDK'sını başlatmak için kullanılan erişim belirteçleri sağlamak için bir sunucu tarafı bileşeni kullanır. Bu sunucu tarafı bileşenini yapılandırmak için Azure İşlevleri ile Güvenilen Hizmet öğreticisini izleyebilirsiniz.

Örnek şöyle görünür:

Örnek uygulamanın giriş sayfasını gösteren ekran görüntüsü.

"Yeni aramayı başlat" düğmesine bastığınızda, iOS uygulaması arama için kullanmak üzere görünen adınızı girmenizi ister.

Örnek uygulamanın arama öncesi ekranını gösteren ekran görüntüsü.

"Aramayı Başlat" ekranında "İleri" seçeneğine dokunduktan sonra, iOS paylaşım sayfası aracılığıyla aramanın grup kimliğini paylaşma fırsatınız olur.

Örnek uygulamanın grup kimliği paylaşma ekranını gösteren ekran görüntüsü.

Uygulama ayrıca mevcut aramanın kimliğini veya ekip kimliği bağlantısını belirterek mevcut bir Azure İletişim Hizmetleri çağrısına katılmanızı sağlar.

Örnek uygulamanın çağrıya katılma ekranını gösteren ekran görüntüsü.

Bir aramaya katıldıktan sonra, henüz yetkilendirilmediyse uygulamaya kameranıza ve mikrofonunuza erişim izni vermeniz istenir. Tüm AVFoundation tabanlı uygulamalar gibi gerçek ses ve video işlevlerinin de yalnızca gerçek donanımlarda kullanılabildiğini unutmayın.

Görünen adınızı yapılandırdıktan ve aramaya katıldıktan sonra, çekirdek arama deneyiminin bulunduğu ana arama tuvalini görürsünüz.

Örnek uygulamanın ana ekranını gösteren ekran görüntüsü.

Ana arama ekranının bileşenleri:

  • Medya Galerisi: Katılımcıların gösterildiği ana aşama. Bir katılımcının kamerası etkinse video akışı burada gösterilir. Her katılımcının görünen adını ve video akışını (varsa) gösteren tek bir kutucuğu vardır. Galeri birden çok katılımcıyı destekler ve katılımcılar aramaya eklendiğinde veya kaldırıldığında güncelleştirilir.
  • Eylem Çubuğu: Birincil çağrı denetimlerinin bulunduğu yerdir. Bu denetimler, videonuzu ve mikrofonunuzu açmanızı/kapatmanızı, ekranınızı paylaşmanızı ve aramayı bırakmanızı olanaklı verir.

Aşağıda önkoşullar ve örneği ayarlama adımları hakkında daha fazla bilgi bulabilirsiniz.

Önkoşullar

  • Etkin aboneliği olan bir Azure hesabı. Ayrıntılar için bkz . Ücretsiz hesap oluşturma.
  • Anahtar zincirinize yüklenmiş geçerli bir geliştirici sertifikasının yanı sıra Xcode çalıştıran bir Mac.
  • bir Azure İletişim Hizmetleri kaynağı. Ayrıntılar için bkz. Azure İletişim Hizmetleri kaynağı oluşturma.
  • Erişim belirteçlerini getirmek için Kimlik Doğrulama Uç Noktasını çalıştıran bir Azure İşlevi.

Örneği yerel olarak çalıştırma

Grup çağrısı örneği, XCode kullanılarak yerel olarak çalıştırılabilir. Geliştiriciler uygulamayı test etmek için fiziksel cihazlarını veya öykünücülerini kullanabilir.

Örneği ilk kez çalıştırmadan önce

  1. komutunu çalıştırarak pod installbağımlılıkları yükleyin.
  2. XCode ile açın AzureCalling.xcworkspace .
  3. Kökte adlı AppSettings.xcconfig bir metin dosyası oluşturun ve değerini ayarlayın:
    communicationTokenFetchUrl = <your authentication endpoint, without the https:// component>
    

Örneği çalıştırma

İstediğiniz simülatörde veya cihazda AzureCalling hedefini kullanarak örneği XCode'da derleyin ve çalıştırın.

(İsteğe bağlı) Kimlik doğrulama uç noktasının güvenliğini sağlama

Tanıtım amacıyla bu örnek, Azure İletişim Hizmetleri erişim belirtecini getirmek için varsayılan olarak genel olarak erişilebilen bir uç nokta kullanır. Üretim senaryolarında, kendi belirteçlerinizi sağlamak için kendi güvenli uç noktanızı kullanmanızı öneririz.

Ek yapılandırmayla bu örnek, uygulamanın Azure İletişim Hizmetleri erişim belirtecini getirmesi için kullanıcı oturum açma bilgilerinin gerekli olması için Microsoft Entra ID (Microsoft Entra ID) korumalı uç noktasına bağlanmayı destekler. Aşağıdaki adımlara bakın:

  1. Uygulamanızda Microsoft Entra kimlik doğrulamasını etkinleştirin.
  2. Microsoft Entra App Registrations altında kayıtlı uygulamanıza genel bakış sayfasına gidin. , , Directory (tenant) IDdeğerlerini not Application (client) IDalınApplication ID URI

Azure portalında Microsoft Entra yapılandırması.

  1. Henüz yoksa kökte bir AppSettings.xcconfig dosya oluşturun ve değerleri ekleyin:
    communicationTokenFetchUrl = <Application ID URI, without the https:// component>
    aadClientId = <Application (client) ID>
    aadTenantId = <Directory (tenant) ID>
    

Kaynakları temizleme

İletişim Hizmetleri aboneliğini temizlemek ve kaldırmak istiyorsanız, kaynağı veya kaynak grubunu silebilirsiniz. Kaynak grubunun silinmesi, kaynak grubuyla ilişkili diğer tüm kaynakları da siler. Kaynakları temizleme hakkında daha fazla bilgi edinin.

Sonraki adımlar

Daha fazla bilgi için aşağıdaki makaleleri inceleyin:

Ek okuma

Android için Azure İletişim Hizmetleri Grup Çağrısı Hero Örneği, Android'i Çağıran İletişim Hizmetleri SDK'sının ses ve video içeren bir grup arama deneyimi oluşturmak için nasıl kullanılabileceğini gösterir. Bu örnek hızlı başlangıçta örneği ayarlamayı ve çalıştırmayı öğreneceksiniz. Bağlam için örneğe genel bir bakış sağlanır.

Kodu indirin

GitHub'da bu örneğe yönelik projeyi bulun.

Genel bakış

Örnek, hem sesli hem de görüntülü arama özelliğine sahip bir arama deneyimi oluşturmak için Azure İletişim Hizmetleri Android UI istemci kitaplığını kullanan yerel bir Android uygulamasıdır. Uygulama, daha sonra Azure İletişim Hizmetleri SDK'sını başlatmak için kullanılan erişim belirteçleri sağlamak için bir sunucu tarafı bileşeni kullanır. Bu sunucu tarafı bileşenini yapılandırmak için Azure İşlevleri ile Güvenilen Hizmet öğreticisini izleyebilirsiniz.

Örnek şöyle görünür:

Örnek uygulamanın giriş sayfasını gösteren ekran görüntüsü.

"Yeni aramayı başlat" düğmesine bastığınızda, Android uygulaması arama için kullanmak üzere görünen adınızı girmenizi ister.

Örnek uygulamanın arama öncesi ekranını gösteren ekran görüntüsü.

"Arama Başlat" sayfasında "İleri" seçeneğine dokunduktan sonra "Grup Araması Kimliği"ni paylaşma fırsatınız olur.

Örnek uygulamanın Grup Arama Kimliği paylaşma ekranını gösteren ekran görüntüsü.

Uygulama, mevcut aramanın kimliğini veya teams toplantı kimliği bağlantısını ve görünen adını belirterek mevcut bir Azure İletişim Hizmetleri çağrısına katılmanızı sağlar.

Örnek uygulamanın çağrıya katılma ekranını gösteren ekran görüntüsü.

Bir aramaya katıldıktan sonra, henüz yetkilendirilmediyse uygulamaya kameranıza ve mikrofonunuza erişim izni vermeniz istenir. Çekirdek arama deneyiminin bulunduğu ana arama tuvalini göreceksiniz.

Örnek uygulamanın ana ekranını gösteren ekran görüntüsü.

Ana arama ekranının bileşenleri:

  • Medya Galerisi: Katılımcıların gösterildiği ana aşama. Bir katılımcının kamerası etkinse video akışı burada gösterilir. Her katılımcının görünen adını ve video akışını (varsa) gösteren tek bir kutucuğu vardır. Galeri birden çok katılımcıyı destekler ve katılımcılar aramaya eklendiğinde veya kaldırıldığında güncelleştirilir.
  • Eylem Çubuğu: Birincil çağrı denetimlerinin bulunduğu yerdir. Bu denetimler, videonuzu ve mikrofonunuzu açmanızı/kapatmanızı, ekranınızı paylaşmanızı ve aramayı bırakmanızı olanaklı verir.

Aşağıda önkoşullar ve örneği ayarlama adımları hakkında daha fazla bilgi bulabilirsiniz.

Önkoşullar

Örneği yerel olarak çalıştırma

Grup çağrısı örneği, Android Studio kullanılarak yerel olarak çalıştırılabilir. Geliştiriciler uygulamayı test etmek için fiziksel cihazlarını veya öykünücülerini kullanabilir.

Örneği ilk kez çalıştırmadan önce

  1. Android Studio'yu açın ve Open an Existing Project
  2. AzureCalling Örnek için indirilen sürümün içindeki klasörü açın.
  3. güncelleştirmek appSettings.propertiesiçin uygulamayı/varlıkları genişletin. Anahtarın communicationTokenFetchUrl değerini, ön koşul olarak ayarlanmış Kimlik Doğrulama Uç Noktanızın URL'si olacak şekilde ayarlayın.

Örneği çalıştırma

Android Studio'da örneği derleyin ve çalıştırın.

(İsteğe bağlı) Kimlik doğrulama uç noktasının güvenliğini sağlama

Tanıtım amacıyla bu örnek, bir Azure İletişim Hizmetleri belirteci getirmek için varsayılan olarak genel olarak erişilebilen bir uç nokta kullanır. Üretim senaryolarında, kendi belirteçlerinizi sağlamak için kendi güvenli uç noktanızı kullanmanızı öneririz.

Ek yapılandırmayla bu örnek, uygulamanın Azure İletişim Hizmetleri belirtecini getirmesi için kullanıcı oturum açma bilgilerinin gerekli olması için Microsoft Entra Id (Microsoft Entra ID) korumalı uç noktasına bağlanmayı destekler. Aşağıdaki adımlara bakın:

  1. Uygulamanızda Microsoft Entra kimlik doğrulamasını etkinleştirin.

  2. Microsoft Entra App Registrations altında kayıtlı uygulamanıza genel bakış sayfasına gidin. , , Signature hashMSAL Configutaiondeğerlerini not Package namealın.

Azure portalında Microsoft Entra yapılandırması.

  1. Microsoft Entra Id'yi etkinleştirmek için düzenleyin AzureCalling/app/src/main/res/raw/auth_config_single_account.json ve ayarlayın isAADAuthEnabled .

  2. Keystore imza karması olarak düzenleyin AndroidManifest.xml ve ayarlayın android:path . (İsteğe bağlı. Geçerli değer, bundled debug.keystore'dan karma kullanır. Farklı anahtar deposu kullanılıyorsa, bu güncelleştirilmelidir.)

    <activity android:name="com.microsoft.identity.client.BrowserTabActivity">
             <intent-filter>
                 <action android:name="android.intent.action.VIEW" />
                 <category android:name="android.intent.category.DEFAULT" />
                 <category android:name="android.intent.category.BROWSABLE" />
                 <data
                     android:host="com.azure.samples.communication.calling"
                     android:path="/Signature hash" <!-- do not remove /. The current hash in AndroidManifest.xml is for debug.keystore. -->
                     android:scheme="msauth" />
             </intent-filter>
         </activity>
    
  3. Azure portalından MSAL Android yapılandırmasını kopyalayın ve öğesine AzureCalling/app/src/main/res/raw/auth_config_single_account.jsonyapıştırın. "account_mode" dahil et: "SINGLE"

       {
          "client_id": "",
          "authorization_user_agent": "DEFAULT",
          "redirect_uri": "",
          "account_mode" : "SINGLE",
          "authorities": [
             {
                "type": "AAD",
                "audience": {
                "type": "AzureADMyOrg",
                "tenant_id": ""
                }
             }
          ]
       }
    
  4. Anahtarın communicationTokenFetchUrl değerini düzenleyip AzureCalling/app/src/main/res/raw/auth_config_single_account.json güvenli Kimlik Doğrulama Uç Noktanızın URL'si olacak şekilde ayarlayın.

  5. Kapsamlardan Expose an API Azure Active Directory anahtarın aadScopes değerini düzenleyin AzureCalling/app/src/main/res/raw/auth_config_single_account.json ve ayarlayın

  6. Kullanıcı bilgilerini getirmek için graphURL AzureCalling/app/assets/appSettings.properties değerini Graph API uç noktası olarak ayarlayın.

  7. Kullanıcının uygulamayı yeniden başlatırken tekrar tekrar kimliğinin doğrulanması gerekmeyecek şekilde sessiz oturum açmayı etkinleştirmek için anahtarın tenant değerini düzenleyin AzureCalling/app/src/main/assets/appSettings.properties ve ayarlayın.

Kaynakları temizleme

İletişim Hizmetleri aboneliğini temizlemek ve kaldırmak istiyorsanız, kaynağı veya kaynak grubunu silebilirsiniz. Kaynak grubunun silinmesi, kaynak grubuyla ilişkili diğer tüm kaynakları da siler. Kaynakları temizleme hakkında daha fazla bilgi edinin.

Sonraki adımlar

Daha fazla bilgi için aşağıdaki makaleleri inceleyin:

Ek okuma

Windows için Azure İletişim Hizmetleri Grup Çağrısı Hero Örneği, ses ve video içeren bir grup arama deneyimi oluşturmak için İletişim Hizmetleri Windows SDK'sını çağırmanın nasıl kullanılabileceğini gösterir. Bu örnekte, örneği ayarlamayı ve çalıştırmayı öğreneceksiniz. Bağlam için örneğe genel bir bakış sağlanır.

Bu hızlı başlangıçta, Windows için Azure İletişim Hizmetleri Arama SDK'sını kullanarak 1:1 görüntülü arama başlatmayı öğreneceksiniz.

UWP örnek kodu

Önkoşullar

Bu öğreticiyi tamamlamak için aşağıdaki önkoşulları karşılamanız gerekir:

Ayarlama

Projeyi oluşturma

Visual Studio'da, tek sayfalı bir Evrensel Windows Platformu (UWP) uygulaması ayarlamak için Boş Uygulama (Evrensel Windows) şablonuyla yeni bir proje oluşturun.

Visual Studio'da Yeni UWP Projesi penceresini gösteren ekran görüntüsü.

paketini yükleyin

Projenize sağ tıklayın ve 1.2.0-beta.1 veya üst sürümü yüklemek Azure.Communication.Calling.WindowsClient için adresine gidinManage Nuget Packages. Önceden Dahil Et'in işaretli olduğundan emin olun.

Erişim isteğinde bulunma

adresine Package.appxmanifest gidin ve öğesine tıklayın Capabilities. İnternet'e gelen ve giden erişim kazanmak için denetleyin Internet (Client & Server) . Mikrofonun ses akışına erişmek için denetleyin Microphone . Cihazın kamerasına erişmek için kontrol edin WebCam .

Sağ tıklayıp Kodu Görüntüle'yi seçerek aşağıdaki kodu kodunuza Package.appxmanifest ekleyin.

<Extensions>
<Extension Category="windows.activatableClass.inProcessServer">
<InProcessServer>
<Path>RtmMvrUap.dll</Path>
<ActivatableClass ActivatableClassId="VideoN.VideoSchemeHandler" ThreadingModel="both" />
</InProcessServer>
</Extension>
</Extensions>

Uygulama çerçevesini ayarlama

Mantığımızı eklemek için temel bir düzen yapılandırmamız gerekir. Giden arama yapmak için, arayanın Kullanıcı Kimliğini sağlamamız gerekir TextBox . Ayrıca bir Start Call düğmeye ve bir düğmeye Hang Up de ihtiyacımız var. Ayrıca yerel videoyu önizlememiz ve diğer katılımcının uzak videosunu işlememiz gerekir. Bu nedenle video akışlarını görüntülemek için iki öğeye ihtiyacımız vardır.

Projenizin öğesini MainPage.xaml açın ve içeriği aşağıdaki uygulamayla değiştirin.

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

    <Grid x:Name="MainGrid" HorizontalAlignment="Stretch">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="200*"/>
            <RowDefinition Height="60*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <Grid Grid.Row="0" x:Name="AppTitleBar" Background="LightSeaGreen">
            <!-- Width of the padding columns is set in LayoutMetricsChanged handler. -->
            <!-- Using padding columns instead of Margin ensures that the background paints the area under the caption control buttons (for transparent buttons). -->
            <TextBlock x:Name="QuickstartTitle" Text="Calling Quickstart sample title bar" Style="{StaticResource CaptionTextBlockStyle}" Padding="4,4,0,0"/>
        </Grid>

        <TextBox Grid.Row="1" x:Name="CalleeTextBox" PlaceholderText="Who would you like to call?" TextWrapping="Wrap" VerticalAlignment="Center" />

        <Grid Grid.Row="2" Background="LightGray">
            <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" Margin="10">
                <TextBlock VerticalAlignment="Center">Cameras:</TextBlock>
                <ComboBox x:Name="CameraList" HorizontalAlignment="Left" Grid.Column="0" DisplayMemberPath="Name" SelectionChanged="CameraList_SelectionChanged" Margin="10"/>
            </StackPanel>
            <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"/>
                <CheckBox x:Name="BackgroundBlur" Content="Background blur" Width="142" Margin="10,0,0,0" Click="BackgroundBlur_Click"/>
            </StackPanel>
        </StackPanel>
        <TextBox Grid.Row="4" x:Name="Stats" Text="" TextWrapping="Wrap" VerticalAlignment="Center" Height="30" Margin="0,2,0,0" BorderThickness="2" IsReadOnly="True" Foreground="LightSlateGray" />
    </Grid>
</Page>

App.xaml.cs öğesini açın (sağ tıklayıp Kodu Görüntüle'yi seçin) ve bu satırı en üste ekleyin:

using CallingQuickstart;

MainPage.xaml.cs öğesini açın (sağ tıklayın ve Kodu Görüntüle'yi seçin) ve içeriği aşağıdaki uygulamayla değiştirin:

using Azure.Communication.Calling.WindowsClient;
using System;
using System.Collections.Generic;
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 = "<Azure Communication Services auth token>";
    
        private CallClient callClient;
        private CallTokenRefreshOptions callTokenRefreshOptions;
        private CallAgent callAgent;
        private CommunicationCall call = null;

        private LocalOutgoingAudioStream micStream;
        private LocalOutgoingVideoStream cameraStream;

        #region Page initialization
        public MainPage()
        {
            this.InitializeComponent();
            
            // Hide default title bar.
            var coreTitleBar = CoreApplication.GetCurrentView().TitleBar;
            coreTitleBar.ExtendViewIntoTitleBar = true;

            QuickstartTitle.Text = $"{Package.Current.DisplayName} - Ready";
            Window.Current.SetTitleBar(AppTitleBar);

            CallButton.IsEnabled = true;
            HangupButton.IsEnabled = !CallButton.IsEnabled;
            MuteLocal.IsChecked = MuteLocal.IsEnabled = !CallButton.IsEnabled;

            ApplicationView.PreferredLaunchViewSize = new Windows.Foundation.Size(800, 600);
            ApplicationView.PreferredLaunchWindowingMode = ApplicationViewWindowingMode.PreferredLaunchViewSize;
        }

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

            base.OnNavigatedTo(e);
        }
#endregion

        private async Task InitCallAgentAndDeviceManagerAsync()
        {
            // Initialize call agent and Device Manager
        }

        private async void Agent_OnIncomingCallAsync(object sender, IncomingCall incomingCall)
        {
            // Accept an incoming call
        }

        private async void CallButton_Click(object sender, RoutedEventArgs e)
        {
            // Start a call with video
        }

        private async void HangupButton_Click(object sender, RoutedEventArgs e)
        {
            // End the current call
        }

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

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

                await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
                {
                    QuickstartTitle.Text = $"{Package.Current.DisplayName} - {state.ToString()}";
                    Window.Current.SetTitleBar(AppTitleBar);

                    HangupButton.IsEnabled = state == CallState.Connected || state == CallState.Ringing;
                    CallButton.IsEnabled = !HangupButton.IsEnabled;
                    MuteLocal.IsEnabled = !CallButton.IsEnabled;
                });

                switch (state)
                {
                    case CallState.Connected:
                        {
                            break;
                        }
                    case CallState.Disconnected:
                        {
                            break;
                        }
                    default: break;
                }
            }
        }
        
        private async void CameraList_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            // Handle camera selection
        }
    }
}

Nesne modeli

Aşağıdaki sınıflar ve arabirimler, Azure İletişim Hizmetleri Çağırma SDK'sının bazı önemli özelliklerini işler:

Veri Akışı Adı Açıklama
CallClient CallClient, çağrı istemci kitaplığının ana giriş noktasıdır.
CallAgent CallAgent çağrıları başlatmak ve katılmak için kullanılır.
CommunicationCall CommunicationCall, yerleştirilen veya birleştirilen çağrıları yönetmek için kullanılır.
CallTokenCredential , CallTokenCredential örneğini CallAgentbaşlatmak için belirteç kimlik bilgisi olarak kullanılır.
CommunicationUserIdentifier CommunicationUserIdentifier, kullanıcının kimliğini temsil etmek için kullanılır. Bu, aşağıdaki seçeneklerden biri olabilir: CommunicationUserIdentifier, PhoneNumberIdentifier veya CallingApplication.

İstemcinin kimliğini doğrulama

bir CallAgentbaşlatmak için bir Kullanıcı Erişim Belirteci gerekir. Bu belirteç genellikle uygulamaya özgü kimlik doğrulamasına sahip bir hizmetten oluşturulur. Kullanıcı erişim belirteçleri hakkında daha fazla bilgi için Kullanıcı Erişim Belirteçleri kılavuzuna bakın.

Hızlı başlangıç için değerini Azure İletişim Hizmeti kaynağınız için oluşturulan bir kullanıcı erişim belirteci ile değiştirin <AUTHENTICATION_TOKEN> .

Belirteciniz olduktan sonra, çağrı yapmamıza ve almamıza olanak tanıyan bir CallAgent örneği onunla başlatın. Cihazdaki kameralara erişmek için Aygıt Yöneticisi örneği de almalıyız.

İşleve aşağıdaki kodu InitCallAgentAndDeviceManagerAsync ekleyin.

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();

CameraList.ItemsSource = deviceManager.Cameras.ToList();

if (camera != null)
{
    CameraList.SelectedIndex = 0;
}

callTokenRefreshOptions = new CallTokenRefreshOptions(false);
callTokenRefreshOptions.TokenRefreshRequested += OnTokenRefreshRequestedAsync;

var tokenCredential = new CallTokenCredential(authToken, callTokenRefreshOptions);

var callAgentOptions = new CallAgentOptions()
{
    DisplayName = "Contoso",
    //https://github.com/lukes/ISO-3166-Countries-with-Regional-Codes/blob/master/all/all.csv
    EmergencyCallOptions = new EmergencyCallOptions() { CountryCode = "840" }
};


try
{
    this.callAgent = await this.callClient.CreateCallAgentAsync(tokenCredential, callAgentOptions);
    //await this.callAgent.RegisterForPushNotificationAsync(await this.RegisterWNS());
    this.callAgent.CallsUpdated += OnCallsUpdatedAsync;
    this.callAgent.IncomingCallReceived += OnIncomingCallAsync;

}
catch(Exception ex)
{
    if (ex.HResult == -2147024809)
    {
        // E_INVALIDARG
        // Handle possible invalid token
    }
}

Görüntülü arama başlatma

Görüntülü arama başlatmak için uygulamasına CallButton_Click ekleyin. Kameraları cihaz yöneticisi örneğiyle listelememiz ve oluşturmamız LocalOutgoingVideoStreamgerekir. ile öğesini ayarlamalı VideoOptions LocalVideoStream ve çağrısının ilk seçeneklerini ayarlamak için ile startCallOptions geçirmemiz gerekir. öğesine MediaElementekleyerek LocalOutgoingVideoStream yerel videonun önizlemesini görebiliriz.

var callString = CalleeTextBox.Text.Trim();

if (!string.IsNullOrEmpty(callString))
{
    if (callString.StartsWith("8:")) // 1:1 Azure Communication Services call
    {
        call = await StartAcsCallAsync(callString);
    }
    else if (callString.StartsWith("+")) // 1:1 phone call
    {
        call = await StartPhoneCallAsync(callString, "+12133947338");
    }
    else if (Guid.TryParse(callString, out Guid groupId))// Join group call by group guid
    {
        call = await JoinGroupCallByIdAsync(groupId);
    }
    else if (Uri.TryCreate(callString, UriKind.Absolute, out Uri teamsMeetinglink)) //Teams meeting link
    {
        call = await JoinTeamsMeetingByLinkAsync(teamsMeetinglink);
    }
}

if (call != null)
{
    call.RemoteParticipantsUpdated += OnRemoteParticipantsUpdatedAsync;
    call.StateChanged += OnStateChangedAsync;
}

Farklı arama türlerini başlatmak veya buna katılmak için yöntemleri ekleyin (1:1 Azure İletişim Hizmetleri arama, 1:1 telefon araması, Azure İletişim Hizmetleri Grup araması, Teams toplantısına katılma vb.).

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

private async Task<CommunicationCall> StartPhoneCallAsync(string acsCallee, string alternateCallerId)
{
    var options = await GetStartCallOptionsAsynnc();
    options.AlternateCallerId = new PhoneNumberCallIdentifier(alternateCallerId);

    var call = await this.callAgent.StartCallAsync( new [] { new PhoneNumberCallIdentifier(acsCallee) }, options);
    return call;
}

private async Task<CommunicationCall> JoinGroupCallByIdAsync(Guid groupId)
{
    var joinCallOptions = await GetJoinCallOptionsAsync();

    var groupCallLocator = new GroupCallLocator(groupId);
    var call = await this.callAgent.JoinAsync(groupCallLocator, joinCallOptions);
    return call;
}

private async Task<CommunicationCall> JoinTeamsMeetingByLinkAsync(Uri teamsCallLink)
{
    var joinCallOptions = await GetJoinCallOptionsAsync();

    var teamsMeetingLinkLocator = new TeamsMeetingLinkLocator(teamsCallLink.AbsoluteUri);
    var call = await callAgent.JoinAsync(teamsMeetingLinkLocator, joinCallOptions);
    return call;
}

private async Task<StartCallOptions> GetStartCallOptionsAsynnc()
{
    return new StartCallOptions() {
        OutgoingAudioOptions = new OutgoingAudioOptions() { IsOutgoingAudioMuted = true, OutgoingAudioStream = micStream  },
        OutgoingVideoOptions = new OutgoingVideoOptions() { OutgoingVideoStreams = new OutgoingVideoStream[] { cameraStream } }
    };
}

private async Task<JoinCallOptions> GetJoinCallOptionsAsync()
{
    return new JoinCallOptions() {
        OutgoingAudioOptions = new OutgoingAudioOptions() { IsOutgoingAudioMuted = true },
        OutgoingVideoOptions = new OutgoingVideoOptions() { OutgoingVideoStreams = new OutgoingVideoStream[] { cameraStream } }
    };
}

Yöntemindeki seçili kameraya CameraList_SelectionChanged bağlı olarak LocalVideoStream oluşturmak için kodu ekleyin.

var selectedCamerea = CameraList.SelectedItem as VideoDeviceDetails;
cameraStream = new LocalOutgoingVideoStream(selectedCamerea);

 var localUri = await cameraStream.StartPreviewAsync();
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
    LocalVideo.Source = MediaSource.CreateFromUri(localUri);
});

if (call != null)
{
    await call?.StartVideoAsync(cameraStream);
}

Gelen aramayı kabul etme

Gelen bir aramayı videoyla yanıtlamak için uygulamasını OnIncomingCallAsync uygulamasına ekleyin, öğesini öğesine acceptCallOptionsgeçirinLocalVideoStream.

var incomingCall = args.IncomingCall;

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

_ = await incomingCall.AcceptAsync(acceptCallOptions);

Uzak katılımcı ve uzak video akışları

Tüm uzak katılımcılar, bir çağrı örneğindeki RemoteParticipants koleksiyon aracılığıyla kullanılabilir. Arama bağlandıktan sonra, aramanın uzak katılımcılarına erişebilir ve uzak video akışlarını işleyebiliriz.


private async void Call_OnVideoStreamsUpdatedAsync(object sender, RemoteVideoStreamsEventArgs args)
{
    foreach (var remoteVideoStream in args.AddedRemoteVideoStreams)
    {
        await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () =>
        {
            RemoteVideo.Source = await remoteVideoStream.Start();
        });
    }

    foreach (var remoteVideoStream in args.RemovedRemoteVideoStreams)
    {
        remoteVideoStream.Stop();
    }
}

private async void Agent_OnCallsUpdatedAsync(object sender, CallsUpdatedEventArgs args)
{
    var removedParticipants = new List<RemoteParticipant>();
    var addedParticipants = new List<RemoteParticipant>();

    foreach(var call in args.RemovedCalls)
    {
        removedParticipants.AddRange(call.RemoteParticipants.ToList<RemoteParticipant>());
    }

    foreach (var call in args.AddedCalls)
    {
        addedParticipants.AddRange(call.RemoteParticipants.ToList<RemoteParticipant>());
    }

    await OnParticipantChangedAsync(removedParticipants, addedParticipants);
}

private async Task OnParticipantChangedAsync(IEnumerable<RemoteParticipant> removedParticipants, IEnumerable<RemoteParticipant> addedParticipants)
{
    foreach (var participant in removedParticipants)
    {
        foreach(var incomingVideoStream in  participant.IncomingVideoStreams)
        {
            var remoteVideoStream = incomingVideoStream as RemoteIncomingVideoStream;
            if (remoteVideoStream != null)
            {
                await remoteVideoStream.StopPreviewAsync();
            }
        }
        participant.VideoStreamStateChanged -= OnVideoStreamStateChanged;
    }

    foreach (var participant in addedParticipants)
    {
        participant.VideoStreamStateChanged += OnVideoStreamStateChanged;
    }
}

private void OnVideoStreamStateChanged(object sender, VideoStreamStateChangedEventArgs e)
{
    CallVideoStream callVideoStream = e.CallVideoStream;

    switch (callVideoStream.StreamDirection)
    {
        case StreamDirection.Outgoing:
            OnOutgoingVideoStreamStateChanged(callVideoStream as OutgoingVideoStream);
            break;
        case StreamDirection.Incoming:
            OnIncomingVideoStreamStateChanged(callVideoStream as IncomingVideoStream);
            break;
    }
}

private async void OnIncomingVideoStreamStateChanged(IncomingVideoStream incomingVideoStream)
{
    switch (incomingVideoStream.State)
    {
        case VideoStreamState.Available:
        {
            switch (incomingVideoStream.Kind)
            {
                case VideoStreamKind.RemoteIncoming:
                    var remoteVideoStream = incomingVideoStream as RemoteIncomingVideoStream;
                    var uri = await remoteVideoStream.StartPreviewAsync();

                    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
                    {
                        RemoteVideo.Source = MediaSource.CreateFromUri(uri);
                    });
                    break;

                case VideoStreamKind.RawIncoming:
                    break;
            }
            break;
        }
        case VideoStreamState.Started:
            break;
        case VideoStreamState.Stopping:
            break;
        case VideoStreamState.Stopped:
            if (incomingVideoStream.Kind == VideoStreamKind.RemoteIncoming)
            {
                var remoteVideoStream = incomingVideoStream as RemoteIncomingVideoStream;
                await remoteVideoStream.StopPreviewAsync();
            }
            break;
        case VideoStreamState.NotAvailable:
            break;
    }

}

Uzak videoları işleme

Her uzak video akışı için akışına MediaElementekleyin.

private async Task AddVideoStreamsAsync(IReadOnlyList<RemoteVideoStream> remoteVideoStreams)
{
    foreach (var remoteVideoStream in remoteVideoStreams)
    {
        var remoteUri = await remoteVideoStream.Start();

        await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            RemoteVideo.Source = remoteUri;
            RemoteVideo.Play();
        });
    }
}

Çağrı durumu güncelleştirmesi

Aramanın bağlantısı kesildikten sonra video işleyicilerini temizlememiz ve uzak katılımcıların aramaya ilk katıldığında olayı işlememiz gerekir.

private async void Call_OnStateChanged(object sender, PropertyChangedEventArgs args)
{
    switch (((Call)sender).State)
    {
        case CallState.Disconnected:
            await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
            {
                LocalVideo.Source = null;
                RemoteVideo.Source = null;
            });
            break;

        case CallState.Connected:
            foreach (var remoteParticipant in call.RemoteParticipants)
            {
                String remoteParticipantMRI = remoteParticipant.Identifier.ToString();
                remoteParticipantDictionary.TryAdd(remoteParticipantMRI, remoteParticipant);
                await AddVideoStreams(remoteParticipant.VideoStreams);
                remoteParticipant.OnVideoStreamsUpdated += Call_OnVideoStreamsUpdated;
            }
            break;

        default:
            break;
    }
}

Aramayı sonlandırma

Düğmeye tıklandığında Hang Up geçerli aramayı sonlandırın. Oluşturduğumuz callAgent ile bir çağrıyı sonlandırmak için uygulamayı HangupButton_Click ekleyin ve katılımcı güncelleştirmesini ve çağrı durumu olay işleyicilerini yok edin.

var call = this.callAgent?.Calls?.FirstOrDefault();
if (call != null)
{
    try
    {
        await call.HangUpAsync(new HangUpOptions() { ForEveryone = true });
    }
    catch(Exception ex) 
    {
    }
}

Kodu çalıştırma

Kodu Visual Studio'da derleyebilir ve çalıştırabilirsiniz. Çözüm platformları için , ve x86'yi x64 destekliyoruzARM64.

Metin alanında bir kullanıcı kimliği sağlayarak ve düğmeye tıklayarak Start Call giden görüntülü arama yapabilirsiniz.

Not: Yankı botu video akışını desteklemediğinden arama 8:echo123 özelliği video akışını durdurur.

Kullanıcı kimlikleri (kimlik) hakkında daha fazla bilgi için Kullanıcı Erişim Belirteçleri kılavuzuna bakın.

WinUI 3 örnek kodu

Önkoşullar

Bu öğreticiyi tamamlamak için aşağıdaki önkoşulları karşılamanız gerekir:

Ayarlama

Projeyi oluşturma

Visual Studio'da, tek sayfalı bir WinUI 3 uygulaması ayarlamak için Boş Uygulama, Paketlenmiş (Masaüstünde WinUI 3) şablonuyla yeni bir proje oluşturun.

Visual Studio'da Yeni WinUI Projesi penceresini gösteren ekran görüntüsü.

paketini yükleyin

Projenize sağ tıklayın ve 1.0.0 veya üst sürümü yüklemek Azure.Communication.Calling.WindowsClient için adresine gidinManage Nuget Packages. Önceden Dahil Et'in işaretli olduğundan emin olun.

Erişim isteğinde bulunma

Visual Studio'da İnternet ve Mikrofona erişim isteğinde bulunmayı gösteren ekran görüntüsü.

aşağıdaki kodu öğesininize app.manifestekleyin:

<file name="RtmMvrMf.dll">
    <activatableClass name="VideoN.VideoSchemeHandler" threadingModel="both" xmlns="urn:schemas-microsoft-com:winrt.v1" />
</file>

Uygulama çerçevesini ayarlama

Mantığımızı eklemek için temel bir düzen yapılandırmamız gerekir. Giden arama yapmak için, arayanın Kullanıcı Kimliğini sağlamamız gerekir TextBox . Ayrıca bir Start Call düğmeye ve bir düğmeye Hang Up de ihtiyacımız var. Ayrıca yerel videoyu önizlememiz ve diğer katılımcının uzak videosunu işlememiz gerekir. Bu nedenle video akışlarını görüntülemek için iki öğeye ihtiyacımız vardır.

Projenizin öğesini MainWindow.xaml açın ve içeriği aşağıdaki uygulamayla değiştirin.

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

    <Grid x:Name="MainGrid">
        <Grid.RowDefinitions>
            <RowDefinition Height="32"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="200*"/>
            <RowDefinition Height="60*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <Grid Grid.Row="0" x:Name="AppTitleBar" Background="LightSeaGreen">
            <!-- Width of the padding columns is set in LayoutMetricsChanged handler. -->
            <!-- Using padding columns instead of Margin ensures that the background paints the area under the caption control buttons (for transparent buttons). -->
            <TextBlock x:Name="QuickstartTitle" Text="Calling Quickstart sample title bar" Style="{StaticResource CaptionTextBlockStyle}" Padding="4,4,0,0"/>
        </Grid>

        <TextBox Grid.Row="1" x:Name="CalleeTextBox" PlaceholderText="Who would you like to call?" TextWrapping="Wrap" VerticalAlignment="Center" />

        <Grid Grid.Row="2" Background="LightGray">
            <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" Margin="10">
                <TextBlock VerticalAlignment="Center">Cameras:</TextBlock>
                <ComboBox x:Name="CameraList" HorizontalAlignment="Left" Grid.Column="0" DisplayMemberPath="Name" SelectionChanged="CameraList_SelectionChanged" Margin="10"/>
            </StackPanel>
            <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"/>
                <CheckBox x:Name="BackgroundBlur" Content="Background blur" Width="142" Margin="10,0,0,0" Click="BackgroundBlur_Click"/>
            </StackPanel>
        </StackPanel>
        <TextBox Grid.Row="4" x:Name="Stats" Text="" TextWrapping="Wrap" VerticalAlignment="Center" Height="30" Margin="0,2,0,0" BorderThickness="2" IsReadOnly="True" Foreground="LightSlateGray" />
    </Grid>    
</Page>

App.xaml.cs öğesini açın (sağ tıklayıp Kodu Görüntüle'yi seçin) ve bu satırı en üste ekleyin:

using CallingQuickstart;

MainWindow.xaml.cs öğesini açın (sağ tıklayın ve Kodu Görüntüle'yi seçin) ve içeriği aşağıdaki uygulamayla değiştirin:

using Azure.Communication.Calling.WindowsClient;
using Azure.WinRT.Communication;
using Microsoft.UI.Xaml;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Windows.Media.Core;

namespace CallingQuickstart
{
    public sealed partial class MainWindow : Window
    {
        CallAgent callAgent;
        Call call;
        DeviceManager deviceManager;
        Dictionary<string, RemoteParticipant> remoteParticipantDictionary = new Dictionary<string, RemoteParticipant>();

        public MainWindow()
        {
            this.InitializeComponent();
            Task.Run(() => this.InitCallAgentAndDeviceManagerAsync()).Wait();
        }

        private async Task InitCallAgentAndDeviceManagerAsync()
        {
            // Initialize call agent and Device Manager
        }

        private async void Agent_OnIncomingCallAsync(object sender, IncomingCall incomingCall)
        {
            // Accept an incoming call
        }

        private async void CallButton_Click(object sender, RoutedEventArgs e)
        {
            // Start a call with video
        }

        private async void HangupButton_Click(object sender, RoutedEventArgs e)
        {
            // End the current call
        }

        private async void Call_OnStateChangedAsync(object sender, PropertyChangedEventArgs args)
        {
            var state = (sender as Call)?.State;
            this.DispatcherQueue.TryEnqueue(() => {
                State.Text = state.ToString();
            });
        }
    }
}

Nesne modeli

Aşağıdaki sınıflar ve arabirimler, Azure İletişim Hizmetleri Çağırma SDK'sının bazı önemli özelliklerini işler:

Veri Akışı Adı Açıklama
CallClient CallClient, çağrı istemci kitaplığının ana giriş noktasıdır.
CallAgent CallAgent çağrıları başlatmak ve katılmak için kullanılır.
CommunicationCall CommunicationCall, yerleştirilen veya birleştirilen çağrıları yönetmek için kullanılır.
CallTokenCredential , CallTokenCredential örneğini CallAgentbaşlatmak için belirteç kimlik bilgisi olarak kullanılır.
CommunicationUserIdentifier CommunicationUserIdentifier, kullanıcının kimliğini temsil etmek için kullanılır. Bu, aşağıdaki seçeneklerden biri olabilir: CommunicationUserIdentifier, PhoneNumberIdentifier veya CallingApplication.

İstemcinin kimliğini doğrulama

bir CallAgentbaşlatmak için bir Kullanıcı Erişim Belirteci gerekir. Bu belirteç genellikle uygulamaya özgü kimlik doğrulamasına sahip bir hizmetten oluşturulur. Kullanıcı erişim belirteçleri hakkında daha fazla bilgi için Kullanıcı Erişim Belirteçleri kılavuzuna bakın.

Hızlı başlangıç için değerini Azure İletişim Hizmeti kaynağınız için oluşturulan bir kullanıcı erişim belirteci ile değiştirin <AUTHENTICATION_TOKEN> .

Bir belirteciniz olduğunda, çağrı yapmamıza ve almamıza olanak tanıyan bir CallAgent örneği onunla başlatın. Cihazdaki kameralara erişmek için Aygıt Yöneticisi örneği de almalıyız.

İşleve aşağıdaki kodu InitCallAgentAndDeviceManagerAsync ekleyin.

var callClient = new CallClient();
this.deviceManager = await callClient.GetDeviceManagerAsync();

var tokenCredential = new CallTokenCredential("<AUTHENTICATION_TOKEN>");
var callAgentOptions = new CallAgentOptions()
{
    DisplayName = "<DISPLAY_NAME>"
};

this.callAgent = await callClient.CreateCallAgentAsync(tokenCredential, callAgentOptions);
this.callAgent.OnCallsUpdated += Agent_OnCallsUpdatedAsync;
this.callAgent.OnIncomingCall += Agent_OnIncomingCallAsync;

Görüntülü arama başlatma

Görüntülü arama başlatmak için uygulamasına CallButton_Click ekleyin. Kameraları cihaz yöneticisi örneğiyle listelememiz ve oluşturmamız LocalVideoStreamgerekir. ile öğesini ayarlamalı VideoOptions LocalVideoStream ve çağrısının ilk seçeneklerini ayarlamak için ile startCallOptions geçirmemiz gerekir. öğesine MediaPlayerElementekleyerek LocalVideoStream yerel videonun önizlemesini görebiliriz.

var startCallOptions = new StartCallOptions();

if (this.deviceManager.Cameras?.Count > 0)
{
    var videoDeviceInfo = this.deviceManager.Cameras?.FirstOrDefault();
    if (videoDeviceInfo != null)
    {
        var selectedCamerea = CameraList.SelectedItem as VideoDeviceDetails;
        cameraStream = new LocalOutgoingVideoStream(selectedCamerea);

        var localUri = await cameraStream.StartPreviewAsync();
        await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            LocalVideo.Source = MediaSource.CreateFromUri(localUri);
        });

        startCallOptions.VideoOptions = new OutgoingVideoOptions(new[] { cameraStream });
    }
}

var callees = new ICommunicationIdentifier[1]
{
    new CommunicationUserIdentifier(CalleeTextBox.Text.Trim())
};

this.call = await this.callAgent.StartCallAsync(callees, startCallOptions);
this.call.OnRemoteParticipantsUpdated += Call_OnRemoteParticipantsUpdatedAsync;
this.call.OnStateChanged += Call_OnStateChangedAsync;

Gelen aramayı kabul etme

Gelen bir aramayı videoyla yanıtlamak için uygulamasını Agent_OnIncomingCallAsync uygulamasına ekleyin, öğesini öğesine acceptCallOptionsgeçirinLocalVideoStream.

var acceptCallOptions = new AcceptCallOptions();

if (this.deviceManager.Cameras?.Count > 0)
{
    var videoDeviceInfo = this.deviceManager.Cameras?.FirstOrDefault();
    if (videoDeviceInfo != null)
    {
        var selectedCamerea = CameraList.SelectedItem as VideoDeviceDetails;
        cameraStream = new LocalOutgoingVideoStream(selectedCamerea);

        var localUri = await cameraStream.StartPreviewAsync();
        await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            LocalVideo.Source = MediaSource.CreateFromUri(localUri);
        });

        acceptCallOptions.VideoOptions = new OutgoingVideoOptions(new[] { localVideoStream });
    }
}

call = await incomingCall.AcceptAsync(acceptCallOptions);

Uzak katılımcı ve uzak video akışları

Tüm uzak katılımcılar, bir çağrı örneğindeki RemoteParticipants koleksiyon aracılığıyla kullanılabilir. Arama bağlandıktan sonra, aramanın uzak katılımcılarına erişebilir ve uzak video akışlarını işleyebiliriz.

private async void Call_OnVideoStreamsUpdatedAsync(object sender, RemoteVideoStreamsEventArgs args)
{
    foreach (var remoteVideoStream in args.AddedRemoteVideoStreams)
    {
        this.DispatcherQueue.TryEnqueue(async () => {
            RemoteVideo.Source = MediaSource.CreateFromUri(await remoteVideoStream.Start());
            RemoteVideo.MediaPlayer.Play();
        });
    }

    foreach (var remoteVideoStream in args.RemovedRemoteVideoStreams)
    {
        remoteVideoStream.Stop();
    }
}

private async void Agent_OnCallsUpdatedAsync(object sender, CallsUpdatedEventArgs args)
{
    foreach (var call in args.AddedCalls)
    {
        foreach (var remoteParticipant in call.RemoteParticipants)
        {
            var remoteParticipantMRI = remoteParticipant.Identifier.ToString();
            this.remoteParticipantDictionary.TryAdd(remoteParticipantMRI, remoteParticipant);
            await AddVideoStreamsAsync(remoteParticipant.VideoStreams);
            remoteParticipant.OnVideoStreamsUpdated += Call_OnVideoStreamsUpdatedAsync;
        }
    }
}

private async void Call_OnRemoteParticipantsUpdatedAsync(object sender, ParticipantsUpdatedEventArgs args)
{
    foreach (var remoteParticipant in args.AddedParticipants)
    {
        String remoteParticipantMRI = remoteParticipant.Identifier.ToString();
        this.remoteParticipantDictionary.TryAdd(remoteParticipantMRI, remoteParticipant);
        await AddVideoStreamsAsync(remoteParticipant.VideoStreams);
        remoteParticipant.OnVideoStreamsUpdated += Call_OnVideoStreamsUpdatedAsync;
    }

    foreach (var remoteParticipant in args.RemovedParticipants)
    {
        String remoteParticipantMRI = remoteParticipant.Identifier.ToString();
        this.remoteParticipantDictionary.Remove(remoteParticipantMRI);
    }
}

Uzak videoları işleme

Her uzak video akışı için akışına MediaPlayerElementekleyin.

private async Task AddVideoStreamsAsync(IReadOnlyList<RemoteVideoStream> remoteVideoStreams)
{
    foreach (var remoteVideoStream in remoteVideoStreams)
    {
        var remoteUri = await remoteVideoStream.Start();

        this.DispatcherQueue.TryEnqueue(() => {
            RemoteVideo.Source = MediaSource.CreateFromUri(remoteUri);
            RemoteVideo.MediaPlayer.Play();
        });
    }
}

Çağrı durumu güncelleştirmesi

Aramanın bağlantısı kesildikten sonra video işleyicilerini temizlememiz ve uzak katılımcıların aramaya ilk katıldığında olayı işlememiz gerekir.

private async void Call_OnStateChanged(object sender, PropertyChangedEventArgs args)
{
    switch (((Call)sender).State)
    {
        case CallState.Disconnected:
            this.DispatcherQueue.TryEnqueue(() => { =>
            {
                LocalVideo.Source = null;
                RemoteVideo.Source = null;
            });
            break;

        case CallState.Connected:
            foreach (var remoteParticipant in call.RemoteParticipants)
            {
                String remoteParticipantMRI = remoteParticipant.Identifier.ToString();
                remoteParticipantDictionary.TryAdd(remoteParticipantMRI, remoteParticipant);
                await AddVideoStreams(remoteParticipant.VideoStreams);
                remoteParticipant.OnVideoStreamsUpdated += Call_OnVideoStreamsUpdated;
            }
            break;

        default:
            break;
    }
}

Aramayı sonlandırma

Düğmeye tıklandığında Hang Up geçerli aramayı sonlandırın. Oluşturduğumuz callAgent ile bir çağrıyı sonlandırmak için uygulamayı HangupButton_Click ekleyin ve katılımcı güncelleştirmesini ve çağrı durumu olay işleyicilerini yok edin.

this.call.OnRemoteParticipantsUpdated -= Call_OnRemoteParticipantsUpdatedAsync;
this.call.OnStateChanged -= Call_OnStateChangedAsync;
await this.call.HangUpAsync(new HangUpOptions());

Kodu çalıştırma

Kodu Visual Studio'da derleyebilir ve çalıştırabilirsiniz. Çözüm platformları için , ve x86'yi x64 destekliyoruzARM64.

Metin alanında bir kullanıcı kimliği sağlayarak ve düğmeye tıklayarak Start Call giden görüntülü arama yapabilirsiniz.

Not: Yankı botu video akışını desteklemediğinden arama 8:echo123 özelliği video akışını durdurur.

Kullanıcı kimlikleri (kimlik) hakkında daha fazla bilgi için Kullanıcı Erişim Belirteçleri kılavuzuna bakın.