在Xamarin表单中使用UIDocumentPickerViewController作为依赖服务

时间:2018-04-22 13:55:40

标签: xamarin xamarin.forms xamarin.ios

我正在使用Xamarin表单并为以下目标编写依赖服务:

  1. 打开iOS文件应用。 (UIDocumentPickerViewController)

  2. 选择任何类型的文档。

  3. 将该文档复制到我的应用程序文档目录中。 (适用于应用访问)

  4. 将该文档存储到我的SQLite数据库中,将该文档显示到我的应用程序中。

  5. 我在这里尝试做的是在条目点击时从我的应用程序调用文件应用程序并且点击事件似乎运行良好我的依赖服务调用完美但现在当我尝试使用UIDocumentPickerViewController我无法得到在我的依赖服务中查看控制器上下文以调用PresentViewController方法。现在我知道了xamarin表单的上下文,但我不知道它是否会在这里工作,我甚至不知道使用它是否是一个明智的想法,因为它已经被标记为已经过时,因为我不是来自iOS背景,我不知道什么是正确的解决方案。

    我的代码如下:

    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);
        }
    }
    

    我的问题:

    1. 我的方法是否适合挑选文件?

    2. 我将从文件选择中获取回调的对象是什么?我将如何获得回调?

    3. 是否有任何其他方式或内容可用于xamarin表单,某些指南或允许我从我的本机文件系统中选择文档的内容,并简要介绍如何在ios和android中处理它?<​​/ p>

3 个答案:

答案 0 :(得分:2)

Hello Guys,您可以使用以下代码挑选使用iOS设备在代码中提及的任何类型的文档 -

使用follwing接口:

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;
        }
    }

现在您需要使用以下代码进行呼叫:

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

对于Android中的选择文档,您可以使用以下代码

  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);
}
}

答案 1 :(得分:2)

对于Android中的选择文档,您可以使用以下代码:

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);
    }
}

使用以下代码访问帮助程序类:public class Media:

IMedia {
    public Task<string> OpenDocument() { 
        var task = new TaskCompletionSource<string>(); 
        try {            
            IntentHelper.OpenDocPicker((path) => { task.SetResult(path); }); 
        } catch (Exception ex) {  
            task.SetResult(null); 
        } 
        return task.Task; 
    } 
}

答案 2 :(得分:0)

因为我一直在寻找UIDocumentPickerViewController而不是UIDocumentMenuViewController,所以其他答案不是我想要的:

这就是我最终要这样做的方式:

致电文档选择器:

   var docPicker = new UIDocumentPickerViewController(new string[]
            { UTType.Data, UTType.Content }, UIDocumentPickerMode.Import);
            docPicker.WasCancelled += DocPicker_WasCancelled;
            docPicker.DidPickDocumentAtUrls += DocPicker_DidPickDocumentAtUrls;
            docPicker.DidPickDocument += DocPicker_DidPickDocument;
            var _currentViewController = GetCurrentUIController();
            if (_currentViewController != null)
                _currentViewController.PresentViewController(docPicker, true, null);

GetCurrentUIController是用于获取当前UI控制器的函数,

 public UIViewController GetCurrentUIController()
    {
        UIViewController viewController;
        var window = UIApplication.SharedApplication.KeyWindow;
        if (window == null)
        {
            return null;
        }

        if (window.RootViewController.PresentedViewController == null)
        {
            window = UIApplication.SharedApplication.Windows
                     .First(i => i.RootViewController != null &&
                                 i.RootViewController.GetType().FullName
                                 .Contains(typeof(Xamarin.Forms.Platform.iOS.Platform).FullName));
        }

        viewController = window.RootViewController;

        while (viewController.PresentedViewController != null)
        {
            viewController = viewController.PresentedViewController;
        }

        return viewController;
    }

对于iOS 11以下的版本,我添加了DidPickDocument事件:

 private void DocPicker_DidPickDocument(object sender, UIDocumentPickedEventArgs e)
    {
        try
        {
            NSUrl filePath = e.Url.AbsoluteUrl;
            //This is the url for your document and you can use it as you please.
        }
        catch (Exception ex)
        {

        }
      }

对于iOS 11以上的版本,您可以使用DidPickDocumentUrls,因为该位置支持多重选择:

  private void DocPicker_DidPickDocumentAtUrls(object sender, UIDocumentPickedAtUrlsEventArgs e)
    {
        try
        {

         List<NSUrl> filePath = e.Urls.ToList().Select(y => y.AbsoluteUrl).ToList();
        //returns the list of images selected
        }
        catch (Exception ex)
        {
            AppLogger.LogException(ex);
        }
    }