Search code examples
c#windows-runtimewindows-phone-8.1background-task

Windows phone app 8.1 - Background Task is not launched


Timer Background task in my windows phone 8.1 app was fired only when app was running in debug mode from visual studio. But if I launch even debug binary without debugging it doesn't work, not after 15 minutes, not after several hours. I tested it on windows phone 8.1 emulator and on nokia lumia 920 - the same result: in debug session it works (it is fired by system and I can fire it manually from Debug Location toolbar), but when app launched manually nothing happens.

I have windows store app also and time background task works in it quite well.

To use background tasks I did the following:

  1. In my wp8.1 project's manifest I've added:

    <Extension Category="windows.backgroundTasks" EntryPoint="data.TimerHandler">
            <BackgroundTasks>
                    <Task Type="timer" />
            </BackgroundTasks>
    </Extension>
    
  2. Created in namespace 'data' class MyTimerManager with such methods (among others):

    public static BackgroundTaskRegistration RegisterBackgroundTask(string taskEntryPoint, string taskName, IBackgroundTrigger trigger, IBackgroundCondition condition)
    {
        foreach (var cur in BackgroundTaskRegistration.AllTasks)
        {
            if (cur.Value.Name == taskName)
                return (BackgroundTaskRegistration)(cur.Value);
        }
        var builder = new BackgroundTaskBuilder();
        builder.Name = taskName;
        builder.TaskEntryPoint = taskEntryPoint;
        builder.SetTrigger(trigger);
        if (condition != null)
            builder.AddCondition(condition);
        BackgroundTaskRegistration task = null;
        try
        {
            task = builder.Register();
        }
        catch (Exception e)
        {
            LogError(e);
        }
        return task;
    }
    
    public static bool UnRegisterBackgroundTask(string taskName)
    {
        foreach (var cur in BackgroundTaskRegistration.AllTasks)
        {
            if (cur.Value.Name == taskName)
            {
                ((BackgroundTaskRegistration)cur.Value).Unregister(false);
                return true;
            }
        }
        return false;
    }
    
    public static void setupAlarm()
    {
        TimeTrigger timerTrigger = new TimeTrigger(30, false);
        string entryPoint = "data.TimerHandler";
        string taskName = "TimerHandler task";
        UnRegisterBackgroundTask(taskName);//just in case
        BackgroundTaskRegistration task = RegisterBackgroundTask(entryPoint, taskName, timerTrigger, null);
        Log("RegisterBackgroundTask: " + (task!=null ?task.Name:null));
    }
    
  3. Created winrt component project, set its Default Namespace to 'data' (the same namespace that I used for class MyTimerManager in main app) added class TimerHandler:

    namespace data
    {
    public sealed class  TimerHandler : IBackgroundTask
    {
        BackgroundTaskDeferral deferral = null;
    
        public async void Run(IBackgroundTaskInstance taskInstance)
        {
            deferral = taskInstance.GetDeferral();
            await BackgroundExecutionManager.RequestAccessAsync();
            await backgroundTimerCallAsync();
            deferral.Complete();
        }
        public static async Task backgroundTimerCallAsync()
        {
            NotificationSender ns = new NotificationSender(false, null, null);
            ns.sendNotification("Timer task msg");//my code which sends notification
        }
    }
    }
    
  4. Added reference to winrt component project into my wp8.1 project.

It is very important to use the same namespace: in my Windows Store 8.1 app background task wasn't fired until I realized that. And no a single word about it in MSFT docs!

Every app launch I call setupAlarm() and in log I see task's name (everything was fine). But nothing happens then. If I launch this task manually (from Lifecircle Events control) I see my notification. The strange thing that I rememeber month ago when this code was written I saw notifications. I've checked everything with msft docs, but everything seems fine. What else should I do to make tasks be fired?


Solution

  • In some examples I've found out that you should call RequestAccessAsync BEFORE registering your tasks! That did the trick.

    Before means that you must wait until RequestAccessAsync finished, I had to call it in sync code, so I did it like that:

        BackgroundExecutionManager.RequestAccessAsync.AsTask().ContinueWith(
            (t) => registerMyTasks()).ConfigureAwait(false);