My UWP app hosts an AppService that runs in the same process as the app does. To do this I have followed this documentation.
The goal of this AppService is to communicate two running Apps.
This is the code I use to allow incoming AppService connections:
private AppServiceConnection AppServiceConnection;
private BackgroundTaskDeferral AppServiceDeferral;
protected override void OnBackgroundActivated(BackgroundActivatedEventArgs args)
{
base.OnBackgroundActivated(args);
IBackgroundTaskInstance taskInstance = args.TaskInstance;
AppServiceTriggerDetails appService = taskInstance.TriggerDetails as AppServiceTriggerDetails;
AppServiceDeferral = taskInstance.GetDeferral();
taskInstance.Canceled += OnAppServicesCanceled;
AppServiceConnection = appService.AppServiceConnection;
AppServiceConnection.RequestReceived += OnAppServiceRequestReceived;
AppServiceConnection.ServiceClosed += AppServiceConnection_ServiceClosed;
}
private async void OnAppServiceRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
{
AppServiceDeferral messageDeferral = args.GetDeferral();
ValueSet response = (await IPC.Controller.ProcessIncomeRequests(args.Request.Message.ToDictionary())).ToValueSet();
await args.Request.SendResponseAsync(response);
messageDeferral.Complete();
}
private void OnAppServicesCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
{
AppServiceDeferral.Complete();
}
private void AppServiceConnection_ServiceClosed(AppServiceConnection sender, AppServiceClosedEventArgs args)
{
AppServiceDeferral.Complete();
}
As mentioned in the following Stackoverflow question, a communication from a 'client' app can be established to the 'host' app even if the 'host' app isn't running. For my purposes, I would like to deny incoming AppServices connections unless the 'host' app is currently running.
Is there a way I can do this? What property could I check within the OnBackgroundActivated
method to decide whether to accept the taskInstance
or not?
UPDATE:
Is it right to say that the method OnLaunched(LaunchActivatedEventArgs e)
is only fired after a "conventional" start up of the app (user launching the app manually)?
If that's the case, then one solution could be to keep track of a boolean variable AppIsRunning
:
private static bool AppIsRunning = false;
protected override async void OnLaunched(LaunchActivatedEventArgs e)
{
...
AppIsRunning = true;
...
}
private AppServiceConnection AppServiceConnection;
private BackgroundTaskDeferral AppServiceDeferral;
protected override void OnBackgroundActivated(BackgroundActivatedEventArgs args)
{
base.OnBackgroundActivated(args);
IBackgroundTaskInstance taskInstance = args.TaskInstance;
AppServiceTriggerDetails appService = taskInstance.TriggerDetails as AppServiceTriggerDetails;
AppServiceDeferral = taskInstance.GetDeferral();
taskInstance.Canceled += OnAppServicesCanceled;
AppServiceConnection = appService.AppServiceConnection;
AppServiceConnection.RequestReceived += OnAppServiceRequestReceived;
AppServiceConnection.ServiceClosed += AppServiceConnection_ServiceClosed;
}
private async void OnAppServiceRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
{
if (AppIsRunning)
{
AppServiceDeferral messageDeferral = args.GetDeferral();
ValueSet response = (await IPC.Controller.ProcessIncomeRequests(args.Request.Message.ToDictionary())).ToValueSet();
await args.Request.SendResponseAsync(response);
messageDeferral.Complete();
}
}
private void OnAppServicesCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
{
AppServiceDeferral.Complete();
}
private void AppServiceConnection_ServiceClosed(AppServiceConnection sender, AppServiceClosedEventArgs args)
{
AppServiceDeferral.Complete();
}
This way the incoming AppService requests wouldn't be handled when the app is not currently running.
As I have mentioned in my Update to the question, tracking a boolean variable that changes it's default value when the
OnLaunched(LaunchActivatedEventArgs e)
method is called could be used as a workaround for the required purposes. The value of this variable should be checked before accepting an AppService Request, to decide whether it is accepted or not.