Wednesday

18-06-2025 Vol 19

Microsoft Teams Video Calls to .NET MAUI: A Seamless Integration Guide for Android

Microsoft Teams Video Calls to .NET MAUI: A Seamless Integration Guide for Android

Introduction

In today’s interconnected world, seamless communication is paramount. Microsoft Teams has emerged as a leading platform for collaboration and communication, while .NET MAUI provides a powerful framework for building cross-platform applications. Integrating Microsoft Teams video calls into your .NET MAUI Android application can significantly enhance its functionality and user experience. This comprehensive guide will walk you through the process, providing a step-by-step approach to achieve seamless integration.

This article will cover everything from setting up your environment and obtaining the necessary SDKs to implementing the video call functionality within your .NET MAUI application. We will also delve into handling permissions, managing the Teams client, and addressing potential challenges.

Why Integrate Microsoft Teams Video Calls into Your .NET MAUI App?

Before we dive into the technical details, let’s explore the benefits of integrating Microsoft Teams video calls into your .NET MAUI application:

  1. Enhanced User Experience: Provide a unified communication experience within your application, eliminating the need for users to switch between different apps.
  2. Improved Collaboration: Facilitate real-time collaboration among users directly within your application.
  3. Increased Engagement: Drive user engagement by offering a more interactive and personal communication channel.
  4. Streamlined Workflows: Integrate video calls into your existing workflows to improve efficiency and productivity.
  5. Customization: Tailor the video call experience to align with your application’s branding and design.

Prerequisites

Before you begin, ensure you have the following prerequisites in place:

  1. .NET MAUI Development Environment: A properly configured .NET MAUI development environment, including Visual Studio or Visual Studio Code with the necessary extensions.
  2. Android SDK: The Android SDK installed and configured for your development environment.
  3. Microsoft Teams Account: A Microsoft Teams account with the necessary permissions to access the Teams API.
  4. Microsoft Azure Account: A Microsoft Azure account to register your application and obtain the necessary credentials.

Step 1: Setting Up Your Azure Application

The first step is to register your application in the Azure Active Directory (Azure AD). This allows your application to securely access the Microsoft Teams API.

