Skip to content

Instantly share code, notes, and snippets.

@Clancey
Last active December 29, 2015 03:49
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Clancey/7610128 to your computer and use it in GitHub Desktop.
Save Clancey/7610128 to your computer and use it in GitHub Desktop.
Background Downloader. Has the same API as WebClient but uses the underlying NSUrlRequest to download in the background.
public class BackgroundDownload
{
public BackgroundDownload ()
{
}
NSUrlSessionDownloadTask downloadTask;
static NSUrlSession session;
public async Task DownloadFileAsync(Uri url, string destination)
{
if (downloadTask != null)
return;
if(session == null)
session = InitBackgroundSession ();
Tcs = new TaskCompletionSource<bool> ();
Destination = destination;
using (var request = new NSUrlRequest(new NSUrl(url.AbsoluteUri))) {
downloadTask = session.CreateDownloadTask (request);
downloadTask.Resume ();
}
await Tcs.Task;
}
public event Action<float> ProgressChanged;
float progress;
public float Progress {
get {
return progress;
}
private set {
if (Math.Abs (progress - value) < float.Epsilon)
return;
progress = value;
if (ProgressChanged != null)
ProgressChanged (progress);
}
}
NSUrlSession InitBackgroundSession ()
{
Console.WriteLine ("InitBackgroundSession");
using (var configuration = NSUrlSessionConfiguration.BackgroundSessionConfiguration ("async.background.downloader")) {
return NSUrlSession.FromConfiguration (configuration, new UrlSessionDelegate (this), null);
}
}
protected string Destination;
protected TaskCompletionSource<bool> Tcs;
public class UrlSessionDelegate : NSUrlSessionDownloadDelegate
{
public BackgroundDownload controller;
public UrlSessionDelegate (BackgroundDownload controller)
{
this.controller = controller;
}
public override void DidWriteData (NSUrlSession session, NSUrlSessionDownloadTask downloadTask, long bytesWritten, long totalBytesWritten, long totalBytesExpectedToWrite)
{
Console.WriteLine ("Set Progress");
if (downloadTask == controller.downloadTask) {
float progress = totalBytesWritten / (float)totalBytesExpectedToWrite;
Console.WriteLine (string.Format ("DownloadTask: {0} progress: {1}", downloadTask, progress));
InvokeOnMainThread(() => controller.Progress = progress);
}
}
public override void DidFinishDownloading (NSUrlSession session, NSUrlSessionDownloadTask downloadTask, NSUrl location)
{
Console.WriteLine ("Finished");
Console.WriteLine ("File downloaded in : {0}", location);
NSFileManager fileManager = NSFileManager.DefaultManager;
var URLs = fileManager.GetUrls (NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomain.User);
NSUrl documentsDictionry = URLs [0];
NSUrl originalURL = downloadTask.OriginalRequest.Url;
NSUrl destinationURL = NSUrl.FromFilename(controller.Destination);
NSError removeCopy;
NSError errorCopy;
fileManager.Remove (destinationURL, out removeCopy);
bool success = fileManager.Copy (location, destinationURL, out errorCopy);
if (success) {
controller.Tcs.TrySetResult (true);
} else {
controller.Tcs.TrySetException(new Exception(string.Format("Error during the copy: {0}", errorCopy.LocalizedDescription)));
}
}
public override void DidCompleteWithError (NSUrlSession session, NSUrlSessionTask task, NSError error)
{
float progress = task.BytesReceived / (float)task.BytesExpectedToReceive;
InvokeOnMainThread (() => controller.Progress = progress);
controller.downloadTask = null;
Console.WriteLine ("DidComplete");
if (error == null)
controller.Tcs.TrySetResult (true);
else {
controller.Tcs.TrySetException(new Exception(string.Format("Error during the copy: {0}", error.LocalizedDescription)));
}
}
public override void DidResume (NSUrlSession session, NSUrlSessionDownloadTask downloadTask, long resumeFileOffset, long expectedTotalBytes)
{
Console.WriteLine ("DidResume");
}
public override void DidFinishEventsForBackgroundSession (NSUrlSession session)
{
AppDelegate appDelegate = UIApplication.SharedApplication.Delegate as AppDelegate;
var handler = appDelegate.BackgroundSessionCompletionHandler;
if (handler != null) {
appDelegate.BackgroundSessionCompletionHandler = null;
handler ();
}
BackgroundDownload.session = null;
Console.WriteLine ("All tasks are finished");
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment