【问题标题】:File picker in xamarin forms applicationxamarin 表单应用程序中的文件选择器
【发布时间】:2017-04-27 13:03:32
【问题描述】:

我使用渲染器从系统中选择一个文件并在应用程序中显示它。我用过

Intent intent = new Intent(Intent.ActionOpenDocument);
            intent.SetType("file/*");
            intent.AddCategory(Intent.CategoryOpenable);
            String[] mimeTypes = { "text/csv", "text/comma-separated-values" ,"application/pdf","image/*"};
            intent.SetType("*/*");
            intent.PutExtra(Intent.ExtraMimeTypes, mimeTypes);
            ((FormsAppCompatActivity)Forms.Context).StartActivityForResult(intent, 7007);

我在 MainActivity 的 OnActivityResult 中获得了数据。现在我有了 Android.Net.Uri,我想找到绝对文件路径。这里我用了

public String getRealPathFromURI(Android.Net.Uri contentUri)
        {
            String res = null;
            String[] proj = {Android.Provider.MediaStore.Images.Media.InterfaceConsts.Data};
            ICursor cursor = ContentResolver.Query(contentUri, proj, null, null, null);
            if (cursor.MoveToFirst())
            {                
                int column_index = cursor.GetColumnIndexOrThrow(Android.Provider.MediaStore.Images.Media.InterfaceConsts.Data);
                res = cursor.GetString(column_index);
            }
            cursor.Close();
            return res;
        }

我在 Marshmallow 设备中进行测试,但每次都返回 null 值。有什么指导吗?

