Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using UIDocumentPickerViewController in Xamarin forms as a dependency service

I'm using Xamarin forms and writing a dependency service for the following objectives :

  1. Open iOS files app. (UIDocumentPickerViewController )

  2. Select any kind of a document.

  3. Copy that document into my application Documents directory. (For app access)

  4. Show that document into my application by storing its path into my SQLite DB.

What I am trying to do here is call the Files app from my application on an Entry click and the click event seems to be working well my dependency service calls perfectly but now when I try to use the UIDocumentPickerViewController I am unable to get View controller context in my dependency service to call the PresentViewController method. Now I know about the xamarin forms context but I don't know if it will work here and I don't even know if it would be a smart idea to use it as it has already been marked as obsolete and since I am not from the iOS background, I don't know what would be the right solution for it.

My code is as follows :

public class DocumentPickerRenderer : IDocumentPicker
{
    public object PickFile()
    {
        var docPicker = new UIDocumentPickerViewController(new string[] { UTType.Data, UTType.Content }, UIDocumentPickerMode.Import);
        docPicker.WasCancelled += (sender, wasCancelledArgs) =>
        {
        };
        docPicker.DidPickDocumentAtUrls += (object sender, UIDocumentPickedAtUrlsEventArgs e) =>
        {
            Console.WriteLine("url = {0}", e.Urls[0].AbsoluteString);
            //bool success = await MoveFileToApp(didPickDocArgs.Url);
            var success = true;
            string filename = e.Urls[0].LastPathComponent;
            string msg = success ? string.Format("Successfully imported file '{0}'", filename) : string.Format("Failed to import file '{0}'", filename);
            var alertController = UIAlertController.Create("import", msg, UIAlertControllerStyle.Alert);
            var okButton = UIAlertAction.Create("OK", UIAlertActionStyle.Default, (obj) =>
            {
                alertController.DismissViewController(true, null);
            });
            alertController.AddAction(okButton);
            PresentViewController(alertController, true, null);
        };
        PresentViewController(docPicker, true, null);
    }
}

My questions:

  1. Is my methodology correct for picking files?

  2. what will be the object that I will be getting as a callback from a file selection and how will I get the callback?

  3. Is there any other way or something available for xamarin forms, some guide or something that allows me to pick documents from my native file systems and gives a brief on how to handle it in both ios and android?

like image 311
FreakyAli Avatar asked Apr 22 '18 13:04

FreakyAli


People also ask

What is Xamarin essentials?

Xamarin. Essentials provides a single cross-platform API that works with any iOS, Android, or UWP application that can be accessed from shared code no matter how the user interface is created. See the platform & feature support guide for more information on supported operating systems.

What is Assembly in Xamarin forms?

This is called Registration.The platform implementations must be registered with the DependencyService , so that Xamarin. Forms can locate them at runtime. This is typically performed with the DependencyAttribute , which indicates that the specified type provides an implementation of the interface .


1 Answers

Hello Guys, You can use following code for picking any type of documents to mention in code using iOS Devices-


use follwing interface:

public interface IMedia
{
 Task<string> OpenDocument();
 }


 public Task<string> OpenDocument()
    {

        var task = new TaskCompletionSource<string>();
        try
        {
            OpenDoc(GetController(), (obj) =>
            {
                if (obj == null)
                {
                    task.SetResult(null);
                    return;
                }
                var aa = obj.AbsoluteUrl;
                task.SetResult(aa.Path);
            });
        }
        catch (Exception ex)
        {
            task.SetException(ex);
        }
        return task.Task;
    }

    static Action<NSUrl> _callbackDoc;

    public static void OpenDoc(UIViewController parent, Action<NSUrl> callback)
    {
        _callbackDoc = callback;
        var version = UIDevice.CurrentDevice.SystemVersion;
        int verNum = 0;
        Int32.TryParse(version.Substring(0, 2), out verNum);

        var allowedUTIs = new string[]
        {
        UTType.UTF8PlainText,
        UTType.PlainText,
        UTType.RTF,
        UTType.PNG,
        UTType.Text,
        UTType.PDF,
        UTType.Image,
        UTType.Spreadsheet,
        "com.microsoft.word.doc",
        "org.openxmlformats.wordprocessingml.document",
        "com.microsoft.powerpoint.ppt",
        "org.openxmlformats.spreadsheetml.sheet",
        "org.openxmlformats.presentationml.presentation",
        "com.microsoft.excel.xls",

        };

        // Display the picker
        var pickerMenu = new UIDocumentMenuViewController(allowedUTIs, UIDocumentPickerMode.Import);
        pickerMenu.DidPickDocumentPicker += (sender, args) =>
        {
            if (verNum < 11)
            {
                args.DocumentPicker.DidPickDocument += (sndr, pArgs) =>
                {
                    UIApplication.SharedApplication.OpenUrl(pArgs.Url);
                    pArgs.Url.StopAccessingSecurityScopedResource();

                    var cb = _callbackDoc;
                    _callbackDoc = null;
                    pickerMenu.DismissModalViewController(true);
                    cb(pArgs.Url.AbsoluteUrl);
                };
            }
            else
            {
                args.DocumentPicker.DidPickDocumentAtUrls += (sndr, pArgs) =>
                {
                    UIApplication.SharedApplication.OpenUrl(pArgs.Urls[0]);
                    pArgs.Urls[0].StopAccessingSecurityScopedResource();

                    var cb = _callbackDoc;
                    _callbackDoc = null;
                    pickerMenu.DismissModalViewController(true);
                    cb(pArgs.Urls[0].AbsoluteUrl);
                };
            }
            // Display the document picker
            parent.PresentViewController(args.DocumentPicker, true, null);
        };

        pickerMenu.ModalPresentationStyle = UIModalPresentationStyle.Popover;
        parent.PresentViewController(pickerMenu, true, null);
        UIPopoverPresentationController presentationPopover = pickerMenu.PopoverPresentationController;
        if (presentationPopover != null)
        {
            presentationPopover.SourceView = parent.View;
            presentationPopover.PermittedArrowDirections = UIPopoverArrowDirection.Down;
        }
    }

Now you need to call using following code:

var filePath = await DependencyService.Get<IMedia>().OpenDocument();

For pick document in Android, you can use following code

  public class IntentHelper
 {

  public const int DocPicker = 101;
  static Action<string> _callback;
  public static async void ActivityResult(int requestCode, Result resultCode, Intent data)
{  if (requestCode == RequestCodes.DocPicker)
    {
        if (data.Data == null)
        {
            _callback(null);
        }
        else
        {
            var destFilePath = FilePath.GetPath(CurrentActivity, data.Data);
            _callback(destFilePath);
        }
    }
}

 public static Activity CurrentActivity
{
    get
    {
        return (Xamarin.Forms.Forms.Context as MainActivity);
    }
}

 public static void OpenDocPicker(Action<string> callback)
{
    _callback = callback;
    var intent = new Intent(Intent.ActionOpenDocument);
    intent.AddCategory(Intent.CategoryOpenable);
    intent.SetType("*/*");
    CurrentActivity.StartActivityForResult(intent, RequestCodes.DocPicker);
}
}
like image 163
Shashikant Yadav Avatar answered Oct 12 '22 14:10

Shashikant Yadav