.NET MAUIのライフサイクルイベントでローカル通知を受け取ろう

# はじめに
.NET MAUIには、通常「Running(実行中)」、「Not Running(実行されていない)」、「DeActived(非アクティブ)」、「Stopped(停止)」の 4 つの実行状態があります。

そのそれぞれのライフサイクルの状態から別の状態へ変化した時、ライフサイクルイベントが発生し、メソッドを発行することができます。

Microsoft公式より引用
![](https://learn.microsoft.com/en-us/dotnet/maui/fundamentals/media/app-lifecycle/app-lifecycle.png?view=net-maui-7.0)


今回はこのライフサイクルイベントを使用して、「DeActived」非アクティブから「Stopped」停止へ変わった時、ローカル通知を発行するアプリを作っていきます。

# アプリのライフサイクルの状態
4つのアプリの状態について解説します。
|  | 名前 | 状態 |
|:-:|:-:|:-:|
|  1|Running(実行中)   | アプリが実行されている時  |
|  2|Not Running(実行されていない)   | アプリが全く動いていないとき(再起動後など)   |
|  3|DeActived(非アクティブ)  | アプリが別のアプリへフォーカスが移った時  |
|  4|Stopped(停止)   | アプリが停止した時  |

# アプリのライフサイクルイベント
アプリが「Not Running」から「Running」、「Running」から「DeActived」、「DeActived」から「Stopped」、「Stopped」から「Running」、「Stopped」から「Not Running」に移行するときにライフサイクルイベントがあるのですが、それぞれの名称を以下にまとめます。

| イベント名 | 説明 | ここから | に移った時 |
|:-:|:-:|:-:|:-:|
| Created  | アプリが開始されたとき  | Not Running  | Running  |
| Activated | アプリが開始されたとき、およびアプリがフォーカスされたとき  | Not Running  | Running  |
| Deactivated  | 他のアプリにフォーカスが移ったとき  | Running  | DeActived  |
| Stopped  | アプリが表示されなくなったとき  | DeActived  | Stopped  |
| Resumed  | アプリ停止後に実行されたとき(初回起動時は発生しない)  | Stopped  | Running  |
| Destroying  | アプリがアンインストールされたとき？  | Stopped  | Not Running  |

※Destroyingの説明ですが、公式がわかりずらくほんとにアプリがアンインストールされた時なのか不明です。（調査中）

以上を踏まえて今回は「Stopped」イベントから通知を発行する方法について解説していきます。

# 通知のライブラリをNuGet
通知機能を追加するので、以下のライブラリをNuGetします。（Windows,Macには非対応のようです。）

Plugin.LocalNotification
![Plugin.Local.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3007605/dc13c85e-be6b-483f-ffc0-af9a690f439a.png)

このライブラリを使用するためにMauiProgram.csファイルを以下のように追加します。
```cs
public static MauiApp CreateMauiApp()
	{
		var builder = MauiApp.CreateBuilder();
		builder
			.UseMauiApp<App>()
			.UseLocalNotification()//←これを追加
			.ConfigureFonts(fonts =>
			{
				fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
				fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
			});
```

# ライフサイクルイベントと通知処理
標準的な6つのライフサイクルイベントはApp.xaml.csファイルにoverrideで記述します。

```cs
public partial class App : Application
{
	public App()
	{
		InitializeComponent();

		MainPage = new AppShell();
	}
    //追加した処理
    protected override Window CreateWindow(IActivationState activationState)//オーバーライドしているので、そのメソッドを呼び出す。
    {
		Window window= base.CreateWindow(activationState);//Windowクラスのインスタンスを作成する
		window.Stopped += (s, e) =>   //←window.ライフサイクルイベント名(今回はStopped)でイベントハンドラーを作成
		{
            //通知の処理
			var request = new NotificationRequest //ライブラリのNotificationRequestクラスを作成
			{
				NotificationId = 1337,//通知のID(なんでもよい)
				Title = "寝てますよ",//(通知のタイトル)
				Subtitle = "あなたはStoppedによって寝ていました",//(通知のサブタイトル)
				Description = "It's Me",//(説明など)
				BadgeNumber = 0,//(通知バッジのナンバー)
                //通知のスケジュールを設定する
				Schedule = new NotificationRequestSchedule
				{
					NotifyTime = DateTime.Now.AddSeconds(5),//イベントが起こった5秒あとに通知をする処理
				}
			};
			LocalNotificationCenter.Current.Show(request);//通知センターに通知を表示するメソッド
		};
        return window;//windowを返すようにする
    }
}
```
これでプログラムの方は完成になります。

普通にデバッグをしてしまうと、停止をすれば、デバッグも止まってしまうため、ちゃんと動いているのか確認できませんので、デバッグ無しで実行をします。

そうして立ち上がったアプリをタスクキルで削除すると、以下の通り、５秒後通知がきました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3007605/30d24c51-36b8-a824-7577-4c93ed63b34c.png)

# プラットフォームごとのライフサイクルイベントについて
ライフサイクルイベントですが先ほど紹介した6種類の標準的なものに加え、それぞれのプラットフォームによって特別なライフサイクルイベントがあります。
今回詳しくは記載しないため、Microsoft公式を見てもらえばと思います。

https://learn.microsoft.com/en-us/dotnet/maui/fundamentals/app-lifecycle?view=net-maui-7.0#platform-lifecycle-events

また、このプラットフォーム固有のライフサイクルイベントを発行させたいとき、App.xaml.csでoverrideではなく、MauiProgram.csに以下のように拡張メソッドとしての記述となるので、注意です。

```cs
public static MauiApp CreateMauiApp()
   {
     var builder = MauiApp.CreateBuilder();
     builder.UseMauiApp<App>()
     builder.ConfigureLifecycleEvents(AppLifecycle => {
          //Androidのライフサイクルイベント
          #if ANDROID
             AppLifecycle.AddAndroid(android => android
                .OnBackPressed((activity) => BackPressed()));
          #endif
          //iOSのライフサイクルイベント
          #if IOS
             AppLifecycle.AddiOS(ios => ios
                .WillEnterForeground((app) => EnteredForeground()));
          #endif
          //Windowsのライフサイクルイベント
          #if WINDOWS
             AppLifecycle
                .AddWindows(windows =>
                windows.OnNativeMessage((app, args) => {
                app.ExtendsContentIntoTitleBar = false;
                }));
          #endif
  });

     return builder.Build();
   }
```
# さいごに
.NET MAUIのライフサイクルイベントは思ったよりも簡単に作成できます。

この機能を使っていろんなアプリを作ってみてください。