diff --git a/sample/Maui.Android.InAppUpdates.SampleApp.csproj b/sample/Maui.Android.InAppUpdates.SampleApp.csproj
index 10cfe02..8fd362e 100644
--- a/sample/Maui.Android.InAppUpdates.SampleApp.csproj
+++ b/sample/Maui.Android.InAppUpdates.SampleApp.csproj
@@ -64,7 +64,7 @@
-
+
diff --git a/src/libs/Maui.Android.InAppUpdates/Maui.Android.InAppUpdates.csproj b/src/libs/Maui.Android.InAppUpdates/Maui.Android.InAppUpdates.csproj
index 24b0f24..77c58e0 100644
--- a/src/libs/Maui.Android.InAppUpdates/Maui.Android.InAppUpdates.csproj
+++ b/src/libs/Maui.Android.InAppUpdates/Maui.Android.InAppUpdates.csproj
@@ -19,7 +19,7 @@
10.0.17763.0
6.5
-
+
Oscore.$(AssemblyName)
NuGet package that implementing Android In-App Updates for MAUI with debugging capabilities.
@@ -27,14 +27,14 @@
-
+
-
-
-
-
+
+
+
+
diff --git a/src/libs/Maui.Android.InAppUpdates/Platforms/Android/DefaultUserInterface.cs b/src/libs/Maui.Android.InAppUpdates/Platforms/Android/DefaultUserInterface.cs
index 908fc34..d4ac321 100644
--- a/src/libs/Maui.Android.InAppUpdates/Platforms/Android/DefaultUserInterface.cs
+++ b/src/libs/Maui.Android.InAppUpdates/Platforms/Android/DefaultUserInterface.cs
@@ -10,17 +10,30 @@ public static class DefaultUserInterface
/// Displays a short duration toast message at the center of the screen.
///
/// The text to be displayed in the toast message.
- public static void ShowShortToast(
- string text)
+ public static void ShowShortToast(string text)
{
- Toast.MakeText(
- context: Platform.AppContext,
- text: text,
- duration: ToastLength.Short)?.Show();
+ try
+ {
+ if (Platform.AppContext is null)
+ {
+ Handler.Options.DebugAction($"Cannot show toast - Platform.AppContext is null: {text}");
+ return;
+ }
+
+ Toast.MakeText(
+ context: Platform.AppContext,
+ text: text,
+ duration: ToastLength.Short)?.Show();
+ }
+ catch (Exception ex)
+ {
+ Handler.Options.DebugAction($"Failed to show toast '{text}': {ex}");
+ }
}
///
/// Displays a snackbar with an action to complete the app update process.
+ /// If snackbar fails due to theme incompatibility, falls back to toast message.
///
/// The text to display on the snackbar.
/// The text for the action button.
@@ -30,18 +43,86 @@ public static void ShowSnackbar(
string actionText,
Action clickHandler)
{
- if (Platform.CurrentActivity?.Window?.DecorView is not {} view ||
- Snackbar.Make(
- text: text,
- duration: BaseTransientBottomBar.LengthIndefinite,
- view: view) is not {} snackbar)
+ var fallbackMessage = $"{text} - {actionText}";
+
+ try
+ {
+ var view = Platform.CurrentActivity?.Window?.DecorView;
+ if (view is null)
+ {
+ FallbackToToastWithAction("Cannot show snackbar - no active view", fallbackMessage, clickHandler, null);
+ return;
+ }
+
+ var snackbar = Snackbar.Make(view, text, BaseTransientBottomBar.LengthIndefinite);
+ if (snackbar is null)
+ {
+ FallbackToToastWithAction("Cannot create snackbar", fallbackMessage, clickHandler, view);
+ return;
+ }
+
+ snackbar.SetAction(text: actionText, clickHandler: clickHandler);
+ snackbar.Show();
+ }
+ catch (Exception ex) when (IsThemeRelated(ex))
+ {
+ HandleSnackbarFailure(ex, "theme related", fallbackMessage, clickHandler, Platform.CurrentActivity?.Window?.DecorView);
+ }
+ catch (Exception ex)
{
- return;
+ HandleSnackbarFailure(ex, "general exception", fallbackMessage, null, null);
}
-
- snackbar.SetAction(
- text: actionText,
- clickHandler: clickHandler);
- snackbar.Show();
}
+
+ private static void FallbackToToastWithAction(
+ string debugMessage,
+ string fallbackMessage,
+ Action? clickHandler,
+ global::Android.Views.View? fallbackView)
+ {
+ Handler.Options.DebugAction($"{debugMessage}, falling back to toast and auto-triggering action");
+ ShowShortToast(fallbackMessage);
+
+ // Auto-trigger the action since user can't click the snackbar
+ if (clickHandler is not null && fallbackView is not null)
+ {
+ try
+ {
+ clickHandler(fallbackView);
+ }
+ catch (Exception actionEx)
+ {
+ Handler.Options.DebugAction($"Error auto-executing snackbar action: {actionEx}");
+ }
+ }
+ }
+
+ private static void HandleSnackbarFailure(
+ Exception ex,
+ string errorType,
+ string fallbackMessage,
+ Action? clickHandler,
+ global::Android.Views.View? view)
+ {
+ Handler.Options.DebugAction($"Snackbar {errorType}: {ex}");
+ ShowShortToast(fallbackMessage);
+
+ // Only auto-trigger for theme-related exceptions where user interaction was expected
+ if (clickHandler is not null && view is not null)
+ {
+ try
+ {
+ clickHandler(view);
+ }
+ catch (Exception actionEx)
+ {
+ Handler.Options.DebugAction($"Error executing snackbar action: {actionEx}");
+ }
+ }
+ }
+
+ private static bool IsThemeRelated(Exception ex) =>
+ ex is global::Android.Views.InflateException ||
+ (ex is Java.Lang.UnsupportedOperationException &&
+ ex.Message?.Contains("Failed to resolve attribute", StringComparison.Ordinal) == true);
}
\ No newline at end of file