Skip to content

Commit

Permalink
Make Essentials lifecycle registration happen by default (#4221)
Browse files Browse the repository at this point in the history
* Make ConfigureEssentials host builder a thing

* Clean up windows window messages + lifecycle

* Add windows lifecycle for window subclassed

* Add OnCreate to Android's lifecycle events which are invoked

Also removes the overrides from the templates since these are now wired up automatically for Essentials

* Fix ordering of base call to OnRequestPermissionsResult

This should come first so that apps have an opportunity to handle this before the base does.

* Remove redundant OnLaunched call in Windows' templates

* Move UseEssentials into the "useDefaults" scope

* Revert duplicate oncreate lifecycle event invocation
  • Loading branch information
Redth committed Jan 26, 2022
1 parent cdf43da commit 34e1af5
Show file tree
Hide file tree
Showing 15 changed files with 83 additions and 136 deletions.

This file was deleted.

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
Expand All @@ -9,22 +9,31 @@

namespace Microsoft.Maui.Essentials
{
public interface IEssentialsBuilder
{
IEssentialsBuilder UseMapServiceToken(string token);

IEssentialsBuilder AddAppAction(AppAction appAction);

IEssentialsBuilder OnAppAction(Action<AppAction> action);

IEssentialsBuilder UseVersionTracking();
}

public static class EssentialsExtensions
{
public static MauiAppBuilder ConfigureEssentials(this MauiAppBuilder builder, Action<IEssentialsBuilder> configureDelegate = null)
internal static MauiAppBuilder UseEssentials(this MauiAppBuilder builder)
{
if (configureDelegate != null)
{
builder.Services.AddSingleton<EssentialsRegistration>(new EssentialsRegistration(configureDelegate));
}
builder.Services.TryAddEnumerable(ServiceDescriptor.Transient<IMauiInitializeService, EssentialsInitializer>());

builder.ConfigureLifecycleEvents(life =>
{
#if __ANDROID__
Platform.Init(MauiApplication.Current);
life.AddAndroid(android => android
.OnCreate((activity, savedInstanceState) =>
{
Platform.Init(activity, savedInstanceState);
})
.OnRequestPermissionsResult((activity, requestCode, permissions, grantResults) =>
{
Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
Expand Down Expand Up @@ -53,6 +62,10 @@ public static MauiAppBuilder ConfigureEssentials(this MauiAppBuilder builder, Ac
}));
#elif WINDOWS
life.AddWindows(windows => windows
.OnNativeMessage((window, args) =>
{
Platform.NewWindowProc(args.Hwnd, args.MessageId, args.WParam, args.LParam);
})
.OnActivated((window, args) =>
{
Platform.OnActivated(window, args);
Expand All @@ -67,7 +80,18 @@ public static MauiAppBuilder ConfigureEssentials(this MauiAppBuilder builder, Ac
return builder;
}

public static IEssentialsBuilder AddAppAction(this IEssentialsBuilder essentials, string id, string title, string subtitle = null, string icon = null) =>
public static MauiAppBuilder ConfigureEssentials(this MauiAppBuilder builder, Action<IEssentialsBuilder>? configureDelegate = null)
{
if (configureDelegate != null)
{
builder.Services.AddSingleton<EssentialsRegistration>(new EssentialsRegistration(configureDelegate));
}
builder.Services.TryAddEnumerable(ServiceDescriptor.Transient<IMauiInitializeService, EssentialsInitializer>());

return builder;
}

public static IEssentialsBuilder AddAppAction(this IEssentialsBuilder essentials, string id, string title, string? subtitle = null, string? icon = null) =>
essentials.AddAppAction(new AppAction(id, title, subtitle, icon));

internal class EssentialsRegistration
Expand All @@ -88,7 +112,7 @@ internal void RegisterEssentialsOptions(IEssentialsBuilder essentials)
class EssentialsInitializer : IMauiInitializeService
{
private readonly IEnumerable<EssentialsRegistration> _essentialsRegistrations;
private EssentialsBuilder _essentialsBuilder;
private EssentialsBuilder? _essentialsBuilder;

public EssentialsInitializer(IEnumerable<EssentialsRegistration> essentialsRegistrations)
{
Expand Down Expand Up @@ -127,20 +151,20 @@ public async void Initialize(IServiceProvider services)
VersionTracking.Track();
}

void HandleOnAppAction(object sender, AppActionEventArgs e)
void HandleOnAppAction(object? sender, AppActionEventArgs e)
{
_essentialsBuilder.AppActionHandlers?.Invoke(e.AppAction);
_essentialsBuilder?.AppActionHandlers?.Invoke(e.AppAction);
}
}

class EssentialsBuilder : IEssentialsBuilder
{
internal readonly List<AppAction> AppActions = new List<AppAction>();
internal Action<AppAction> AppActionHandlers;
internal Action<AppAction>? AppActionHandlers;
internal bool TrackVersions;

#pragma warning disable CS0414 // Remove unread private members
internal string MapServiceToken;
internal string? MapServiceToken;
#pragma warning restore CS0414 // Remove unread private members

public IEssentialsBuilder UseMapServiceToken(string token)
Expand Down
3 changes: 3 additions & 0 deletions src/Core/src/Hosting/MauiAppBuilder.cs
Expand Up @@ -8,6 +8,7 @@
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.EventLog;
using Microsoft.Maui.Essentials;
using Microsoft.Maui.LifecycleEvents;

namespace Microsoft.Maui.Hosting
Expand Down Expand Up @@ -55,6 +56,8 @@ internal MauiAppBuilder(bool useDefaults = true)
this.ConfigureAnimations();
this.ConfigureCrossPlatformLifecycleEvents();
this.ConfigureDispatching();

this.UseEssentials();
}
}

Expand Down
1 change: 1 addition & 0 deletions src/Core/src/LifecycleEvents/Windows/WindowsLifecycle.cs
Expand Up @@ -10,6 +10,7 @@ public static class WindowsLifecycle
public delegate void OnNativeMessage(UI.Xaml.Window window, WindowsNativeMessageEventArgs args);
public delegate void OnWindowCreated(UI.Xaml.Window window);
public delegate void OnResumed(UI.Xaml.Window window);
public delegate void OnNativeWindowSubclassed(UI.Xaml.Window window, WindowsNativeWindowSubclassedEventArgs args);

// Internal events
internal delegate void OnMauiContextCreated(IMauiContext mauiContext);
Expand Down
Expand Up @@ -10,6 +10,7 @@ public static class WindowsLifecycleBuilderExtensions
public static IWindowsLifecycleBuilder OnWindowCreated(this IWindowsLifecycleBuilder lifecycle, WindowsLifecycle.OnWindowCreated del) => lifecycle.OnEvent(del);
public static IWindowsLifecycleBuilder OnResumed(this IWindowsLifecycleBuilder lifecycle, WindowsLifecycle.OnResumed del) => lifecycle.OnEvent(del);
public static IWindowsLifecycleBuilder OnNativeMessage(this IWindowsLifecycleBuilder lifecycle, WindowsLifecycle.OnNativeMessage del) => lifecycle.OnEvent(del);
public static IWindowsLifecycleBuilder OnNativeWindowSubclassed(this IWindowsLifecycleBuilder lifecycle, WindowsLifecycle.OnNativeWindowSubclassed del) => lifecycle.OnNativeWindowSubclassed(del);

internal static IWindowsLifecycleBuilder OnMauiContextCreated(this IWindowsLifecycleBuilder lifecycle, WindowsLifecycle.OnMauiContextCreated del) => lifecycle.OnEvent(del);
}
Expand Down
Expand Up @@ -73,9 +73,9 @@ protected override void OnRestart()

public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
{
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);

MauiApplication.Current?.Services?.InvokeLifecycleEvents<AndroidLifecycle.OnRequestPermissionsResult>(del => del(this, requestCode, permissions, grantResults));

base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}

protected override void OnRestoreInstanceState(Bundle savedInstanceState)
Expand Down
1 change: 1 addition & 0 deletions src/Core/src/Platform/Android/MauiAppCompatActivity.cs
@@ -1,5 +1,6 @@
using Android.OS;
using AndroidX.AppCompat.App;
using Microsoft.Maui.LifecycleEvents;
using Microsoft.Maui.Platform;

namespace Microsoft.Maui
Expand Down
20 changes: 7 additions & 13 deletions src/Core/src/Platform/Windows/MauiWinUIWindow.cs
Expand Up @@ -10,22 +10,13 @@ public class MauiWinUIWindow : UI.Xaml.Window
bool _enableResumeEvent;
public MauiWinUIWindow()
{
NativeMessage += OnNativeMessage;
Activated += OnActivated;
Closed += OnClosed;
VisibilityChanged += OnVisibilityChanged;

SubClassingWin32();
}

protected virtual void OnNativeMessage(object? sender, WindowsNativeMessageEventArgs args)
{
if (args.MessageId == WindowsNativeMessageIds.WM_SETTINGCHANGE || args.MessageId == WindowsNativeMessageIds.WM_THEMECHANGE)
MauiWinUIApplication.Current.Application?.ThemeChanged();

MauiWinUIApplication.Current.Services?.InvokeLifecycleEvents<WindowsLifecycle.OnNativeMessage>(m => m(this, args));
}

protected virtual void OnActivated(object sender, UI.Xaml.WindowActivatedEventArgs args)
{
if (args.WindowActivationState != UI.Xaml.WindowActivationState.Deactivated)
Expand All @@ -49,8 +40,6 @@ protected virtual void OnVisibilityChanged(object sender, UI.Xaml.WindowVisibili
MauiWinUIApplication.Current.Services?.InvokeLifecycleEvents<WindowsLifecycle.OnVisibilityChanged>(del => del(this, args));
}

public event EventHandler<WindowsNativeMessageEventArgs> NativeMessage;

#region Native Window

IntPtr _hwnd = IntPtr.Zero;
Expand All @@ -76,17 +65,22 @@ void SubClassingWin32()
if (_hwnd == IntPtr.Zero)
throw new NullReferenceException("The Window Handle is null.");

MauiWinUIApplication.Current.Services?.InvokeLifecycleEvents<WindowsLifecycle.OnNativeWindowSubclassed>(
del => del(this, new WindowsNativeWindowSubclassedEventArgs(_hwnd)));

newWndProc = new WinProc(NewWindowProc);
oldWndProc = SetWindowLongPtr(_hwnd, /* GWL_WNDPROC */ -4, newWndProc);
}

IntPtr NewWindowProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
{
if (msg == WindowsNativeMessageIds.WM_SETTINGCHANGE || msg == WindowsNativeMessageIds.WM_THEMECHANGE)
MauiWinUIApplication.Current.Application?.ThemeChanged();

var args = new WindowsNativeMessageEventArgs(hWnd, msg, wParam, lParam);

NativeMessage?.Invoke(this, args);
MauiWinUIApplication.Current.Services?.InvokeLifecycleEvents<WindowsLifecycle.OnNativeMessage>(m => m(this, args));

Essentials.Platform.NewWindowProc(hWnd, msg, wParam, lParam);
return CallWindowProc(oldWndProc, hWnd, msg, wParam, lParam);
}

Expand Down
@@ -0,0 +1,14 @@
using System;

namespace Microsoft.Maui.Platform
{
public class WindowsNativeWindowSubclassedEventArgs : EventArgs
{
public WindowsNativeWindowSubclassedEventArgs(IntPtr hwnd)
{
Hwnd = hwnd;
}

public IntPtr Hwnd { get; private set; }
}
}
26 changes: 3 additions & 23 deletions src/Essentials/samples/Samples/App.xaml.cs
Expand Up @@ -16,34 +16,14 @@ public App()
{
InitializeComponent();

VersionTracking.Track();

MainPage = new NavigationPage(new HomePage());

SetUpAppActions();
}

async void SetUpAppActions()
{
try
{
await AppActions.SetAsync(
new AppAction("app_info", "App Info", icon: "app_info_action_icon"),
new AppAction("battery_info", "Battery Info"));

AppActions.OnAppAction += AppActions_OnAppAction;
}
catch (FeatureNotSupportedException ex)
{
Debug.WriteLine($"{nameof(AppActions)} Exception: {ex}");
}
}

void AppActions_OnAppAction(object sender, AppActionEventArgs e)
public static void HandleAppActions(AppAction appAction)
{
MainPage.Dispatcher.Dispatch(async () =>
App.Current.Dispatcher.Dispatch(async () =>
{
var page = e.AppAction.Id switch
var page = appAction.Id switch
{
"battery_info" => new BatteryPage(),
"app_info" => new AppInfoPage(),
Expand Down
44 changes: 13 additions & 31 deletions src/Essentials/samples/Samples/Startup.cs
@@ -1,5 +1,6 @@
using Microsoft.Maui;
using Microsoft.Maui.Controls.Hosting;
using Microsoft.Maui.Essentials;
using Microsoft.Maui.Hosting;
using Microsoft.Maui.LifecycleEvents;

Expand All @@ -9,41 +10,22 @@ public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var appBuilder = MauiApp.CreateBuilder();
var builder = MauiApp.CreateBuilder();

#if WINDOWS
Microsoft.Maui.Essentials.Platform.MapServiceToken =
"RJHqIE53Onrqons5CNOx~FrDr3XhjDTyEXEjng-CRoA~Aj69MhNManYUKxo6QcwZ0wmXBtyva0zwuHB04rFYAPf7qqGJ5cHb03RCDw1jIW8l";
#endif

appBuilder
.ConfigureLifecycleEvents(lifecycle =>
builder
.UseMauiApp<App>()
.ConfigureEssentials(essentials =>
{
#if __IOS__
lifecycle
.AddiOS(iOS => iOS
.OpenUrl((app, url, options) =>
Microsoft.Maui.Essentials.Platform.OpenUrl(app, url, options))
.ContinueUserActivity((application, userActivity, completionHandler) =>
Microsoft.Maui.Essentials.Platform.ContinueUserActivity(application, userActivity, completionHandler))
.PerformActionForShortcutItem((application, shortcutItem, completionHandler) =>
Microsoft.Maui.Essentials.Platform.PerformActionForShortcutItem(application, shortcutItem, completionHandler)));
#elif WINDOWS
lifecycle
.AddWindows(windows =>
{
windows
.OnLaunched((app, e) =>
Microsoft.Maui.Essentials.Platform.OnLaunched(e));
windows
.OnActivated((window, e) =>
Microsoft.Maui.Essentials.Platform.OnActivated(window, e));
});
essentials.UseVersionTracking();
#if WINDOWS
essentials.UseMapServiceToken("RJHqIE53Onrqons5CNOx~FrDr3XhjDTyEXEjng-CRoA~Aj69MhNManYUKxo6QcwZ0wmXBtyva0zwuHB04rFYAPf7qqGJ5cHb03RCDw1jIW8l");
#endif
})
.UseMauiApp<App>();
essentials.AddAppAction("app_info", "App Info", icon: "app_info_action_icon");
essentials.AddAppAction("battery_info", "Battery Info");
essentials.OnAppAction(App.HandleAppActions);
});

return appBuilder.Build();
return builder.Build();
}
}
}
Expand Up @@ -7,16 +7,4 @@ namespace MauiApp._1;
[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize)]
public class MainActivity : MauiAppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Platform.Init(this, savedInstanceState);
}

public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
{
Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);

base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
Expand Up @@ -20,12 +20,5 @@ public App()
}

protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();

protected override void OnLaunched(LaunchActivatedEventArgs args)
{
base.OnLaunched(args);

Platform.OnLaunched(args);
}
}

Expand Up @@ -7,16 +7,4 @@ namespace MauiApp._1;
[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize)]
public class MainActivity : MauiAppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Platform.Init(this, savedInstanceState);
}

public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
{
Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);

base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
}

0 comments on commit 34e1af5

Please sign in to comment.