如果手机已锁定,请在后台继续iOS中的任务

时间:2016-09-20 10:27:15

标签: c# ios iphone xamarin.forms

我正在以Xamarin形式(PCL - ios和android)执行此应用程序,我从服务器获取大数据(使用httpclient),我正在显示进度对话框,向用户显示正在获取数据。

让我们说,用户不小心锁定了iphone,这些是我在我的应用中发现的事情。

  1. 转到后台。但之后该应用程序似乎终止了。
  2. 解锁手机,应用程序显示解锁前显示的相同屏幕,但没有发生后台进程(可能是因为应用程序已终止(但是,为什么应用已终止?)
  3. 我的疑问: 1.为什么应用程序不继续数据获取?似乎在android中工作正常。 2.一旦iPhone被锁定,实际上会发生什么? 3.如何在iOS后台继续执行任务,说我在pcl执行http调用?

1 个答案:

答案 0 :(得分:3)

这就是iOS和Android的不同之处。虽然Xamarin使两者都更容易开发,但最终它们仍然只是Android和iOS应用程序,必须遵守该操作系统的规则。

在iOS中,从版本9开始,您无法在后台运行代码,因为您可以在Android中使用代码。对于iOS,你将不得不为此做一些魔术。 您可以遵循this blogpost来描述您想要做的事情。

他说;

  

背景是我们用于允许某些过程的术语   我们的应用程序中的代码继续执行而另一个应用程序在   前景。在iOS上,在iOS 9之前,只允许使用一个应用程序   一次执行代码。这被称为前台应用程序。如果   您不要更改代码以告诉iOS您计划运行代码   在后台,您的应用程序将被强制终止和删除   如果您的代码尝试在后台执行,则从内存中获取。   Android实际上允许代码在后台活动中运行,但是   后台活动是首先要终止的事情之一   操作系统需要更多内存。相反,在Android上,我们应该   使用另一个称为服务的特殊类。

所以还要再看一下你在Android中如何做到这一点,因为如果你做错了,你的传输也会被中断。

为了在iOS中实现,他使用了这个:

  

在iOS项目的AppDelegate.cs文件中,我们将使用Messaging   中心订阅“开始”和“停止”消息。为了方便,   我已将iOS apis包装在另一个名为的类中   iOSLongRunningTaskExample。 iOS的重要方法是   UIApplication.SharedApplication.BeginBackgroundTask ("LongRunningTask", OnExpiration)和   UIApplication.SharedApplication.EndBackgroundTask (taskId)。这些是   告诉iOS我们将在后台运行代码的方法   并且不终止我们的应用程序。

然后他按照这样的方式实现它们:

[Register ("AppDelegate")]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate  
{
    public override bool FinishedLaunching (UIApplication app, NSDictionary options)
    {
        MessagingCenter.Subscribe<StartLongRunningTaskMessage> (this, "StartLongRunningTaskMessage", async message => {
            longRunningTaskExample = new iOSLongRunningTaskExample ();
            await longRunningTaskExample.Start ();
        });

        MessagingCenter.Subscribe<StopLongRunningTaskMessage> (this, "StopLongRunningTaskMessage", message => {
            longRunningTaskExample.Stop ();
        });
    }
}

public class iOSLongRunningTaskExample  
{
    nint _taskId;
    CancellationTokenSource _cts;

    public async Task Start ()
    {
        _cts = new CancellationTokenSource ();

        _taskId = UIApplication.SharedApplication.BeginBackgroundTask ("LongRunningTask", OnExpiration);

        try {
            //INVOKE THE SHARED CODE
            var counter = new TaskCounter();
            await counter.RunCounter(_cts.Token);

        } catch (OperationCanceledException) {
        } finally {
            if (_cts.IsCancellationRequested) {
                var message = new CancelledMessage();
                Device.BeginInvokeOnMainThread (
                    () => MessagingCenter.Send(message, "CancelledMessage")
                );
            }
        }

        UIApplication.SharedApplication.EndBackgroundTask (_taskId);
    }

    public void Stop ()
    {
        _cts.Cancel ();
    }

    void OnExpiration ()
    {
        _cts.Cancel ();
    }
}

有关详细信息,请查看帖子。