I'm trying to create a Windows UAP (C#) to constantly log location data in a background task, for now all I'm trying to do is start the background task off of a geofence trigger.
I've followed a lot of guides for how to do this, I've added the entry point in the Package.appxmanifest to "BackgroundTask.LocationBackgroundTask" and selected the location property.
I'm then registering the task using the following:
var result = await BackgroundExecutionManager.RequestAccessAsync();
var builder = new BackgroundTaskBuilder();
builder.Name = BackgroundTaskName;
builder.TaskEntryPoint = BackgroundTaskEntryPoint;
builder.SetTrigger(new LocationTrigger(LocationTriggerType.Geofence));
var geofenceTask = builder.Register();
I use the following code to verify if the background task is registered and it returns true to indicate that the task is registered:
public bool IsTaskRegistered()
{
var Registered = false;
var entry = BackgroundTaskRegistration.AllTasks.FirstOrDefault(keyval => keyval.Value.Name == BackgroundTaskName);
if (entry.Value != null)
Registered = true;
return Registered;
}
The problem I'm having is that the Run method in the background task is just not getting triggered.
To verify the background task itself is all good, I swapped out the trigger type for builder.SetTrigger(new SystemTrigger(SystemTriggerType.PowerStateChange, true)); (and updated the Package.appxmanifest to have the system event property). This then worked fine as the background task was triggered as I'd expect when I unplugged the power source from my laptop.
The other thing to note is that when debugging I don't see the background task under the Lifecycle Events whereas I do when testing with the SystemTrigger.
The problem does therefore seem to be specific to the geofence triggering. I'm starting to pull my hair out a bit over this so would be grateful for any suggestions.
Related
I'm trying to re-purpose a code-snippet for a UWP app using Windows.Media.SpeechRecognition's SpeechRecognizer class.
The problem is that it doesn't seem to utilize the timeout that I set for EndSilenceTimeout -- yet both BabbleTimeout and InitialSilenceTimeout appear to be working just fine. Basically, a 1-2 second pause will always end the session, and I'm trying to figure out how to fix or work around this.
I've tried with both RecognizeAsync and RecognizeWithUIAsync but neither made a difference.
private async void StartRecognizing()
{
var speechRecognizer = new SpeechRecognizer();
speechRecognizer.Timeouts.EndSilenceTimeout = TimeSpan.FromSeconds(10);
speechRecognizer.Timeouts.BabbleTimeout = TimeSpan.FromSeconds(10);
speechRecognizer.Timeouts.InitialSilenceTimeout = TimeSpan.FromSeconds(10);
await speechRecognizer.CompileConstraintsAsync();
SpeechRecognitionResult speechRecognitionResult = await speechRecognizer.RecognizeAsync();
var messageDialog = new Windows.UI.Popups.MessageDialog(speechRecognitionResult.Text, "Text spoken");
await messageDialog.ShowAsync();
}
To test this, just make a new UWP app in Visual Studio and grant yourself permission to access the microphone in the package app manifest; additionally you'll need to make sure your OS itself allows for this in the Speech, inking, & typing settings on Windows 10 v1803.
I have the same problem as this guy over here: UWP Timetrigger not working
but I can't comment the question because my reputation is not high enough, so I'm creating a new question.
As I said, I have the same problem. I registered the background task, but nothing happens. My background task is located in a seperate project (Runtime Component). So that's not the problem.
This is the method I made to register the task:
public static BackgroundTaskRegistration Register(string name, string taskEntryPoint, IBackgroundTrigger trigger, IBackgroundCondition condition)
{
var foundTask = BackgroundTaskRegistration.AllTasks.FirstOrDefault(x => x.Value.Name == name);
if (foundTask.Value != null)
return (BackgroundTaskRegistration)foundTask.Value;
var builder = new BackgroundTaskBuilder();
builder.Name = name;
builder.TaskEntryPoint = taskEntryPoint;
builder.SetTrigger(trigger);
if (condition != null)
builder.AddCondition(condition);
return builder.Register();
}
and this is how I call it:
BackgroundTaskRegister.Register(nameof(NotificationTask), $"Epguides.Background.{_backgroundTaskName}", new TimeTrigger(30, true), null);
When I debug my application and use Lifecycle Events in Visual studio to test my background task, everything works fine. So the problem is not the task.
When I inspect the BackgroundTaskRegistration result I see that the property trigger is null. on the MSDN page of BackgroundTaskRegistration.Trigger it says the following
This is not intended for use in your code. For all unsupported trigger types, the value returned by this property is null.
So from what I understand is that TimeTrigger is an unsupported trigger type, because Trigger is null.
This is what is declared in the manifest file
Is there someone that can explain why it is not working. I'm using version 10.0.10586
You can confirm that the your task is registered or not by using powershell.
Open powershell with administrative rights, and run 'Get-AppBackgroundTask'. All of registered tasks are listed. If you can't find your task from the list, there are some problems at registration.
Have you add the background task project as a reference to your main app?
Have you call the BackgroundExecutionManager.RequestAccessAsync()? You should call it before registering, from UI thread.
I have a sample app of background task with timetrigger on the store. It's hidden from storefront and search, but you can download it from following link:
https://www.microsoft.com/store/p/ddlgbgtasktrial/9nblggh4s785
This app regist a simple background task with 15min interval timetrigger. This task just output the debugmessage to the logfile. The app shows a log. If it works well, you can see the debug output with about 15min intervals.
I've confirmed that the app works with Win10 desktop 10586.494 and mobile 14393.0.
I had exactly same problem with TimeTrigger (Application trigger was working without any issues) and I followed every step from MSDN regarding BackgroundTask in UWP. But ONLY below "magic line" helped me to solve - BIG THANKS to #Canol Gökel for his reply in comments (I think it deserve separate answer):
BackgroundExecutionManager.RemoveAccess(); // This is the magic line!
var backgroundAccessStatus = await BackgroundExecutionManager.RequestAccessAsync();
Time trigger is part of UWP background task sample (Scenario 4) which was working for me. But this line is not used there at all. Instead it is used in NFC sample during check if application was updated:
private static async Task<bool> DoBackgroundRequestAccess()
{
String appVersion = String.Format("{0}.{1}.{2}.{3}",
Package.Current.Id.Version.Build,
Package.Current.Id.Version.Major,
Package.Current.Id.Version.Minor,
Package.Current.Id.Version.Revision);
if ((string)Windows.Storage.ApplicationData.Current.LocalSettings.Values["AppVersion"] != appVersion)
{
// Our app has been updated
Windows.Storage.ApplicationData.Current.LocalSettings.Values["AppVersion"] = appVersion;
// Call RemoveAccess
BackgroundExecutionManager.RemoveAccess();
}
BackgroundAccessStatus status = await BackgroundExecutionManager.RequestAccessAsync();
return status == BackgroundAccessStatus.AlwaysAllowed
|| status == BackgroundAccessStatus.AllowedSubjectToSystemPolicy;
}
I have a background agent for my windows phone 8.1(C#) which listens to push notifications.
I also have a foreground App and it handles push notification if it is running.
The problem is that the background agent invokes a custom method await SyncPushChanges.initUpdate(true); several times causing duplicate values in my sqlite database.
Here is code for foreground delegate:
static async void channel_PushNotificationReceived(PushNotificationChannel sender, PushNotificationReceivedEventArgs args)
{
//Init update from the server
await SyncPushChanges.initUpdate();
//Prevent background agentt from being invoked
args.Cancel = true;
}
Code In background Agent
public async void Run(IBackgroundTaskInstance taskInstance)
{
var deferal = taskInstance.GetDeferral();//Save on CPU seconds since we are doing async
//Get the token and invoke get new data
await SyncPushChanges.initUpdate(true);
deferal.Complete();
}
Anyone who might know why am having my method invokes many times?Your help will be highly appreciated
I found a solution myself.
The issue was that I was not unregistering my background agent and this caused it to work incorrectly when the app was updated(In this case when I run the application again from VS2013).
The following code did the magic
BackgroundExecutionManager.RemoveAccess();
//Unregister the Background Agent
var entry = BackgroundTaskRegistration.AllTasks.FirstOrDefault(keyval => keyval.Value.Name == "myAgent");
if (entry.Value != null)
{
entry.Value.Unregister(true);
}
I have a UAP application, and when I debug on a Windows 10 Phone, IBackgroundTask is triggered automatically. When I debug on Local Machine (Windows 10 x86), it isn't called at all. How can I trigger it?
A simple way is to set a system trigger. In your manifest, you need a "Background Tasks" declaration, with a "System event" property.
In your C# code, you have to register your task and you can bind the task to a particular event system like "NetworkStateChange" :
foreach (var task in BackgroundTaskRegistration.AllTasks)
{
task.Value.Unregister(true);
}
var result = await BackgroundExecutionManager.RequestAccessAsync();
if (result == BackgroundAccessStatus.Denied)
{
return;
}
BackgroundTaskBuilder builder = new BackgroundTaskBuilder();
builder.Name = "<task name>";
builder.TaskEntryPoint = "<task entry point>";
builder.SetTrigger(new SystemTrigger(SystemTriggerType.NetworkStateChange, false));
var registration = builder.Register();
With this code, you can launch the task with a manual manipulation on the network (switch wifi or unplung your cable).
When debugging, you can trigger a background task directly from Visual Studio 2015. There's a drop-down menu called Lifecycle Events that lets you invoke Suspend, Resume and any registered background tasks. Set a breakpoint in your task beforehand. (In my case the class implementing the background task is called NotifyChanges.)
I'm trying to register a background task and I'm getting some strange behaviour. I appears that the task itself is registering and firing at the right time; however, when it does fire it's closing my program down (with no error).
I suspect that the reason is linked to the fact that the program is not asking me is I want to allow a background task to run when I launch. I have created a declaration for the background task as a system event, and am registering like this from the App.Xaml.cs:
var builder = new BackgroundTaskBuilder();
builder.Name = "NewTask";
builder.TaskEntryPoint = "ConnectionMonitor.CheckInternet";
builder.SetTrigger(new SystemTrigger(SystemTriggerType.InternetAvailable, false));
BackgroundTaskRegistration task = builder.Register();
So, I believe my question is: why would it not ask me for permission to run a background task (which I assume will give me the answer to my main problem of why it is crashing)?
I'm not sure whether it matters, but this is a Windows Universal app (the app.xaml.cs above is in the Shared project.
The task looks like this:
BackgroundTaskDeferral _deferral = taskInstance.GetDeferral();
bool newConnected = IsConnected();
if (connected != newConnected)
{
connected = newConnected;
var notifier = ToastNotificationManager.CreateToastNotifier();
var template = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText02);
var element = template.GetElementsByTagName("text")[0];
element.AppendChild(template.CreateTextNode(connected ? "Connection available" : "Connection lost"));
var toast = new ToastNotification(template);
notifier.Show(toast);
}
_deferral.Complete();
You asked: why would it not ask me for permission to run a background task?
The answer is, unless your background task requires lock screen access, it does not require the user's permission to be registered. There is no user prompt, by design. One of the intents of this design is that it allows you to register a task from another task.
In Windows, you do not need to call BackgroundExecutionManager.RequestAccessAsync() except for lock screen access. Calling it will give you more quota but will require the user to approve the task.
In Windows Phone, calling RequestAccessAsync() is required no matter what, but never prompts the user with a UI. For this reason the logic in your Universal App can be shared but will likely have a #if to handle the registration differently, if relevant.