xamarin表单应用程序中的文件选择器

时间:2017-04-27 13:03:33

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

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

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值。任何指导?

2 个答案:

答案 0 :(得分: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 ();
            }
        }
    }

答案 1 :(得分:0)

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

当前维护最活跃的软件包是以下软件包:https://github.com/jfversluis/FilePicker-Plugin-for-Xamarin-and-Windows(注意:我是该项目的贡献者之一)。

拾取文件就像调用var result = await PickFile()并检查结果对象一样容易。另请参见Github项目的README.md中提到的示例代码。