Event handling and app suspend

This post examines an application with a cross-platform library and how to deal with event handling mechanism when application is suspended. The application has a shared cross-platform C++ backend library which communicates with a specific hardware.

There is a requirement to respond quickly to user's start key press.

When the application is suspended it is unknown whether the existing instance will be used again or not.


The high level architecture

The image shows on a high level the different components of the application. The SWIG layer creates the needed interfaces between the phone app and the shared library.


Application launched / running

When the app is launched for the first time the connections are put into place between the different components.

Application class

public partial class App : Application
{
...
  public static ApplicationFrame RootFrame
  {
    get;
    private set;
  }
  ... 
     private void Application_Launching(object sender, 
    LaunchingEventArgs e)
  {
    PlatformAdapter.Singleton.AppInitializing(LaunchMode.New);
    RootFrame.Initialize(true);
  }
  ...
}

PhoneApplicationFrame class

public partial class ApplicationFrame : PhoneApplicationFrame
{
...
  private Listener _listener;
  private bool _initialized;
...
     public void Initialize(bool listenerStartup)
  {
    if (_listener == null)
    {
      _listener = Listener.Singleton;
      _listener.InitializedEventHandler += 
        ListenerInitializationCompleted;
      if (listenerStartup)
      {
        _listener.Startup();
      }
    }

    if (!_initialized)
    {
      Listener.Singleton.Root.Action.HandleAction1 += 
        Action_HandleAction1;
      Listener.Singleton.Root.Action.HandleAction2 += 
        Action_HandleAction2;
      ...
      Listener.Singleton.Root.Action.HandleActionN += 
        Action_HandleActionN;

      _initialized = true;
    }
  }
...
}

Application closed / suspended

When user closes the application nothing special needs to happen. All the resources are freed and connections closed.

When user presses the start key and suspends the application the situation is different. The App doesn't know whether user comes back or not.

Application class

public partial class App : Application
{
...
  public static ApplicationFrame RootFrame
  {
    get;
    private set;
  }
... 

  private void Application_Deactivated(object sender, 
    DeactivatedEventArgs e)
  {
    RootFrame.Deinitialize();
    PlatformAdapter.Singleton.AppSuspending(ExitMode.Suspend);
  }

  private void Application_Closing(object sender, ClosingEventArgs e)
  {
    RootFrame.Deinitialize();
    PlatformAdapter.Singleton.AppSuspending(ExitMode.Close);
  }
...  
}

PhoneApplicationFrame class

public partial class ApplicationFrame :PhoneApplicationFrame
{
...
  private Listener _listener;
  private bool _initialized;
...
  public void Deinitialize()
  {
    if (_listener != null)
    {
      _listener.InitializedEventHandler -= 
        ListenerInitializationCompleted;
      _listener = null;
    }

    if (_initialized)
    {            
      Listener.Singleton.Root.Action.HandleAction1 -= 
        Action_HandleAction1;
      Listener.Singleton.Root.Action.HandleAction2 -= 
        Action_HandleAction2;
      ...
      Listener.Singleton.Root.Action.HandleActionN -= 
        Action_HandleActionN;

      _initialized = false;
    }
  }
  ...
}

Application resumed

When the App finally resumes it needs to check whether the previous instance still exists.

Application class

public partial class App : Application
{
...
  public static ApplicationFrame RootFrame
  {
    get;
    private set;
  }
  ... 

  private void Application_Activated(object sender, ActivatedEventArgs e)
  {
    if (!e.IsApplicationInstancePreserved)
    {
      PlatformAdapter.Singleton.AppInitializing(LaunchMode.Reset);
      RootFrame.Initialize(true);
    }
    else
    {
      PlatformAdapter.Singleton.AppInitializing(LauncMode.Restore);
      RootFrame.Initialize(false);
    }
  }
  ...
}

PhoneApplicationFrame class

public partial class ApplicationFrame : PhoneApplicationFrame
{
...
  private Listener _listener;
  private bool _initialized;
...
  public void Initialize(bool listenerStartup)
  {
    if (_listener == null)
    {
      _listener = Listener.Singleton;
      _listener.InitializedEventHandler += 
        ListenerInitializationCompleted;
      if (listenerStartup)
      {
        _listener.Startup();
      }
    }

    if (!_initialized)
    {
      Listener.Singleton.Root.Action.HandleAction1 += 
        Action_HandleAction1;
      Listener.Singleton.Root.Action.HandleAction2 += 
        Action_HandleAction2;
      ...
      Listener.Singleton.Root.Action.HandleActionN += 
        Action_HandleActionN;

      _initialized = true;
    }
  }
...
}

Birota project

Project repository