How to convert Xamarin iOS project to Xamarin Forms - SimpleBackgroundTransfer

WillAutioItrax 186 Reputation points
2021-11-04T00:21:05.537+00:00

It has been recommended to me that I should try to implement this Xamarin iOS app:

https://github.com/xamarin/ios-samples/tree/main/SimpleBackgroundTransfer

in Xamarin Forms for doing the iOS part of a background download. I have done lots of Xamarin Forms - just not much in Xamarin iOS and request some guidance as how to proceed.

@Wenyan Zhang (Shanghai Wicresoft Co,.Ltd.) What would your recommendation be?

Thanks!
Will

Xamarin
Xamarin
A Microsoft open-source app platform for building Android and iOS apps with .NET and C#.
4,818 questions
{count} votes

1 answer

Sort by: Most helpful
  1. Wenyan Zhang (Shanghai Wicresoft Co,.Ltd.) 15,741 Reputation points Microsoft Employee
    2021-11-10T02:10:41.687+00:00

    Hello,

    Welcome to our Microsoft Q&A platform!

    I have converted this Xamarin iOS demo to Xamarin Forms, it relys on DependencyService, and I use Action to callback the image path, you could refer to the following code:

    XML(MainPage)

    <?xml version="1.0" encoding="utf-8" ?>  
    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"  
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"  
                 xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"  
                 ios:Page.UseSafeArea="true"  
                 x:Class="TestSimpleBackgroundTransferDemo.MainPage">  
        <StackLayout BackgroundColor="Red">  
            <Button Text="start download " Clicked="Button_Clicked"></Button>  
            <Image x:Name="MyImage"></Image>  
        </StackLayout>  
    </ContentPage>  
    

    CodeBehind(MainPage.cs)

    private void Button_Clicked(object sender, EventArgs e)  
            {  
                DependencyService.Get<IDownloadService>().StartDownload();  
            }  
            protected override void OnAppearing()  
            {  
                base.OnAppearing();  
                DependencyService.Get<IDownloadService>().SetSession((p) =>  
                {  
                    Device.BeginInvokeOnMainThread(() =>  
                    {  
                        MyImage.Source = p;  
                    });  
     });  
            }  
    

    Interface

    public interface IDownloadService  
        {  
            void StartDownload();  
            void SetSession(Action<string>pacthCallBack);  
        }  
    

    Add method to Appdelegate

            public Action BackgroundSessionCompletionHandler { get; set; }  
            public override void HandleEventsForBackgroundUrl(UIApplication application, string sessionIdentifier, Action completionHandler)  
            {  
                Console.WriteLine("HandleEventsForBackgroundUrl");  
                BackgroundSessionCompletionHandler = completionHandler;  
            }  
    

    DownloadService.cs in iOS Project

    using Foundation;  
    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Text;  
    using TestSimpleBackgroundTransferDemo.iOS;  
    using UIKit;  
    using Xamarin.Forms;  
      
      
    [assembly: Dependency(typeof(DownloadService))]  
    
    namespace TestSimpleBackgroundTransferDemo.iOS  
    {  
        public class DownloadService : IDownloadService  
        {  
            const string Identifier = "TestSimpleBackgroundTransferDemo.iOS";  
            const string DownloadUrlString = "https://upload.wikimedia.org/wikipedia/commons/9/97/The_Earth_seen_from_Apollo_17.jpg";  
            public NSUrlSessionDownloadTask downloadTask;  
            public NSUrlSession session;  
              
        public void StartDownload()  
        {  
            if (downloadTask != null)  
                return;  
            using (var url = NSUrl.FromString(DownloadUrlString))  
            using (var request = NSUrlRequest.FromUrl(url))  
            {  
                downloadTask = session.CreateDownloadTask(request);  
                downloadTask.Resume();  
            }  
        }  
        public void SetSession(Action<string>pathCallBack)  
        {  
            if (session == null)  
                PathCallBackAction = pathCallBack;  
                session = InitBackgroundSession();  
        }  
    
        public Action<string> PathCallBackAction;  
    
    
        public NSUrlSession InitBackgroundSession()  
        {  
            Console.WriteLine("InitBackgroundSession");  
            //var config = NSUrlSessionConfiguration.CreateBackgroundSessionConfiguration(Identifier);  
            //config.SharedContainerIdentifier = "XXXXX";  
    
            using (var configuration = NSUrlSessionConfiguration.CreateBackgroundSessionConfiguration(Identifier))  
            {  
                return NSUrlSession.FromConfiguration(configuration, new UrlSessionDelegate(this), null);  
            }  
        }  
    
    
        public class UrlSessionDelegate : NSObject, INSUrlSessionDownloadDelegate  
        {  
            public DownloadService downloadService;  
    
            public UrlSessionDelegate(DownloadService downloadService)  
            {  
                this.downloadService = downloadService;  
            }  
    
            [Export("URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:")]  
            public void DidWriteData(NSUrlSession session, NSUrlSessionDownloadTask downloadTask, long bytesWritten, long totalBytesWritten, long totalBytesExpectedToWrite)  
            {  
                Console.WriteLine("Set Progress");  
                if (downloadTask == downloadService.downloadTask)  
                {  
                    float progress = totalBytesWritten / (float)totalBytesExpectedToWrite;  
                    Console.WriteLine(string.Format("DownloadTask: {0}  progress: {1}", downloadTask, progress));  
                }  
            }  
    
    
            public 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 = documentsDictionry.Append("image1.png", false);  
                NSError removeCopy;  
                NSError errorCopy;  
    
                fileManager.Remove(destinationURL, out removeCopy);  
                bool success = fileManager.Copy(location, destinationURL, out errorCopy);  
    
    
                if (success)  
                {  
                    // callback the path  
                    //UIImage image = UIImage.FromFile(destinationURL.Path);  
                    downloadService?.PathCallBackAction?.Invoke(destinationURL.Path);  
                }  
                else  
                {  
                    Console.WriteLine("Error during the copy: {0}", errorCopy.LocalizedDescription);  
                }  
            }  
    
    
            [Export("URLSession:task:didCompleteWithError:")]  
            public void DidCompleteWithError(NSUrlSession session, NSUrlSessionTask task, NSError error)  
            {  
                Console.WriteLine("DidComplete");  
                if (error == null)  
                    Console.WriteLine("Task: {0} completed successfully", task);  
                else  
                    Console.WriteLine("Task: {0} completed with error: {1}", task, error.LocalizedDescription);  
    
                float progress = task.BytesReceived / (float)task.BytesExpectedToReceive;  
                downloadService.downloadTask = null;  
            }  
    
            [Export("URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes:")]  
            public void DidResume(NSUrlSession session, NSUrlSessionDownloadTask downloadTask, long resumeFileOffset, long expectedTotalBytes)  
            {  
                Console.WriteLine("DidResume");  
            }  
    
            [Export("URLSessionDidFinishEventsForBackgroundURLSession:")]  
            public void DidFinishEventsForBackgroundSession(NSUrlSession session)  
            {  
                using (AppDelegate appDelegate = UIApplication.SharedApplication.Delegate as AppDelegate)  
                {  
                    var handler = appDelegate.BackgroundSessionCompletionHandler;  
                    if (handler != null)  
                    {  
                        appDelegate.BackgroundSessionCompletionHandler = null;  
                        handler();  
                    }  
                }  
    
    
                Console.WriteLine("All tasks are finished");  
            }  
        }  
    }  
    }  
    

    Best Regards,
    Wenyan Zhang


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    No comments