【问题讨论】:

    标签: android android-intent xamarin xamarin.forms uri


    【解决方案1】:

    You can take a look to this plugin...

    有一个 IOUtil.cs 类

    public class IOUtil
    {
    
        public static string getPath (Context context, Android.Net.Uri uri)
        {
            bool isKitKat = Build.VERSION.SdkInt >= BuildVersionCodes.Kitkat;
    
            // DocumentProvider
            if (isKitKat && DocumentsContract.IsDocumentUri (context, uri)) {
                // ExternalStorageProvider
                if (isExternalStorageDocument (uri)) {
                    var docId = DocumentsContract.GetDocumentId (uri);
                    string [] split = docId.Split (':');
                    var type = split [0];
    
                    if ("primary".Equals (type, StringComparison.OrdinalIgnoreCase)) {
                        return Android.OS.Environment.ExternalStorageDirectory + "/" + split [1];
                    }
    
                    // TODO handle non-primary volumes
                }
                // DownloadsProvider
                else if (isDownloadsDocument (uri)) {
    
                    string id = DocumentsContract.GetDocumentId (uri);
                    Android.Net.Uri contentUri = ContentUris.WithAppendedId (
                            Android.Net.Uri.Parse ("content://downloads/public_downloads"), long.Parse (id));
    
                    return getDataColumn (context, contentUri, null, null);
                }
                // MediaProvider
                else if (isMediaDocument (uri)) {
                    var docId = DocumentsContract.GetDocumentId (uri);
                    string [] split = docId.Split (':');
                    var type = split [0];
    
                    Android.Net.Uri contentUri = null;
                    if ("image".Equals (type)) {
                        contentUri = MediaStore.Images.Media.ExternalContentUri;
                    } else if ("video".Equals (type)) {
                        contentUri = MediaStore.Video.Media.ExternalContentUri;
                    } else if ("audio".Equals (type)) {
                        contentUri = MediaStore.Audio.Media.ExternalContentUri;
                    }
    
                    var selection = "_id=?";
                    var selectionArgs = new string [] {
                        split[1]
                    };
    
                    return getDataColumn (context, contentUri, selection, selectionArgs);
                }
            }
            // MediaStore (and general)
            else if ("content".Equals (uri.Scheme, StringComparison.OrdinalIgnoreCase)) {
                return getDataColumn (context, uri, null, null);
            }
            // File
            else if ("file".Equals (uri.Scheme, StringComparison.OrdinalIgnoreCase)) {
                return uri.Path;
            }
    
            return null;
        }
    
        public static string getDataColumn (Context context, Android.Net.Uri uri, string selection,
        string [] selectionArgs)
        {
    
            ICursor cursor = null;
            var column = "_data";
            string [] projection = {
                column
            };
    
            try {
                cursor = context.ContentResolver.Query (uri, projection, selection, selectionArgs,
                        null);
                if (cursor != null && cursor.MoveToFirst ()) {
                    int column_index = cursor.GetColumnIndexOrThrow (column);
                    return cursor.GetString (column_index);
                }
            } finally {
                if (cursor != null)
                    cursor.Close ();
            }
            return null;
        }
    
        /**
         * @param uri The Uri to check.
         * @return Whether the Uri authority is ExternalStorageProvider.
         */
        public static bool isExternalStorageDocument (Android.Net.Uri uri)
        {
            return "com.android.externalstorage.documents".Equals (uri.Authority);
        }
    
        /**
         * @param uri The Uri to check.
         * @return Whether the Uri authority is DownloadsProvider.
         */
        public static bool isDownloadsDocument (Android.Net.Uri uri)
        {
            return "com.android.providers.downloads.documents".Equals (uri.Authority);
        }
    
        /**
         * @param uri The Uri to check.
         * @return Whether the Uri authority is MediaProvider.
         */
        public static bool isMediaDocument (Android.Net.Uri uri)
        {
            return "com.android.providers.media.documents".Equals (uri.Authority);
        }
    
        public static byte [] readFile (string file)
        {
            try {
                return readFile (new File (file));
            } catch (Exception ex) {
                System.Diagnostics.Debug.Write (ex);
                return new byte [0];
            }
        }
    
        public static byte [] readFile (File file)
        {
            // Open file
            var f = new RandomAccessFile (file, "r");
    
            try {
                // Get and check length
                long longlength = f.Length ();
                var length = (int)longlength;
    
                if (length != longlength)
                    throw new IOException ("Filesize exceeds allowed size");
                // Read file and return data
                byte [] data = new byte [length];
                f.ReadFully (data);
                return data;
            } catch (Exception ex) {
                System.Diagnostics.Debug.Write (ex);
                return new byte [0];
            } finally {
                f.Close ();
            }
        }
    
        public static string GetMimeType (string url)
        {
            string type = null;
            var extension = MimeTypeMap.GetFileExtensionFromUrl (url);
    
            if (extension != null) {
                type = MimeTypeMap.Singleton.GetMimeTypeFromExtension (extension);
            }
    
            return type;
        }
    }
    

    它是这样工作的

        protected override void OnActivityResult (int requestCode, [GeneratedEnum] Result resultCode, Intent data)
        {
            base.OnActivityResult (requestCode, resultCode, data);
    
            if (resultCode == Result.Canceled) {
                // Notify user file picking was cancelled.
                OnFilePickCancelled ();
                Finish ();
            } else {
                System.Diagnostics.Debug.Write (data.Data);
                try {
                    var _uri = data.Data;
    
                    var filePath = IOUtil.getPath (context, _uri);
    
                    if (string.IsNullOrEmpty (filePath))
                        filePath = _uri.Path;
    
                    var file = IOUtil.readFile (filePath);
    
                    var fileName = GetFileName (context, _uri);
    
                    OnFilePicked (new FilePickerEventArgs (file, fileName, filePath));
                } catch (Exception readEx) {
                    // Notify user file picking failed.
                    OnFilePickCancelled ();
                    System.Diagnostics.Debug.Write (readEx);
                } finally {
                    Finish ();
                }
            }
        }
    

    【讨论】:

      【解决方案2】:

      除了在 Forms 项目中使用 Android 特定代码外,您还可以使用 NuGet 上提供的 FilePicker 插件之一。您可以直接在您的 Forms 项目中使用它,而不是跳入 Android 实现。

      目前维护最积极的包是这个:https://github.com/jfversluis/FilePicker-Plugin-for-Xamarin-and-Windows(注意:我是该项目的贡献者之一)。

      选择文件就像调用 var result = await PickFile() 并检查结果对象一样简单。另见 Github 项目的 README.md 中提到的示例代码。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-24
        • 2021-01-04
        • 2018-05-18
        • 2018-06-02
        • 2015-12-04
        • 2018-02-02
        相关资源
        最近更新 更多