How do I read a deployed file in MAUI/Xamarin on Android

Viewed 2830

I have a small MAUI app i'm testing with. Im trying to read a file that was part of the deployment. I have the code below, which works great in a Windows deploy of the MAUI app, but crashes in Android. What is the proper cross-platform way to do this?

        // TODO get from service or xml
        var path = AppDomain.CurrentDomain.BaseDirectory;
        //var path = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location);
        var fullpath = Path.Combine(path, "Services\\questions.json");
        var json = File.ReadAllText(fullpath);
1 Answers

MAUI has a new way to access files included with the app: MauiAsset.

Described in blog Announcing .NET MAUI Preview 4, Raw Assets:

.NET MAUI now makes it very easy to add other assets to your project and reference them directly while retaining platform-native performance. For example, if you want to display a static HTML file in a WebView you can add the file to your project and annotate it as a MauiAsset in the properties.

<MauiAsset Include="Resources\Raw\index.html" />

Tip: you can also use wildcards to enable all files in a directory:

... Include="Resources\Raw\*" ...

Then you can use it in your application by filename.

<WebView Source="index.html" />

UPDATE

However, the feature MauiAsset apparently still needs improvement:

open issue - MauiAsset is very hard to use.

There we learn that for now:

Set BuildAction in each file's properties to MauiAsset.

That is, its not recommended to use the "wildcard" approach at this time. Set that build action on each file in solution explorer / your project / the file.

Accessing on Windows requires a work-around:

#if WINDOWS
    var stream = await Microsoft.Maui.Essentials.FileSystem.OpenAppPackageFileAsync("Assets/" + filePath);
#else
    var stream = await Microsoft.Maui.Essentials.FileSystem.OpenAppPackageFileAsync(filePath);
#endif

NOTE: This will be simplified at some point; follow that issue to see progress.


UPDATE

The current MAUI template is missing some platform-specific flags. For now, add your own flag to identify when the code is running on Windows:

enter image description here


Complete example in ToolmakerSteve - repo MauiSOAnswers. See MauiAssetPage.

MauiAssetPage.xaml:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MauiTests.MauiAssetPage">
    <ContentPage.Content>
        <!-- By the time Maui is released, this is all you will need. -->
        <!-- The Init code-behind won't be needed. -->
        <WebView x:Name="MyWebView" Source="TestWeb.html" />
    </ContentPage.Content>
</ContentPage>

MauiAssetPage.xaml.cs:

using Microsoft.Maui.Controls;
using System.Threading.Tasks;

namespace MauiTests
{
    public partial class MauiAssetPage : ContentPage
    {
        public MauiAssetPage()
        {
            InitializeComponent();

            Device.BeginInvokeOnMainThread(async () =>
            {
                await InitAsync();
            });
        }

        private async Task InitAsync()
        {
            string filePath = "TestWeb.html";
#if WINDOWS
            var stream = await Microsoft.Maui.Essentials.FileSystem.OpenAppPackageFileAsync("Assets/" + filePath);
#else
            var stream = await Microsoft.Maui.Essentials.FileSystem.OpenAppPackageFileAsync(filePath);
#endif

            if (stream != null)
            {
                string s = (new System.IO.StreamReader(stream)).ReadToEnd();
                this.MyWebView.Source = new HtmlWebViewSource { Html = s };
            }
        }
    }
}

TestWeb.html:

(whatever html you want)

In Solution Explorer, add TestWeb.html to your project. In its Properties, select Build Action = MauiAsset.

Related