Фоновая передача и NSURLSession в Xamarin.iOS
Фоновая передача инициируется путем настройки фона NSURLSession
и выполнения задач отправки или скачивания. Если задачи выполняются в фоновом режиме, приостановке или завершении работы приложения, iOS уведомит приложение, вызвав обработчик завершения в AppDelegate приложения. На следующей схеме показано это в действии:
Настройка фонового сеанса
Чтобы сделать фоновый сеанс, создайте новый NSUrlSession
и настройте его с помощью NSUrlSessionConfiguration
объекта.
Объект конфигурации определяет, что может выполнять сеанс, и типы задач, которые он может выполнять.
Сеансы, настроенные с помощью CreateBackgroundSessionConfiguration
метода, будут выполняться в отдельном процессе и выполнять дискреционную передачу (Wi-Fi), чтобы сохранить данные и время работы батареи.
В следующем примере кода демонстрируется правильная настройка фонового сеанса передачи с помощью CreateBackgroundSessionConfiguration
метода и уникального идентификатора строки:
public partial class SimpleBackgroundTransferViewController : UIViewController
{
NSUrlSession session = null;
NSUrlSessionConfiguration configuration =
NSUrlSessionConfiguration.CreateBackgroundSessionConfiguration ("com.SimpleBackgroundTransfer.BackgroundSession");
session = NSUrlSession.FromConfiguration
(configuration, new MySessionDelegate(), new NSOperationQueue());
}
Помимо объекта конфигурации, сеанс также требует делегата сеанса и очереди. Очередь определяет порядок выполнения задач. Делегат сеанса чаперонирует процесс передачи и обрабатывает проверку подлинности, кэширование и другие проблемы, связанные с сеансом.
Работа с задачами и делегатами
Теперь, когда мы настроили фоновый сеанс, давайте начнем задачи по обработке передачи. Эти задачи можно отслеживать с помощью экземпляра NSUrlSessionDelegate
, называемого делегатом сеанса. Делегат сеанса отвечает за пробуждение завершенного или приостановленного приложения в фоновом режиме для обработки проверки подлинности, ошибок или завершения передачи.
Предоставляет NSUrlSessionDelegate
следующие основные методы для проверка состояния передачи:
- DidFinishEventsForBackgroundSession — этот метод вызывается, когда все задачи завершены, и передача завершена.
- DidReceiveChallenge — вызывается для запроса учетных данных при необходимости авторизации.
- DidBecomeInvalidWithError — вызывается, если он
NSURLSession
становится недействительным.
Фоновые сеансы требуют более специализированных делегатов в зависимости от типов выполняемых задач. Фоновые сеансы ограничены двумя типами задач:
- Отправка задач — задачи типа
NSUrlSessionUploadTask
используютINSUrlSessionTaskDelegate
интерфейс, реализующийINSUrlSessionDelegate
. Это позволяет отслеживать ход отправки, обрабатывать перенаправление HTTP и многое другое. - Скачать задачи — задачи типа
NSUrlSessionDownloadTask
используютINSUrlSessionDownloadDelegate
интерфейс, реализующийINSUrlSessionDelegate
иINSUrlSessionTaskDelegate
. Это предоставляет все методы для задач отправки, а также методы для скачивания для отслеживания хода скачивания и определения времени возобновления или завершения задачи скачивания.
Следующий код определяет задачу, которую можно использовать для скачивания изображения из URL-адреса. Задача запускается путем вызова CreateDownloadTask
фонового сеанса и передачи URL-запроса:
const string DownloadURLString = "http://xamarin.com/images/xamarin.png"; // or other hosted file
public NSUrlSessionDownloadTask downloadTask;
NSUrl downloadURL = NSUrl.FromString (DownloadURLString);
NSUrlRequest request = NSUrlRequest.FromUrl (downloadURL);
downloadTask = session.CreateDownloadTask (request);
Затем создайте делегат загрузки сеанса, чтобы отслеживать все задачи загрузки в этом сеансе. Класс делегата должен наследоваться от NSObject
и реализовать необходимый интерфейс:
public class MySessionDelegate : NSObject, INSUrlSessionDownloadDelegate
{
public void DidWriteData (NSUrlSession session, NSUrlSessionDownloadTask downloadTask, long bytesWritten, long totalBytesWritten, long totalBytesExpectedToWrite)
{
Console.WriteLine (string.Format ("DownloadTask: {0} progress: {1}", downloadTask, progress));
InvokeOnMainThread( () => {
// update UI with progress bar, if desired
});
}
...
}
Чтобы узнать ход выполнения задачи скачивания, переопределите DidWriteData
метод для отслеживания хода выполнения и даже обновления пользовательского интерфейса. Обновления пользовательского интерфейса будут отображаться немедленно, если приложение находится на переднем плане или ожидает пользователя при следующем открытии приложения.
API делегата сеанса предоставляет широкий набор средств для взаимодействия с задачами. Полный список методов делегата сеанса см. в NSUrlSessionDelegate
документации по API.
Внимание
Фоновые сеансы запускаются в фоновом потоке, поэтому все вызовы для обновления пользовательского интерфейса должны быть явно запущены в потоке пользовательского интерфейса путем вызова InvokeOnMainThread
, чтобы избежать прекращения приложения iOS.
Обработка завершения передачи
Последний шаг — сообщить приложению о завершении всех задач, связанных с сеансом, и обработать новое содержимое.
AppDelegate
Подпишитесь на HandleEventsForBackgroundUrl
событие. Когда приложение входит в фон и выполняется сеанс передачи, вызывается этот метод, а система передает обработчик завершения:
public System.Action backgroundSessionCompletionHandler;
public void HandleEventsForBackgroundUrl (UIApplication application, string sessionIdentifier, System.Action completionHandler)
{
this.backgroundSessionCompletionHandler = completionHandler;
}
Используйте обработчик завершения, чтобы сообщить iOS о завершении обработки приложения.
Помните, что сеанс может вызывать несколько задач для обработки передачи. После завершения последней задачи приостановленное или завершенное приложение повторно запускается в фоновом режиме. Затем приложение повторно подключается к NSURLSession
уникальному идентификатору сеанса и вызывает DidFinishEventsForBackgroundSession
делегат сеанса. Этот метод — это возможность приложения обрабатывать новое содержимое, включая обновление пользовательского интерфейса, чтобы отразить результаты передачи:
public void DidFinishEventsForBackgroundSession (NSUrlSession session) {
// Handle new information, update UI, etc.
}
Завершив обработку нового содержимого, вызовите обработчик завершения, чтобы сообщить системе, что безопасно сделать моментальный снимок приложения и вернуться в спящий режим:
public void DidFinishEventsForBackgroundSession (NSUrlSession session) {
var appDelegate = UIApplication.SharedApplication.Delegate as AppDelegate;
// Handle new information, update UI, etc.
// call completion handler when you're done
if (appDelegate.backgroundSessionCompletionHandler != null) {
NSAction handler = appDelegate.backgroundSessionCompletionHandler;
appDelegate.backgroundSessionCompletionHandler = null;
handler.Invoke ();
}
}
В этом пошаговом руководстве описаны основные шаги по реализации фоновой службы передачи данных в iOS 7 и более поздней версии.