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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Xamarin表单中的UIDocumentPickerViewController作为依赖服务相关的知识,希望对你有一定的参考价值。

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

  1. 打开ios文件应用。 (UIDocumentPickerViewController)
  2. 选择任何类型的文档。
  3. 将该文档复制到我的应用程序文档目录。 (适用于应用访问)
  4. 通过将其路径存储到我的SQLite DB中,将该文档显示到我的应用程序中。

我在这里尝试做的是在条目点击上从我的应用程序调用Files应用程序并且click事件似乎运行良好我的依赖服务调用完美但现在当我尝试使用UIDocumentPickerViewController时我无法获取View控制器上下文在我的依赖服务中调用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中处理它?
答案

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


使用以下界面:

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);
}
}
另一答案

对于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; 
    } 
}
另一答案

因为我正在寻找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;
  

以上是关于使用Xamarin表单中的UIDocumentPickerViewController作为依赖服务的主要内容,如果未能解决你的问题,请参考以下文章

IOS 中的 Xamarin 表单选择器不会换行

xamarin 表单中的 Web API 请求错误

通过 Xamarin 表单中的 URL 获取 HTML

使用 mvvm 在 xamarin 表单中的视图之间传递数据

如何将 Forms.Image 中的最终照片保存到 xamarin 表单中的本地

Xamarin 表单中的可扩展 ListView