読者です 読者をやめる 読者になる 読者になる

しっぽを追いかけて

ぐるぐるしながら考えています

Unity と猫の話題が中心   掲載内容は個人の私見であり、所属組織の見解ではありません

Xamarin.Forms の App Lifecycle の呼び出され方を調べたい 【Windows Phone 8.0 編】

Windows ランタイムアプリ Windows Phone Xamarin C#

前回 で作成したアプリ基盤をもとに Windows Phone 8.0 でのアプリケーションライフサイクルの動作を確かめてみたいと思います

まずは Windows Phone 8.0 のアプリケーション状態遷移のおさらい

App activation and deactivation for Windows Phone 8

f:id:matatabi_ux:20150307200938p:plain

Not Running、Running、Dormant、Tombstoned の 4つの状態があり、Tombstoned に遷移するとメモリが解放されるので、再開時にデータを復帰させる対応が必要になります

状態の呼称以外は Windows Phone 8.1 もほぼ同じなので、Windows 10 for Phone でもそれほど変更せず移行できそうです

上記を踏まえて Windows Phone 8.0 の動作確認用のアプリを作ります

とりあえずブラウザを開く機能を追加

/// <summary>
/// Web ブラウザを開くサービス
/// </summary>
public class OpenBrowserService : IOpenBrowserService
{
    /// <summary>
    /// Web ブラウザを開く
    /// </summary>
    /// <param name="uri">Uri</param>
    public void OpenUri(string uri)
    {
        SimpleLogger.WriteLine(string.Format("open to {0}", uri));

        Launcher.LaunchUriAsync(new Uri(uri));
    }
}

さくっとブラウザ呼び出しを追加するのみ!

次に App.xaml.cs を変更

public partial class App : Application
{
    /// <summary>
    /// Provides easy access to the root frame of the Phone Application.
    /// </summary>
    /// <returns>The root frame of the Phone Application.</returns>
    public static PhoneApplicationFrame RootFrame { get; private set; }

    /// <summary>
    /// Constructor for the Application object.
    /// </summary>
    public App()
    {
        // Global handler for uncaught exceptions.
        UnhandledException += Application_UnhandledException;

        // ブラウザで開く機能を登録
        SupportLifecycle.App.Container.RegisterType<IOpenBrowserService, OpenBrowserService>(new ContainerControlledLifetimeManager());

        // Standard XAML initialization
        InitializeComponent();


        ~ 中略 ~
    }

    /// <summary>
    /// Application_Launching イベントハンドラ
    /// アプリ起動時に呼び出されます
    /// </summary>
    /// <param name="sender">イベント発行者</param>
    /// <param name="e">イベント引数</param>
    private void Application_Launching(object sender, LaunchingEventArgs e)
    {
        SimpleLogger.WriteLine("Launching.");
    }

    /// <summary>
    /// Application_Activated イベントハンドラ
    /// アプリ起動時に呼び出されます
    /// </summary>
    /// <param name="sender">イベント発行者</param>
    /// <param name="e">イベント引数</param>
    private void Application_Activated(object sender, ActivatedEventArgs e)
    {
        SimpleLogger.WriteLine("Activated.");
    }

    /// <summary>
    /// Application_Deactivated イベントハンドラ
    /// Dormant 遷移時に呼び出されます
    /// </summary>
    /// <param name="sender">イベント発行者</param>
    /// <param name="e">イベント引数</param>
    private void Application_Deactivated(object sender, DeactivatedEventArgs e)
    {
        SimpleLogger.WriteLine("Deactivated.");
    }

    /// <summary>
    /// Application_Closing イベントハンドラ
    /// アプリ終了時に呼び出されます
    /// </summary>
    /// <param name="sender">イベント発行者</param>
    /// <param name="e">イベント引数</param>
    private void Application_Closing(object sender, ClosingEventArgs e)
    {
        SimpleLogger.WriteLine("Closing.");
    }

    ~ 中略 ~
}

DI コンテナに先ほどのサービスクラス実体を登録するのと、各種状態遷移のイベントハンドラをログ出力つきで追加しました

あとは実行・・・下記のような操作を順にやってみます

  • アプリ起動
  • 次画面に遷移
  • ブラウザで Xamarin ホームを開く
  • アプリに戻る
  • トップ画面に戻る
  • OS ホームに戻る
  • 再度アプリに戻る
  • アプリを終了
  • 再度起動

操作の様子はこんな感じ

f:id:matatabi_ux:20150307222917g:plain

そして出力されたログは・・・

App.xaml.Application_Launching: Launching.
App.OnStart: started.
TopPage.xaml.OnAppearing: TopPage Appearing.
SecondPage.xaml.OnAppearing: SecondPage Appearing.
OpenBrowserService.OpenUri: open to http://www.xamarin.com
App.xaml.Application_Deactivated: Deactivated.
App.OnSleep: sleeped.
TopPage.xaml.OnAppearing: TopPage Appearing.
App.xaml.Application_Deactivated: Deactivated.
App.OnSleep: sleeped.
App.xaml.Application_Activated: Activated.
App.OnResume: resumed.
App.xaml.Application_Deactivated: Deactivated.
App.OnSleep: sleeped.
App.xaml.Application_Launching: Launching.
App.OnStart: started.
TopPage.xaml.OnAppearing: TopPage Appearing.

ホーム画面を出してからさらにアプリに戻ると OnResume が呼び出されましたが、明示的にアプリを終了すると再起動時は OnStart が呼び出されました

ただ、ブラウザから戻ってもメモリにデータが残っていたのか、OnResume は呼ばれませんでした

OnResume が呼ばれるかどうかは OS のリソース使用状況(おそらくメモリ)に応じて、Tombstoned に遷移するか否かに依存するとは思いますが、OnResume を通ったときだけセッションデータを復帰させればよさそうです

Application_Closing のイベントハンドラが通ってないのが気になりますが、ストアアプリの場合も終了は検知できないのでおそらくこのイベントハンドラは実質使えないのだと思います・・・