From 27ec911760b0a78428e7d6e58510b8af69fb7587 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Tue, 21 Oct 2025 14:29:04 -0500 Subject: [PATCH] [android] fix Aspire integration / env vars I was trying to run a `dotnet new maui` project in .NET 10 RC 2, which crashed with: 10-21 14:14:34.785 14069 14069 E AndroidRuntime: FATAL EXCEPTION: main 10-21 14:14:34.785 14069 14069 E AndroidRuntime: Process: com.companyname.hellomaui, PID: 14069 10-21 14:14:34.785 14069 14069 E AndroidRuntime: android.runtime.JavaProxyThrowable: [System.IndexOutOfRangeException]: Arg_IndexOutOfRangeException 10-21 14:14:34.785 14069 14069 E AndroidRuntime: at Microsoft.Maui.Hosting.AppHostBuilderExtensions+<>c.b__2_2 + 0x0(Unknown Source) 10-21 14:14:34.785 14069 14069 E AndroidRuntime: at System.Linq.Enumerable.ToDictionary + 0x8c(Unknown Source) 10-21 14:14:34.785 14069 14069 E AndroidRuntime: at System.Linq.Enumerable.ToDictionary + 0x0(Unknown Source) 10-21 14:14:34.785 14069 14069 E AndroidRuntime: at Microsoft.Maui.Hosting.AppHostBuilderExtensions.ConfigureEnvironmentVariables + 0x5a(Unknown Source) 10-21 14:14:34.785 14069 14069 E AndroidRuntime: at Microsoft.Maui.Hosting.MauiAppBuilder..ctor + 0x12e(Unknown Source) 10-21 14:14:34.785 14069 14069 E AndroidRuntime: at Microsoft.Maui.Hosting.MauiApp.CreateBuilder + 0x0(Unknown Source) 10-21 14:14:34.785 14069 14069 E AndroidRuntime: at hellomaui.MauiProgram.CreateMauiApp + 0x0(Unknown Source) 10-21 14:14:34.785 14069 14069 E AndroidRuntime: at hellomaui.MainApplication.CreateMauiApp + 0x0(Unknown Source) 10-21 14:14:34.785 14069 14069 E AndroidRuntime: at Microsoft.Maui.MauiApplication.OnCreate + 0xb(Unknown Source) 10-21 14:14:34.785 14069 14069 E AndroidRuntime: at Android.App.Application.n_OnCreate + 0x16(Unknown Source) 10-21 14:14:34.785 14069 14069 E AndroidRuntime: at crc6488302ad6e9e4df1a.MauiApplication.n_onCreate(Native Method) 10-21 14:14:34.785 14069 14069 E AndroidRuntime: at crc6488302ad6e9e4df1a.MauiApplication.onCreate(MauiApplication.java:17) 10-21 14:14:34.785 14069 14069 E AndroidRuntime: at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1381) 10-21 14:14:34.785 14069 14069 E AndroidRuntime: at android.app.ActivityThread.handleBindApplication(ActivityThread.java:7830) 10-21 14:14:34.785 14069 14069 E AndroidRuntime: at android.app.ActivityThread.-$$Nest$mhandleBindApplication(Unknown Source:0) 10-21 14:14:34.785 14069 14069 E AndroidRuntime: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2546) 10-21 14:14:34.785 14069 14069 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:110) 10-21 14:14:34.785 14069 14069 E AndroidRuntime: at android.os.Looper.loopOnce(Looper.java:248) 10-21 14:14:34.785 14069 14069 E AndroidRuntime: at android.os.Looper.loop(Looper.java:338) 10-21 14:14:34.785 14069 14069 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:9067) 10-21 14:14:34.785 14069 14069 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method) 10-21 14:14:34.785 14069 14069 E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:593) 10-21 14:14:34.785 14069 14069 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:932) Reviewing the existing code: https://github.com/dotnet/maui/blob/a4c124661c1e3c2f530ff2d4ec4c0a86eda8fcbb/src/Core/src/Hosting/Dispatching/AppHostBuilderExtensions.cs#L53-L57 So, I looked at the contents of: > adb pull /data/local/tmp/ide-launchenv.txt /data/local/tmp/ide-launchenv.txt: 1 file pulled, 0 skipped. 0.0 MB/s (3 bytes in 0.002s) The file contains a line with a space character and a newline. No idea what put that there?!? I think the `Select(line => line.Split('=', 2))` call is problematic, in addition to the `ToDictionary()` call. I think both of these could throw exceptions on malformed / weird files. I also got "nerd sniped" to improve the performance: * `System.IO.File.ReadAllLines()` allocates a `string[]` * `line.Split('=', 2)` allocates a `string[]` * `ToDictionary(...)` allocates a dictionary and enumerates everything again. We can just flatten the System.Linq usage here into a `foreach` loop and avoid those allocations. We can also use `IndexOf('=')` to find the split point. After these changes, the app no longer crashes and starts up fine. --- .../Dispatching/AppHostBuilderExtensions.cs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/Core/src/Hosting/Dispatching/AppHostBuilderExtensions.cs b/src/Core/src/Hosting/Dispatching/AppHostBuilderExtensions.cs index d0cecdad3339..616635021141 100644 --- a/src/Core/src/Hosting/Dispatching/AppHostBuilderExtensions.cs +++ b/src/Core/src/Hosting/Dispatching/AppHostBuilderExtensions.cs @@ -50,16 +50,15 @@ public static MauiAppBuilder ConfigureEnvironmentVariables(this MauiAppBuilder b // If the file not exists, we will use the default environment variables which is less stable if (OperatingSystem.IsAndroid() && System.IO.File.Exists(androidEnvVarFilePath)) { - var envVarLines = System.IO.File.ReadAllLines(androidEnvVarFilePath); - - var fileEnvironmentVariables = envVarLines - .Select(line => line.Split('=', 2)) - .ToDictionary(parts => parts[0], parts => parts[1]); - - // Merge file environment variables into the existing environment variables - foreach (var kvp in fileEnvironmentVariables) + foreach (var line in System.IO.File.ReadLines(androidEnvVarFilePath)) { - environmentVariables[kvp.Key] = kvp.Value; + int index = line.IndexOf('=', StringComparison.Ordinal); + if (index > 0) + { + string key = line.Substring(0, index); + string value = line.Substring(index + 1); // May be empty for values like "KEY=" + environmentVariables[key] = value; + } } } #endif