1.1. Registering Your Application in Azure AD

  1. Sign in to the Azure portal: Navigate to the Azure portal (portal.azure.com) and sign in with your Azure account.
  2. Navigate to Azure Active Directory: In the left-hand navigation pane, click on “Azure Active Directory.”
  3. App registrations: In the Azure Active Directory blade, click on “App registrations.”
  4. New registration: Click on the “New registration” button.
  5. Register an application:
    • Name: Enter a name for your application (e.g., “My .NET MAUI Teams Integration”).
    • Supported account types: Select the appropriate account type (e.g., “Accounts in this organizational directory only”).
    • Redirect URI (optional): For testing purposes, you can add a redirect URI (e.g., “msal{YourApplicationId}://auth”). You’ll need to change this based on your actual application ID. This is crucial for the authentication flow.
    • Click on the “Register” button.

1.2. Obtaining the Application (Client) ID and Directory (Tenant) ID

  1. Overview blade: Once the application is registered, you will be redirected to the application’s overview blade.
  2. Record the IDs: Note down the “Application (client) ID” and the “Directory (tenant) ID.” You will need these IDs later to configure your .NET MAUI application.

1.3. Configuring API Permissions

  1. API permissions: In the left-hand navigation pane, click on “API permissions.”
  2. Add a permission: Click on the “Add a permission” button.
  3. Microsoft Graph: Select “Microsoft Graph.”
  4. Delegated permissions: Choose “Delegated permissions.” This is crucial for user-specific access.
    • Select the following permissions (at a minimum, but you may need more depending on your exact use case):
      • offline_access
      • openid
      • profile
      • User.Read
      • Teams.ReadBasic.All
      • Calls.Initiate.All
      • Calls.Join.All
  5. Add permissions: Click on the “Add permissions” button.
  6. Grant admin consent: After adding the permissions, you’ll likely need to grant admin consent for your organization. Click the “Grant admin consent for [Your Organization]” button and confirm. This depends on your organization’s policies.

Step 2: Setting Up Your .NET MAUI Project

2.1. Creating a New .NET MAUI Project

  1. Open Visual Studio: Open Visual Studio and create a new project.
  2. Select .NET MAUI App: Choose the “.NET MAUI App” template.
  3. Configure your project:
    • Project name: Enter a name for your project (e.g., “TeamsMauiApp”).
    • Location: Choose a location for your project.
    • Click on the “Create” button.

2.2. Installing Required NuGet Packages

You’ll need to install several NuGet packages to facilitate the integration with Microsoft Teams. The most important one is the Microsoft Authentication Library (MSAL) for .NET.

  1. Open NuGet Package Manager: In Visual Studio, go to “Tools” -> “NuGet Package Manager” -> “Manage NuGet Packages for Solution.”
  2. Install MSAL: Search for “Microsoft.Identity.Client” and install the latest stable version.
  3. Install other required packages: Depending on how you’re planning to handle the Teams API calls (e.g., using HttpClient), you might also need packages like:
    • Microsoft.Graph (If you are using the Graph SDK)
    • Newtonsoft.Json (For JSON Serialization)

2.3. Platform-Specific Setup (Android)

Android requires specific configurations to handle authentication and permissions.

2.3.1. Android Manifest Configuration

Modify your `AndroidManifest.xml` file (located in `Platforms/Android/AndroidManifest.xml`) to include the following configurations:

  1. Permissions: Add the necessary permissions for camera, microphone, and internet access:
    
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.CAMERA" />
        <uses-permission android:name="android.permission.RECORD_AUDIO" />
        <uses-feature android:name="android.hardware.camera" android:required="false" />
        <uses-feature android:name="android.hardware.microphone" android:required="false" />
        <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
        <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
        
  2. Intent Filter for Redirect URI: Add an intent filter to handle the redirect URI after authentication. Replace `{YourApplicationId}` with your actual Application (Client) ID from Azure AD. This is essential for the MSAL authentication flow to return to your app.
    
        <activity android:name="Microsoft.Identity.Client.Platforms.Android.AuthenticationActivity"
                      android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
                      android:label="Authentication Activity"
                      android:exported="true">  <!-- Make sure android:exported is true -->
          <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:scheme="msal{YourApplicationId}"
                  android:host="auth" />
          </intent-filter>
        </activity>
        

2.3.2. Configuring `MauiProgram.cs`

You might need to configure your `MauiProgram.cs` to initialize MSAL or other platform-specific dependencies. This depends on the exact authentication flow you’re implementing.

Step 3: Implementing Authentication with MSAL

Authentication is crucial for accessing Microsoft Teams resources. MSAL provides a robust way to authenticate users and obtain access tokens.

3.1. Creating an Authentication Helper Class

Create a new class (e.g., `AuthenticationHelper.cs`) to encapsulate the authentication logic.


using Microsoft.Identity.Client;

public class AuthenticationHelper
{
    private static IPublicClientApplication _pca;
    private static readonly string[] Scopes = { "User.Read", "Teams.ReadBasic.All", "Calls.Initiate.All", "Calls.Join.All" }; // Add all your required scopes
    private static readonly string ClientId = "{YourApplicationId}"; // Replace with your Application (Client) ID
    private static readonly string TenantId = "{YourTenantId}"; // Replace with your Directory (Tenant) ID
    private static readonly string Authority = $"https://login.microsoftonline.com/{TenantId}";

    public static async Task<AuthenticationResult> AcquireTokenAsync()
    {
        try
        {
            if (_pca == null)
            {
                _pca = PublicClientApplicationBuilder.Create(ClientId)
                    .WithAuthority(Authority)
                    .WithRedirectUri($"msal{ClientId}://auth") // Ensure this matches your AndroidManifest.xml and Azure AD registration
                    .WithParentActivityOrWindow(() => Platform.CurrentActivity)
                    .Build();
            }

            var accounts = await _pca.GetAccountsAsync();
            var firstAccount = accounts.FirstOrDefault();

            AuthenticationResult authResult = await _pca.AcquireTokenSilent(Scopes, firstAccount)
                .ExecuteAsync();

            return authResult;
        }
        catch (MsalUiRequiredException)
        {
            // Interactive authentication is required
            AuthenticationResult authResult = await _pca.AcquireTokenInteractive(Scopes)
                .WithParentActivityOrWindow(() => Platform.CurrentActivity)
                .ExecuteAsync();

            return authResult;
        }
        catch (Exception ex)
        {
            // Handle authentication errors
            Console.WriteLine($"Authentication Error: {ex.Message}");
            return null;
        }
    }

    public static async Task SignOutAsync()
    {
        if (_pca != null)
        {
            var accounts = await _pca.GetAccountsAsync();
            foreach (var account in accounts)
            {
                await _pca.RemoveAsync(account);
            }
        }
    }
}

3.2. Integrating Authentication into Your .NET MAUI App

Call the `AcquireTokenAsync` method when you need to authenticate the user. For example, in a button click event handler:


private async void OnLoginButtonClicked(object sender, EventArgs e)
{
    var authResult = await AuthenticationHelper.AcquireTokenAsync();

    if (authResult != null)
    {
        // Authentication successful
        string accessToken = authResult.AccessToken;
        // Use the access token to call the Teams API
        Console.WriteLine($"Access Token: {accessToken}");
    }
    else
    {
        // Authentication failed
        Console.WriteLine("Authentication failed.");
    }
}

Step 4: Interacting with the Microsoft Teams API

Once you have an access token, you can use it to call the Microsoft Teams API. You can use either the Microsoft Graph API or the direct Teams API endpoints. Using the Graph API is generally recommended.

4.1. Using the Microsoft Graph API

The Microsoft Graph API provides a unified endpoint for accessing various Microsoft 365 services, including Teams.

  1. Install Microsoft.Graph NuGet Package: Ensure you have the `Microsoft.Graph` NuGet package installed.
  2. Create a GraphServiceClient: Create an instance of `GraphServiceClient` using the access token.
    
        using Microsoft.Graph;
        using Microsoft.Graph.Auth;
    
        // ... Inside your class
    
        private GraphServiceClient GetGraphClient(string accessToken)
        {
            var authProvider = new DelegateAuthenticationProvider(async (requestMessage) =>
            {
                requestMessage.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);
            });
    
            return new GraphServiceClient(authProvider);
        }
        
  3. Call the Teams API: Use the `GraphServiceClient` to call the Teams API endpoints. For example, to get the user’s joined Teams:
    
        private async Task GetJoinedTeamsAsync(string accessToken)
        {
            var graphClient = GetGraphClient(accessToken);
    
            try
            {
                var joinedTeams = await graphClient.Me.JoinedTeams
                    .Request()
                    .GetAsync();
    
                foreach (var team in joinedTeams)
                {
                    Console.WriteLine($"Team Name: {team.DisplayName}, Team ID: {team.Id}");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error getting joined teams: {ex.Message}");
            }
        }
        

4.2. Initiating a Teams Video Call

The process of initiating a Teams video call involves several steps. This example demonstrates initiating an ad-hoc meeting.

  1. Create a Meeting Request: You need to create a meeting request with the participants. This typically involves calling the Graph API to create an online meeting.
    
    using Microsoft.Graph;
    
    public class TeamsCallHelper
    {
        private readonly GraphServiceClient _graphClient;
    
        public TeamsCallHelper(GraphServiceClient graphClient)
        {
            _graphClient = graphClient ?? throw new ArgumentNullException(nameof(graphClient));
        }
    
        public async Task<string> CreateAdhocMeetingAsync(List<string> participantUserPrincipalNames)
        {
            var onlineMeeting = new OnlineMeeting
            {
                StartDateTime = DateTimeOffset.UtcNow,
                EndDateTime = DateTimeOffset.UtcNow.AddHours(1),
                Subject = "Ad-hoc Teams Meeting",
                Participants = new MeetingParticipants
                {
                    Attendees = participantUserPrincipalNames.Select(upn => new MeetingParticipantInfo { Identity = new IdentitySet { User = new Identity { UserPrincipalName = upn } } }).ToList()
                }
            };
    
            try
            {
                var createdMeeting = await _graphClient.Me.OnlineMeetings
                    .Request()
                    .AddAsync(onlineMeeting);
    
                return createdMeeting.JoinWebUrl; // Return the join URL.
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error creating ad-hoc meeting: {ex.Message}");
                return null;
            }
        }
    }
    

    Note: This snippet is simplified. In a real-world scenario, you would handle time zones, better error handling, and possibly specify more meeting options.

  2. Get the Join URL: After creating the meeting, retrieve the `JoinWebUrl` from the response. This URL allows participants to join the meeting.
  3. Launch the Teams Client: You need to use an intent to launch the Teams client and pass the join URL. This will require platform-specific code (Android in this case).
    
    //In your .NET MAUI code
    public static void OpenTeamsMeeting(string joinUrl)
    {
        if (string.IsNullOrEmpty(joinUrl)) return;
    
    #if ANDROID
        OpenTeamsMeetingAndroid(joinUrl);
    #endif
    }
    
    #if ANDROID
    [assembly: Dependency(typeof(YourNamespace.Droid.TeamsLauncher))] //Replace YourNamespace
    namespace YourNamespace.Droid
    {
        public class TeamsLauncher
        {
            public static void OpenTeamsMeetingAndroid(string joinUrl)
            {
                try
                {
                    var intent = new Android.Content.Intent(Android.Content.Intent.ActionView, Android.Net.Uri.Parse(joinUrl));
                    intent.SetPackage("com.microsoft.teams"); // Ensure Teams package name is correct
    
                    Android.App.Application.Context.StartActivity(intent);
                }
                catch (Android.Content.ActivityNotFoundException)
                {
                    // Teams app is not installed.  Handle this gracefully (e.g., show a message).
                    // Consider redirecting the user to the Play Store to install Teams.
                    Console.WriteLine("Microsoft Teams is not installed.");
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Error opening Teams meeting: {ex.Message}");
                }
            }
        }
    }
    #endif
    
  4. Handle Teams Not Installed: If the Teams app is not installed, you will receive an `ActivityNotFoundException`. Handle this gracefully by informing the user and potentially redirecting them to the Google Play Store to install Teams.

Step 5: Handling Permissions

Android requires users to grant permissions for accessing the camera and microphone. You need to request these permissions at runtime.

5.1. Requesting Permissions

  1. Use Essentials.Permissions: The `Xamarin.Essentials` library provides a cross-platform way to request permissions.
    
    using Microsoft.Maui.ApplicationModel;
    
    public async Task<PermissionStatus> CheckAndRequestCameraPermission()
    {
        PermissionStatus status = await Permissions.CheckStatusAsync<Permissions.Camera>();
    
        if (status != PermissionStatus.Granted)
        {
            status = await Permissions.RequestAsync<Permissions.Camera>();
        }
    
        return status;
    }
    
    public async Task<PermissionStatus> CheckAndRequestMicrophonePermission()
    {
        PermissionStatus status = await Permissions.CheckStatusAsync<Permissions.Microphone>();
    
        if (status != PermissionStatus.Granted)
        {
            status = await Permissions.RequestAsync<Permissions.Microphone>();
        }
    
        return status;
    }
    
    //Example Usage:
    private async void OnCallButtonClicked(object sender, EventArgs e)
    {
        PermissionStatus cameraStatus = await CheckAndRequestCameraPermission();
        PermissionStatus microphoneStatus = await CheckAndRequestMicrophonePermission();
    
        if (cameraStatus == PermissionStatus.Granted && microphoneStatus == PermissionStatus.Granted)
        {
            //Proceed with the call
            //...
        }
        else
        {
            //Handle permission denial (e.g., show a message)
            Console.WriteLine("Camera or microphone permission denied.");
        }
    }
    
  2. Handle Permission Denials: If the user denies a permission, provide a clear explanation of why the permission is needed and guide them on how to enable it in the device settings.

Step 6: Managing the Teams Client

Handling the Teams client lifecycle is crucial for a seamless integration.

6.1. Checking if Teams is Installed

Before attempting to launch the Teams client, check if it is installed on the device. The previous section shows how this is done. Handle the `ActivityNotFoundException` and guide the user to install Teams if it’s not present.

6.2. Handling Backgrounding and Resuming

When the user switches away from your application to the Teams client, your application may be backgrounded. Implement proper handling for backgrounding and resuming to ensure the user’s state is preserved and the video call continues seamlessly.

Step 7: Error Handling and Troubleshooting

Integrating with external APIs can be complex. Implement robust error handling to gracefully handle potential issues.

7.1. Authentication Errors

Authentication errors can occur due to invalid credentials, network issues, or permission problems. Implement error handling to catch these exceptions and provide informative messages to the user.

7.2. API Errors

API errors can occur due to invalid requests, rate limiting, or server issues. Implement error handling to catch these exceptions and retry the request or inform the user.

7.3. Teams Client Errors

Teams client errors can occur due to installation problems, compatibility issues, or network problems. Handle these errors gracefully and provide helpful guidance to the user.

Best Practices

  1. Use asynchronous programming: Use `async` and `await` to avoid blocking the UI thread when making network requests.
  2. Handle exceptions: Implement comprehensive error handling to gracefully handle potential issues.
  3. Cache access tokens: Cache access tokens to avoid repeatedly prompting the user for credentials.
  4. Use dependency injection: Use dependency injection to make your code more testable and maintainable.
  5. Implement logging: Implement logging to track errors and debug issues.
  6. Follow security best practices: Follow security best practices to protect user data and prevent vulnerabilities.

Example: Complete Calling Sequence

This brings together the various steps.

  1. User initiates a call within your .NET MAUI App.
  2. Your app checks and requests Camera and Microphone permissions.
  3. Your app authenticates the user via MSAL (`AuthenticationHelper.AcquireTokenAsync()`).
  4. Your app obtains an Access Token.
  5. Your app uses the Access Token to call the Microsoft Graph API to create an Ad-hoc meeting (`TeamsCallHelper.CreateAdhocMeetingAsync()`).
  6. Your app receives the meeting Join URL from the Graph API.
  7. Your app launches the Microsoft Teams app via an Android Intent, passing the Join URL. (`TeamsLauncher.OpenTeamsMeetingAndroid()`).
  8. If the Teams app is not installed, your app handles the `ActivityNotFoundException` and prompts the user to install Teams.

Conclusion

Integrating Microsoft Teams video calls into your .NET MAUI Android application can significantly enhance its functionality and user experience. By following this comprehensive guide, you can seamlessly integrate Teams video calls into your application, providing a unified communication experience for your users. Remember to pay close attention to authentication, permissions, and error handling to ensure a robust and secure integration.

This guide provides a solid foundation for integrating Teams video calls. You can customize the implementation further to meet the specific requirements of your application. Good luck!

“`

omcoding

Leave a Reply

Your email address will not be published. Required fields are marked *