/// <summary> /// Gets called as we receive data. /// </summary> /// <param name="session">Session.</param> /// <param name="downloadTask">Download task.</param> /// <param name = "bytesWritten"></param> /// <param name="totalBytesWritten">Total bytes written.</param> /// <param name = "totalBytesExpectedToWrite"></param> public override void DidWriteData(NSUrlSession session, NSUrlSessionDownloadTask downloadTask, long bytesWritten, long totalBytesWritten, long totalBytesExpectedToWrite) { nuint localIdentifier = downloadTask.TaskIdentifier; float percentage = (float)totalBytesWritten / (float)totalBytesExpectedToWrite; Console.WriteLine("DidWriteData - Task: {0}, BytesWritten: {1}, Total: {2}, Expected: {3}, Percentage: {4}", localIdentifier, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite, percentage); var downloadInfo = AppDelegate.GetDownloadInfoByTaskId(localIdentifier); int index = AppDelegate.GetDownloadInfoIndexByTaskId(localIdentifier); if (downloadInfo != null) { downloadInfo.Progress = percentage; } else { Console.WriteLine("Unable to find download info for task ID '{0}'.", localIdentifier); } // We are not on the UI thread here. var indexPath = NSIndexPath.FromRowSection(index, 0); this.InvokeOnMainThread(() => { this.controller.TableView.ReloadRows(new NSIndexPath[] { indexPath }, UITableViewRowAnimation.None); }); }
/// <summary> /// Very misleading method name. Gets called if a download is done. Does not necessarily indicate an error /// unless the NSError parameter is not null. /// </summary> public override void DidCompleteWithError(NSUrlSession session, NSUrlSessionTask task, NSError error) { var downloadInfo = AppDelegate.GetDownloadInfoByTaskId(task.TaskIdentifier); // Remember the first completed download. We want to play that when all downloads have finished. // If playback is started right here in this method, DidFinishEventsForBackgroundSession() won't be called - no idea why. if (this.firstCompletedDownload == null) { this.firstCompletedDownload = downloadInfo; } if (error == null) { return; } Console.WriteLine("DidCompleteWithError - Task: {0}, Error: {1}", task.TaskIdentifier, error); if (downloadInfo != null) { downloadInfo.Reset(true); } task.Cancel(); this.InvokeOnMainThread(() => this.controller.TableView.ReloadData()); }
/// <summary> /// Gets called if the download has been completed. /// </summary> public override void DidFinishDownloading(NSUrlSession session, NSUrlSessionDownloadTask downloadTask, NSUrl location) { // The download location will be a file location. var sourceFile = location.Path; // Construct a destination file name. var destFile = downloadTask.OriginalRequest.Url.AbsoluteString.Substring(downloadTask.OriginalRequest.Url.AbsoluteString.LastIndexOf("/") + 1); Console.WriteLine("DidFinishDownloading - Task: {0}, Source file: {1}", downloadTask.TaskIdentifier, sourceFile); // Copy over to documents folder. Note that we must use NSFileManager here! File.Copy() will not be able to access the source location. NSFileManager fileManager = NSFileManager.DefaultManager; // Create the filename var documentsFolderPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); NSUrl destinationURL = NSUrl.FromFilename(Path.Combine(documentsFolderPath, destFile)); // Update download info object. var downloadInfo = AppDelegate.GetDownloadInfoByTaskId(downloadTask.TaskIdentifier); // Remove any existing file in our destination NSError error; fileManager.Remove(destinationURL, out error); bool success = fileManager.Copy(sourceFile, destinationURL.Path, out error); if (success) { // Update download info object. this.UpdateDownloadInfo(downloadInfo, DownloadInfo.STATUS.Completed, destinationURL); } else { // Clean up. downloadInfo.Reset(true); this.UpdateDownloadInfo(downloadInfo, DownloadInfo.STATUS.Cancelled, null); Console.WriteLine("Error during the copy: {0}", error.LocalizedDescription); } this.InvokeOnMainThread(() => { this.controller.TableView.ReloadData(); }); // Serialize all info to disk. AppDelegate.SerializeAvailableDownloads(); }