Xamarin.Forms.iOS 13中的后台任务处理(刷新)问题

时间:2020-10-23 17:09:02

标签: ios xamarin xamarin.forms xamarin.ios

最近几天,我一直在努力让iOS应用在后台运行时能ping通我的API。

我已经遍历了Apple的iOS框架上的所有文档以及Xamarin文档。看起来很简单,设置了计划的刷新任务,然后提交URL请求。

后台任务标识符位于info.plist中,并且后台处理和获取功能已打开。

我已经在当前正在使用的应用上尝试过此操作,并且还为此目的专门设置了一个测试应用。 我已经尝试了是否使用NSOperation和NSOperatonQueue。 在极少数情况下,我会在MS App Center的事件日志中看到计划任务,因此要触发该任务,但是只有一次且不再重复。

首先,我尝试了后台获取功能,但似乎没有被触发,因此我切换到iOS 13后台任务。

我正在MacOS 11中(也在Windows 10的VS2019中)在Visual Studio 2019中进行开发,但是在调试XCode中的应用程序过程时遇到了麻烦。

我正在提供指向我在GitHub中的测试项目存储库的链接。 https://github.com/sigthor/background.ping

相关代码位于AppDelegate.cs和PingOperation.cs

public readonly NSUrlSessionConfiguration urlSessionConfiguration = null;
private readonly NSUrlSession urlSession = null;
private readonly string RefreshTaskId = "com.bgtest.ios.background-test.refresh";

public AppDelegate()
{
   urlSessionConfiguration = 
       NSUrlSessionConfiguration.CreateBackgroundSessionConfiguration("com.bgtest.ios.background-test");
   urlSession = NSUrlSession.FromConfiguration(urlSessionConfiguration);
}

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
    global::Xamarin.Forms.Forms.SetFlags("CollectionView_Experimental");
    global::Xamarin.Forms.Forms.Init();
    LoadApplication(new App());

    BGTaskScheduler.Shared.Register(RefreshTaskId, null, task => HandleAppRefresh(task as BGAppRefreshTask));

    return base.FinishedLaunching(app, options);
}

public override void DidEnterBackground(UIApplication uiApplication)
{
    ScheduleAppRefresh();

    base.DidEnterBackground(uiApplication);
}

private void HandleAppRefresh(BGAppRefreshTask task)
{
    Debug.WriteLine("HandleAppRefresh started");
    ScheduleAppRefresh();

    var queue = new NSOperationQueue();
    queue.MaxConcurrentOperationCount = 1;

    var pingOperation = new PingOperation(0, 0, "205558e0-f226-446d-a769-aaceb3b2a880", urlSession);

    task.ExpirationHandler = () =>
    {
        queue.CancelAllOperations();
    };

    pingOperation.CompletionBlock = () =>
    {
        Debug.WriteLine("Ping operation completed");
        task.SetTaskCompleted(!pingOperation.IsCancelled);
    };

    queue.AddOperation(pingOperation);
}

private void ScheduleAppRefresh()
{
    Debug.WriteLine("Scheduling ping task");
    var request = new BGAppRefreshTaskRequest(RefreshTaskId)
    {
        EarliestBeginDate = (NSDate)DateTime.Now.AdMinutes(5)
    };

    BGTaskScheduler.Shared.Submit(request, out NSError error);

    if (error != null)
    {
        throw new Exception(error.LocalizedDescription);
    }
}
public class PingOperation : NSOperation
{
    ...
    public override void Start()
    {
        Debug.WriteLine("Ping operation started");
        WillChangeValue("IsExecuting");
        isExecuting = true;
        DidChangeValue("IsExecuting");

        if (IsCancelled)
        {
            Finish(false);
            return;
        }

        Debug.WriteLine("UrlSession request created");
        var request = CreatePingRequest();
        dataTask = session.CreateDataTask(request);

        Finish(true);
    }
    public void Finish(bool result)
    {
        if (IsExecuting)
        {
            return;
        }

        WillChangeValue("IsExecuting");
        WillChangeValue("IsFinished");

        isExecuting = false;
        this.result = result;
        dataTask.Dispose();
        dataTask = null;

        DidChangeValue("IsExecuting");
        DidChangeValue("IsFinished");
    }

    private NSUrlRequest CreatePingRequest()
    {
        var url = GeneratePingUrl(userId);
        var req = new NSMutableUrlRequest(NSUrl.FromString(url));
        req.HttpMethod = "POST";
        req.CachePolicy = NSUrlRequestCachePolicy.ReloadIgnoringCacheData;
        var content = JsonConvert.SerializeObject(new
        {
            Long = longitude,
            Lat = latitude
        });
        req.Body = content;

        return req;
    }
    ...
}

Ps。我还尝试仅在调度程序之外手动触发任务。 NSUrlRequset已创建,但请求似乎从未发出过。

我们非常感谢您的帮助。

0 个答案:

没有答案