András Tóth‘s professional blog
banditoth.net

Hey there 👋, I’m banditoth a .NET MAUI developer from Hungary.
I write about software development with .NET technologies.

You can find me on:
LinkedIn | Github | StackOverflow | X / Twitter | Threads

Tag: maui

  • .NET MAUI Android Auto : Launching Navigation Apps from your app

    This content has 1 year. Some of the information in this post may be out of date or no longer work. Please, read this page keeping its age in your mind.

    Android Auto is a popular platform that allows users to seamlessly integrate their Android devices with their car’s infotainment system. This integration extends to navigation, allowing users to launch navigation apps like Google Maps or Waze directly from Android Auto. In this blog post, we’ll explore how to achieve this functionality from within your Android application using .NET MAUI.

    The key to launching navigation apps on Android Auto is to construct a URI with the desired latitude and longitude and use an Intent to open the navigation app. Let’s break down the code snippet you provided to understand how it works:

    public class NavigationOnClickListener : Java.Lang.Object, IOnClickListener
    {
        private readonly CarContext _context;
        private readonly double _latitude;
        private readonly double _longitude;
    
        public NavigationOnClickListener(CarContext context, double latitude, double longitude)
        {
            _context = context;
            _latitude = latitude;
            _longitude = longitude;
        }
    
        public void OnClick()
        {
            string uri = $"geo:{_latitude.ToString(CultureInfo.InvariantCulture)},{_longitude.ToString(CultureInfo.InvariantCulture)}";
            Intent intent = new Intent(CarContext.ActionNavigate)
                .SetData(AndroidUri.Parse(uri));
            _context.StartCarApp(intent);
        }
    }
    
    

    AndroidUri is the Android.Net.Uri class alias achieved by:

    using AndroidUri = Android.Net.Uri;
    

    Let’s dissect this code step by step:

    1. NavigationOnClickListener is a custom class that implements the IOnClickListener interface. This class is responsible for handling the click event that launches the navigation app.
    2. In the constructor, we receive three parameters: context, latitude, and longitude. context is the CarContext instance, and latitude and longitude are the destination coordinates (double).
    3. Inside the OnClick method, we construct a URI in the following format: "geo:latitude,longitude". The CultureInfo.InvariantCulture is used to ensure that the decimal separator is a period (.) rather than a comma (,) to make the URI universally compatible. This is crucial because different regions may use different formats for numbers.
    4. We create an Intent with the action CarContext.ActionNavigate. This action specifies that we want to launch a navigation app.
    5. We set the data of the intent by parsing the constructed URI using AndroidUri.Parse(uri).
    6. Finally, we start the navigation app by invoking _context.StartCarApp(intent).
  • .NET MAUI Android Auto: Async loading of lists

    This content has 1 year. Some of the information in this post may be out of date or no longer work. Please, read this page keeping its age in your mind.

    Android Auto has become an integral part of the modern driving experience, allowing users to access important information and features without taking their eyes off the road. In this blog post, we’ll explore how to implement asynchronous loading of lists in Android Auto to ensure a smooth and responsive user experience.

    If you are new how to implement Android Auto in your .NET MAUI Application, then scroll to the very end of this post, and you will find a detailed tutorial video by Christian Strydom how to do it.

    Implementation

    Let’s assume that we have a class with a list of SomeObject named _allItems.
    This list contains the data we want to display in an Android Auto list. If you dont have this private field of List<SomeObject> in your Android Auto Screen class, then define it like this: ‘private List<SomeObject> _allItems;’

    We’ll use the OnGetTemplate method to check whether _allItems has data. If it doesn’t, we’ll start an asynchronous task to load the data and show a loading indicator. If it does, we’ll build the list with the existing data.

    OnGetTemplate modify

    In the OnGetTemplate method, we’ll first create a ListTemplateBuilder and check if _allItems has data:

    public override ITemplate OnGetTemplate()
    {
        var listTemplateBuilder = new ListTemplate.Builder();
    
        if (_allItems?.Any() != true)
        {
            // Start an async task to load data
            _ = LoadData();
    
            // Show a loading indicator
            return listTemplateBuilder.SetLoading(true).Build();
        }
        
        // Build the list using the existing data
        var items = BuildListItems(_allItems);
        listTemplateBuilder.AddItems(items);
    
        return listTemplateBuilder.Build();
    }
    

    Implement the Async Task

    Now, let’s create an asynchronous task, LoadDataAsyncTask, which will invoke a method asynchronously to fetch and set the value of _allItems. We will use a hypothetical API call as an example:

        private async Task LoadData()
        {
            try
            {
                // Perform an asynchronous operation (e.g., an API call)
                var result = await SomeApiCallAsync(); // Replace with your actual API call
    
                // Set the value of _allItems with the result
                _allItems = result;
            }
            catch (Exception e)
            {
                // Handle exceptions and show a CarToast
                CarToast.MakeCarToast(CarContext , "An error occurred", CarToast.DurationLong).Show();
            }
            finally
            {
                // Ensure that the UI is invalidated
                // This will trigger the OnGetTemplate again.
                Invalidate();
            }
        }
    

    Implementing asynchronous loading of lists in Android Auto ensures that your app remains responsive and user-friendly. By following this approach, you can fetch and display data efficiently, handle exceptions gracefully, and maintain a smooth user experience while driving. Android Auto provides a powerful platform for developers to create safe and engaging automotive experiences, and proper asynchronous loading is a key part of that experience.

  • .NET MAUI: Enhancing apps with Microsoft App Center: Analytics and Diagnostics

    This content has 2 years. Some of the information in this post may be out of date or no longer work. Please, read this page keeping its age in your mind.

    As the world of software development continues to evolve, building robust and responsive applications has become crucial. Microsoft’s App Center offers a comprehensive suite of tools designed to streamline the development process and elevate user experiences. In this extended blog post, we’ll dive into integrating Microsoft App Center into .NET MAUI projects, specifically focusing on how Analytics and Diagnostics can provide invaluable insights for developers and project owners.

    What is Microsoft App Center?

    Microsoft App Center is a unified platform that empowers developers to build, test, distribute, and monitor mobile and desktop applications. By offering a wide range of tools and services, App Center enhances collaboration, accelerates development, and ensures the quality and performance of applications.

    Analytics and Diagnostics: Why Are They Important?

    1. Analytics: App Center Analytics provides comprehensive insights into user behavior, enabling developers and project owners to make data-driven decisions. By tracking user interactions, app usage patterns, and feature engagement, you can understand how users are interacting with your application. This data is invaluable for optimizing user experiences, improving user flows, and tailoring your app’s functionalities to better meet user needs.
    2. Diagnostics: Diagnosing and resolving issues quickly is essential for maintaining a positive user experience. App Center Diagnostics helps you monitor crashes and exceptions in real-time, allowing you to identify and address problems as they arise. This feature significantly reduces downtime and enhances app stability, thereby improving user satisfaction and retention.

    Integrating Microsoft App Center into .NET MAUI Projects:

    Integrating Microsoft App Center into your .NET MAUI projects is a straightforward process. The steps closely resemble the integration with Xamarin.Forms.

    Set Up App Center

    1. Create an account on App Center if you don’t have one already.
    2. Follow steps on this link to create new projects within the AppCenter portal: https://learn.microsoft.com/en-us/appcenter/sdk/getting-started/xamarin.

    Add SDK to Your Project

    Install the Microsoft.AppCenter and Microsoft.AppCenter.Analytics packages via NuGet.

    Create a Crash Analytics Service

    Create an interface and an implementation for the crash analytics features (Analytics and Diagnostics):

    public interface ICrashAnalyticsService
    {
        void TrackEvent(string eventName, Dictionary<string, string>? properties = null);
        void TrackError(Exception exception, Dictionary<string, string>? properties = null);
    }
    
    public class CrashAnalyticsService : ICrashAnalyticsService
    {
        public void TrackEvent(string eventName, Dictionary<string, string>? properties = null)
        {
            Analytics.TrackEvent(eventName, properties);
        }
    
        public void TrackError(Exception exception, Dictionary<string, string>? properties = null)
        {
            Crashes.TrackError(exception, properties);
        }
    }
    

    Initialization and dependency registration

    In your MauiProgram.cs file, register the ICrashAnalyticsService in the ServiceProvider:

    using Microsoft.Maui.Controls.Hosting;
    using Microsoft.Extensions.DependencyInjection;
    using YourNamespace.Services; // Import the namespace for your service implementation
    
    public static MauiApp CreateMauiAppBuilder()
    {
        var builder = MauiApp.CreateBuilder();
        // Other configurations
        .....
        builder.Services.AddTransient<ICrashAnalyticsService, CrashAnalyticsService>();
    
        AppCenter.Start("YOUR_APP_CENTER_SECRET",
            typeof(Analytics), typeof(Crashes));
    
        return builder.Build();
    }
    

    Inject and Use Crash Analytics Service:

    In your ViewModel or code-behind (or wherever you want to use analytics or crash reporting), inject the ICrashAnalyticsService and use it to track events and errors:

    using Microsoft.Maui.Controls;
    using YourNamespace.Services; // Import the namespace for the service
    
    public class MainViewModel : BindableObject
    {
        private readonly ICrashAnalyticsService _crashAnalyticsService;
    
        public MainViewModel(ICrashAnalyticsService crashAnalyticsService)
        {
            _crashAnalyticsService = crashAnalyticsService;
        }
    
        public void ImportantButtonClick()
        {
            // Track an analytics event
            var properties = new Dictionary<string, string>
            {
                { "UserID", "123" },
                { "Action", "ButtonClick" }
            };
            _crashAnalyticsService.TrackEvent("ImportantButtonClick", properties);
    
            // Simulate an exception and track the error
            try
            {
                // Simulate an error
                throw new Exception("Simulated error");
            }
            catch (Exception ex)
            {
                _crashAnalyticsService.TrackError(ex, properties);
            }
        }
    }
    

    Conclusion:

    Microsoft App Center is a powerful ally for .NET MAUI developers, offering robust tools for application development, testing, distribution, and monitoring. Analytics and Diagnostics components provide insights that empower developers and project owners to make informed decisions, optimize user experiences, and ensure application stability. By integrating App Center into your .NET MAUI projects, you’re embracing a proactive approach to delivering high-quality, user-centric applications.

    Note: Although .NET MAUI support isn’t available on App Center at the time of writing, it’s important to stay informed about updates. The .NET MAUI community is actively evolving, and it’s possible that support for .NET MAUI on App Center will be available in the near future. This would streamline the integration process and provide a dedicated platform for managing your .NET MAUI applications.

  • .NET MAUI : Creating Customized Popups with Mopups

    This content has 2 years. Some of the information in this post may be out of date or no longer work. Please, read this page keeping its age in your mind.


    Popups are a powerful UI element to engage users with important information, actions, or requests. While the .NET MAUI CommunityToolkit offers simple popup functionality, sometimes you may need more customization and control over your popups. In this tutorial, we will explore how to implement custom popups using the Mopups library in .NET MAUI.

    Prerequisites:

    • A basic understanding of XAML and C#.

    Install NuGet Package

    Open your .NET MAUI project and install the “Mopups” NuGet package by LuckyDucko.

    Initialize Mopups


    In your MauiProgram.cs file, within the CreateMauiAppBuilder method, call .ConfigureMopups() on the host builder to initialize the Mopups library:

    using Mopups;
    // ...
    
    public static MauiApp CreateMauiAppBuilder()
    {
        var builder = MauiApp.CreateBuilder();
        // Other configurations
        builder.ConfigureMopups();
        return builder.Build();
    }
    

    Create a Custom PopupPage


    Add a new ContentPage to your project and modify the base class of the XAML file to PopupPage. Add the necessary namespace declaration for the Mopups.Pages namespace:

    <?xml version="1.0" encoding="utf-8" ?>
    <pages:PopupPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                      xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                      xmlns:pages="clr-namespace:Mopups.Pages;assembly=Mopups"
                      x:Class="YourNamespace.CustomPopupPage">
        <!-- Your custom popup content here -->
    </pages:PopupPage>
    

    Create and Display the Popup


    In your code-behind or ViewModel, you can use the MopupService to create and display your custom popup:

    using Mopups.Services;
    // ...
    
    private async Task ShowCustomPopupAsync()
    {
        await MopupService.Instance.PushAsync(new CustomPopupPage());
    }
    

    Tip: Adding Background Overlay


    To create a partially opaque background that covers the content underneath the popup, you can set the BackgroundColor property of your PopupPage to a HEX color with transparency, like “#99272727”:

    <pages:PopupPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                      xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                      xmlns:pages="clr-namespace:Mopups.Pages;assembly=Mopups"
                      x:Class="YourNamespace.CustomPopupPage"
                      BackgroundColor="#99272727">
        <!-- Your custom popup content here -->
    </pages:PopupPage>
    

    Conclusion


    The Mopups library offers a robust solution for creating customized popups in .NET MAUI applications. With the ability to fully customize the layout and presentation of your popups, Mopups provides the flexibility needed to create engaging user experiences. By following this tutorial, you can easily integrate Mopups into your .NET MAUI projects and leverage its features to create unique and interactive popups for your users.

  • .NET MAUI: iOS ListView disappearing cells

    This content has 2 years. Some of the information in this post may be out of date or no longer work. Please, read this page keeping its age in your mind.

    In this article, we will delve into a persistent .NET MAUI issue affecting ListViews on the iOS platform in .NET 7 builds. While the .NET 8 preview has addressed this issue, developers seeking a solution can employ the BindableLayout as a temporary workaround. We’ll also explore the concept of BindableLayout and touch on the CachingStrategy within ListViews.

    The Problem: Disappearing Cells in ListViews on iOS

    The issue at hand revolves around the behavior of ListViews on the iOS platform in .NET 7 builds. As users scroll through the list elements, the ListView cells mysteriously disappear, causing a jarring experience. While the .NET 8 preview has resolved this vexing problem, the official release is still pending, leaving developers seeking immediate solutions.

    The Workaround: BindableLayout within ScrollView

    A viable workaround to mitigate the disappearing cell issue involves utilizing the BindableLayout within a ScrollView. The BindableLayout.ItemSource property can be harnessed to mimic the ListView’s behavior. However, it’s crucial to acknowledge that this solution might not deliver the same performance as a native ListView.

    Example Code

    Here’s how you can implement the BindableLayout workaround:

    <ScrollView>
        <StackLayout>
            <BindableLayout.ItemsSource>
                <x:Array Type="{x:Type local:ItemModel}">
                    <local:ItemModel Name="Item 1" />
                    <local:ItemModel Name="Item 2" />
                    <local:ItemModel Name="Item 3" />
                    <!-- Add more items here -->
                </x:Array>
            </BindableLayout.ItemsSource>
            <BindableLayout.ItemTemplate>
                <DataTemplate>
                    <Label Text="{Binding Name}" />
                </DataTemplate>
            </BindableLayout.ItemTemplate>
        </StackLayout>
    </ScrollView>
    

    BindableLayout: A Glimpse

    BindableLayout is a versatile feature within the .NET MAUI framework that allows developers to easily bind collections to layout controls. It’s an excellent alternative when dealing with scenarios where a native ListView isn’t performing optimally or in cases like the aforementioned issue. BindableLayout empowers developers to achieve the desired UI layout while maintaining data synchronization.

    Use BindableLayout when you want more control over the layout of your items, need to create a dynamic UI with varying layouts, and don’t necessarily require built-in performance optimizations.

    Understanding CachingStrategy within ListViews

    ListViews in .NET MAUI come with a property known as CachingStrategy. This property determines how the ListView should cache its visual elements, significantly influencing performance. There are three options:

    1. RecycleElement: This strategy reuses existing cells, enhancing memory usage and rendering speed. However, it might pose issues when complex cell layouts are used.
    2. RetainElement: This strategy preserves cells for the duration of the ListView’s existence. While memory consumption can be higher, it can be useful for more intricate cell layouts.
    3. None: In this strategy, no caching is employed, causing cells to be created and destroyed frequently. While it minimizes memory usage, it can have an adverse impact on performance.

    Conclusion

    While the .NET MAUI framework continues to evolve, issues like the disappearing ListView cells on iOS in .NET 7 builds are inevitable. Developers eagerly anticipate the benefits that .NET 8 will bring, including the resolution of this particular problem. In the interim, the BindableLayout within a ScrollView offers a workaround that replicates the ListView’s behavior, albeit with potential performance differences. By understanding concepts like BindableLayout and the CachingStrategy within ListViews, developers can navigate these challenges while continuing to create engaging and efficient cross-platform applications. Stay tuned for the official .NET 8 release and more innovations that will undoubtedly enhance the .NET MAUI experience.

    https://github.com/dotnet/maui/issues/11640