How to Implement Auto-Update in a .NET MAUI Android App

Learn to implement in-app auto-updates for .NET MAUI Android apps. This guide covers version checks, APK downloads, FileProvider setup, and installation.

  1. Create a version query text file or API on the server.

    1
    2
    
    HttpClient httpClient = new();
    var response = await httpClient.GetStringAsync("http://x.x.x.x/version.txt");
    
  2. Check the local app version and compare it to determine if an update is needed.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
    // Basic information
    string name = AppInfo.Current.Name;
    string package = AppInfo.Current.PackageName;
    string version = AppInfo.Current.VersionString;
    string build = AppInfo.Current.BuildString;
    // Detailed information
    var Text = VersionTracking.Default.IsFirstLaunchEver.ToString();
    Text = VersionTracking.Default.IsFirstLaunchForCurrentVersion.ToString();
    Text = VersionTracking.Default.IsFirstLaunchForCurrentBuild.ToString();
    Text = VersionTracking.Default.CurrentVersion.ToString();
    Text = VersionTracking.Default.CurrentBuild.ToString();
    Text = VersionTracking.Default.FirstInstalledVersion.ToString();
    Text = VersionTracking.Default.FirstInstalledBuild.ToString();
    Text = String.Join(',', VersionTracking.Default.VersionHistory);
    Text = String.Join(',', VersionTracking.Default.BuildHistory);
    
    // These two properties may be null if this is the first version
    Text = VersionTracking.Default.PreviousVersion?.ToString() ?? "none";
    Text = VersionTracking.Default.PreviousBuild?.ToString() ?? "none";
    
  3. Download the new app version (refer to C# HttpClient Download Progress), and save it to the directory Android.App.Application.Context.GetExternalFilesDir(null), FileSystem.Current.CacheDirectory, or Android.App.Application.Context.GetExternalCacheDirs().First().AbsolutePath.

  4. Start the installation process.
    Add permission settings to the application tag in the AndroidManifest.xml file.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="${applicationId}.provider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/provider_paths" />
    </provider>
    

    Add package-related permissions.

    1
    2
    3
    4
    
    <uses-permission android:name="android.permission.INSTALL_PACKAGES" />
    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
    <uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />
    <uses-permission android:name="android.permission.DELETE_PACKAGES" />
    

    Create an xml folder in \Platforms\Android\Resources, and create a provider_paths.xml file in it. Set the file’s Build Action to AndroidResource. The content of the provider_paths.xml file is as follows.

    1
    2
    3
    4
    5
    6
    7
    
    <?xml version="1.0" encoding="utf-8" ?> 
    <paths xmlns:android="schemas.android.com/apk/res/android"> 
        <external-path name="external_files" path="." />
        <external-files-path name="external_files_path" path="." />
        <files-path name="internal_files_path" path="." />
        <cache-path name="internal_cache_path" path="." />
    </paths>
    

    The installation code is as follows.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    
    async Task InstallAPK()
    {
    #if ANDROID
        var context = Android.App.Application.Context;
        var path = Path.Combine(Android.App.Application.Context.GetExternalFilesDir(null).AbsolutePath, "com.companyname.mauiapp.apk"); // files folder
        path = Path.Combine(Android.App.Application.Context.GetExternalCacheDirs().First().AbsolutePath, "com.companyname.mauiapp.apk"); // cache folder
        Java.IO.File file = new Java.IO.File(path);
    
        try
        {
            using (Android.Content.Intent install = new Android.Content.Intent(Android.Content.Intent.ActionView))
            {
                Android.Net.Uri apkURI = AndroidX.Core.Content.FileProvider.GetUriForFile(context, context.ApplicationContext.PackageName + ".provider", file);
                apkURI = Microsoft.Maui.Storage.FileProvider.GetUriForFile(context, context.ApplicationContext.PackageName + ".provider", file); // Using MAUI library
                install.SetDataAndType(apkURI, "application/vnd.android.package-archive");
                install.AddFlags(Android.Content.ActivityFlags.NewTask);
                install.AddFlags(Android.Content.ActivityFlags.GrantReadUriPermission);
                install.AddFlags(Android.Content.ActivityFlags.ClearTop);
                install.PutExtra(Android.Content.Intent.ExtraNotUnknownSource, true);
    
                Platform.CurrentActivity.StartActivity(install);
            }
        }
        catch (Exception ex)
        {
        }
    #endif
    }
    

    If using Platform.CurrentActivity.StartActivityForResult(install); to perform the installation, override the OnActivityResult method in MainActivity.

    1
    2
    3
    4
    
    protected override void OnActivityResult(int requestCode, Result resultCode, Intent? data)
    {
        base.OnActivityResult(requestCode, resultCode, data);
    }
    
  5. Clean up the installation package Receiving Package Install/Uninstall Broadcasts in MAUI (Android).

Built with Hugo
Theme Stack designed by Jimmy