/// <summary>
        /// List contents of folder via storage access framework (used for Android/data/)
        /// </summary>
        /// <param name="uri"></param>
        /// <param name="path">Optional path</param>
        /// <returns></returns>
        public List <FolderChildren> GetFolderChildren(Uri uri, string path)
        {
            string[] projection =
            {
                DocumentsContract.Document.ColumnDocumentId,
                DocumentsContract.Document.ColumnLastModified
            };

            var newPath  = DocumentsContract.GetTreeDocumentId(uri) + $"/{path}";
            var children = DocumentsContract.BuildChildDocumentsUriUsingTree(uri, newPath);
            List <FolderChildren> folderChildren = new List <FolderChildren>();


            //string fileSelectionQuery = null;
            //Bundle? queryArgs = new Bundle();

            /*if (fileSelection != null)
             * {
             *  var sb = new StringBuilder();
             *  foreach (var _ in fileSelection)
             *  {
             *      sb.Append("?,");
             *  }
             *
             *  var inQuery = sb.ToString().TrimEnd(',');
             *  fileSelectionQuery = DocumentsContract.Document.ColumnDocumentId + $" IN ({inQuery})";
             *  queryArgs.PutString(ContentResolver.QueryArgSqlSelection, fileSelectionQuery);
             *  queryArgs.PutStringArray(ContentResolver.QueryArgSqlSelectionArgs, fileSelection);
             * }*/// https://github.com/xamarin/xamarin-android/issues/5788

            if (_folderCache.ContainsKey(children !.ToString()))
            {
                return(_folderCache[children.ToString() !]);
Esempio n. 2
0
        internal static string GetPathForDocTree(Context context, Uri uri)
        {
            var docUri = DocumentsContract.BuildDocumentUriUsingTree(uri,
                                                                     DocumentsContract.GetTreeDocumentId(uri));
            string path = GetPath(context, docUri);

            return(path);
        }
Esempio n. 3
0
        /// <summary>
        /// return null if the request does not belong to requestId
        /// </summary>
        public static Uri ResolveFromActivityResult(Activity activity, Intent data)
        {
            var androidUri = data.Data;
            var takeFlags  = data.Flags & (ActivityFlags.GrantReadUriPermission | ActivityFlags.GrantWriteUriPermission);

            activity.ContentResolver.TakePersistableUriPermission(androidUri, takeFlags);
            var storageUri = DocumentsContract.BuildDocumentUriUsingTree(androidUri, DocumentsContract.GetTreeDocumentId(androidUri));

            return(new Uri(storageUri.ToString()));
        }
        private async Task <bool> WriteFileAsync(ContentType accessType, string filePath, string storageLocationBase, byte[] bytes)
        {
            switch (accessType)
            {
            case ContentType.DirectAccess:
                await File.WriteAllBytesAsync(filePath, bytes);

                return(true);

            case ContentType.StorageFramework:
                // check file exists

                var fileExistPath = this.GetPathIfFileExists(accessType, filePath, storageLocationBase);

                Uri contentPath;
                if (!fileExistPath.Exists)
                {
                    var pathUri = Uri.Parse(storageLocationBase);
                    //var treeId = DocumentsContract.GetTreeDocumentId(pathUri) + $"/{filePath}";
                    var          treeId       = DocumentsContract.GetTreeDocumentId(pathUri) + $"/{Path.GetDirectoryName(filePath)}";
                    var          newPath      = DocumentsContract.BuildDocumentUriUsingTree(pathUri, treeId);
                    DocumentFile newFile      = DocumentFile.FromTreeUri(Android.App.Application.Context, newPath);
                    var          documentFile = newFile.CreateFile("application/octet-stream", Path.GetFileName(filePath));

                    contentPath = documentFile.Uri;
                }
                else
                {
                    var baseUriParse = Uri.Parse(storageLocationBase);
                    contentPath = DocumentsContract.BuildDocumentUriUsingTree(baseUriParse, fileExistPath.Path);
                }

                var descriptor = AppContentResolver.OpenAssetFileDescriptor(contentPath !, "w");

                if (descriptor == null)
                {
                    throw new Exception($"File descriptor null, tried to open {contentPath}.");
                }

                var writeStream = descriptor.CreateOutputStream();
                if (!writeStream.CanWrite)
                {
                    throw new Exception("Cannot write the writeStream.");
                }
                await writeStream.WriteAsync(bytes);

                return(true);

            default:
                throw new ArgumentOutOfRangeException(nameof(accessType), accessType, null);
            }
        }
        // Methods

        private (bool successful, List <AndroidFile> files) RequestFiles(Uri directoryUri)
        {
            bool successful;
            var  collection = new List <AndroidFile>();

            try
            {
                var childrenUri = DocumentsContract.BuildChildDocumentsUriUsingTree(
                    directoryUri, DocumentsContract.GetTreeDocumentId(directoryUri));

                var cursor = ContentResolver.Query(
                    childrenUri, new[]
                {
                    DocumentsContract.Document.ColumnDisplayName,
                    DocumentsContract.Document.ColumnDocumentId
                }, null, null, null);

                try
                {
                    while (cursor.MoveToNext())
                    {
                        (var name, var uri) =
                            (cursor.GetString(0), DocumentsContract.BuildDocumentUriUsingTree(directoryUri,
                                                                                              cursor.GetString(1)));
                        if (Extensions.Any(ext => name.EndsWith(ext, StringComparison.CurrentCultureIgnoreCase)))
                        {
                            collection.Add(new AndroidFile {
                                Name = name, Uri = uri
                            });
                        }
                    }

                    successful = true;
                }


                finally
                {
                    cursor.Close();
                }
            }

            catch (Java.Lang.Exception e)
            {
                Log.Debug("??", e, e.Message);
                successful = false;
            }

            return(successful, collection);
        }
        /// <summary>
        /// Updates the current directory of the uri passed as an argument and its children directories.
        /// And updates the instance's <see cref="Android.Support.V7.Widget.RecyclerView"/>  depending
        /// on the contents of the children.
        /// </summary>
        /// <param name="uri">The uri of the current directory.</param>
        void UpdateDirectoryEntries(Android.Net.Uri uri)
        {
            var contentResolver = Activity.ContentResolver;
            var docUri          = DocumentsContract.BuildDocumentUriUsingTree(uri,
                                                                              DocumentsContract.GetTreeDocumentId(uri));
            var childrenUri = DocumentsContract.BuildChildDocumentsUriUsingTree(uri,
                                                                                DocumentsContract.GetTreeDocumentId(uri));

            var docCursor = contentResolver.Query(docUri, new [] {
                DocumentsContract.Document.ColumnDisplayName,
                DocumentsContract.Document.ColumnMimeType
            }, null, null, null);

            try {
                while (docCursor.MoveToNext())
                {
                    Log.Debug(TAG, "found doc =" + docCursor.GetString(0) + ", mime=" + docCursor
                              .GetString(1));
                    mCurrentDirectoryUri           = uri;
                    mCurrentDirectoryTextView.Text = docCursor.GetString(0);
                    mCreateDirectoryButton.Enabled = true;
                }
            } finally {
                CloseQuietly(docCursor);
            }

            var childCursor = contentResolver.Query(childrenUri, new [] {
                DocumentsContract.Document.ColumnDisplayName,
                DocumentsContract.Document.ColumnMimeType
            }, null, null, null);

            try {
                List <DirectoryEntry> directoryEntries = new List <DirectoryEntry> ();
                while (childCursor.MoveToNext())
                {
                    Log.Debug(TAG, "found child=" + childCursor.GetString(0) + ", mime=" + childCursor
                              .GetString(1));
                    DirectoryEntry entry = new DirectoryEntry();
                    entry.fileName = childCursor.GetString(0);
                    entry.mimeType = childCursor.GetString(1);
                    directoryEntries.Add(entry);
                }
                mAdapter.SetDirectoryEntries(directoryEntries);
                mAdapter.NotifyDataSetChanged();
            } finally {
                CloseQuietly(childCursor);
            }
        }
Esempio n. 7
0
        /// <summary>
        /// Handles the result from activities called with StartActivityForResult()
        /// </summary>
        /// <param name="requestCode"></param>
        /// <param name="resultCode"></param>
        /// <param name="data"></param>
        protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
        {
            try
            {
                base.OnActivityResult(requestCode, resultCode, data);

                if (resultCode == Result.Ok && data != null && requestCode == OPEN_DOCUMENT_TREE_ACTIVITY)
                {
                    // keep track of the raw URI data returned from user selection
                    // just in case we need it later?
                    _userSelectedDirectory = data.Data;

                    // keep track of the parent directory
                    // this is used in building document URIs of the children
                    // based on their id
                    this._parentUri = DocumentsContract.BuildDocumentUriUsingTree(
                        _userSelectedDirectory,
                        DocumentsContract.GetTreeDocumentId(_userSelectedDirectory)
                        );

                    // WARN: This is a little hacky, and might not be that robust
                    // After creating the initial file strucutre at the location,
                    // I would recommend commenting the below check/function call
                    var dir = DocumentFile.FromTreeUri(this, _parentUri);
                    if (dir.IsDirectory && dir.Length() == 0)
                    {
                        CreateTestFileStructureAtLocation();
                    }

                    // persist permissions for this directory
                    ContentResolver.TakePersistableUriPermission(
                        _userSelectedDirectory,
                        ActivityFlags.GrantReadUriPermission | ActivityFlags.GrantWriteUriPermission
                        );

                    data.AddFlags(ActivityFlags.GrantWriteUriPermission);
                    data.AddFlags(ActivityFlags.GrantReadUriPermission);
                    data.AddFlags(ActivityFlags.GrantPrefixUriPermission);
                    data.AddFlags(ActivityFlags.GrantPersistableUriPermission);
                }
            }
            catch (Exception ex)
            {
                var timeElapsedTV = FindViewById <TextView>(Resource.Id.timeElapsedTV);
                SetTextViewOnError(timeElapsedTV, ex);
            }
        }
Esempio n. 8
0
        private bool CreateTestFileStructureAtLocation()
        {
            try
            {
                Android.Net.Uri dirUri = DocumentsContract.BuildDocumentUriUsingTree(
                    _userSelectedDirectory,
                    DocumentsContract.GetTreeDocumentId(_userSelectedDirectory)
                    );

                for (int i = 0; i < 10; ++i)
                {
                    // create directory
                    var newDir = DocumentsContract.CreateDocument(
                        this.ContentResolver,
                        dirUri,
                        DocumentsContract.Document.MimeTypeDir,
                        $"Directory {i + 1}"
                        );
                    if (newDir == null)
                    {
                        throw new Exception("Unable to create directory at location!");
                    }

                    for (int j = 0; j < 100; ++j)
                    {
                        var newFile = DocumentsContract.CreateDocument(
                            this.ContentResolver,
                            newDir,
                            "text/plain",
                            $"file{j + 1}.txt");
                        if (newFile == null)
                        {
                            throw new Exception("Unable to create file at location!");
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                // set our text view to display the error
                var timeElapsedTV = FindViewById <TextView>(Resource.Id.timeElapsedTV);
                SetTextViewOnError(timeElapsedTV, ex);
            }

            return(true);
        }
        void UpdateDirectoryEntries(Uri uri)
        {
            directoryEntries.Clear();
            var contentResolver = Activity.ContentResolver;
            Uri docUri          = DocumentsContract.BuildDocumentUriUsingTree(uri, DocumentsContract.GetTreeDocumentId(uri));
            Uri childrenUri     = DocumentsContract.BuildChildDocumentsUriUsingTree(uri, DocumentsContract.GetTreeDocumentId(uri));

            try {
                using (ICursor docCursor = contentResolver.Query(docUri, DIRECTORY_SELECTION, null, null, null)) {
                    while (docCursor != null && docCursor.MoveToNext())
                    {
                        currentDirectoryTextView.Text = docCursor.GetString(
                            docCursor.GetColumnIndex(DocumentsContract.Document.ColumnDisplayName));
                    }
                }
            } catch {
            }

            try {
                using (ICursor childCursor = contentResolver.Query(childrenUri, DIRECTORY_SELECTION, null, null, null)) {
                    while (childCursor != null && childCursor.MoveToNext())
                    {
                        var entry = new DirectoryEntry();
                        entry.FileName = childCursor.GetString(childCursor.GetColumnIndex(DocumentsContract.Document.ColumnDisplayName));
                        entry.MimeType = childCursor.GetString(childCursor.GetColumnIndex(DocumentsContract.Document.ColumnMimeType));
                        directoryEntries.Add(entry);
                    }
                }

                if (directoryEntries.Count == 0)
                {
                    nothingInDirectoryTextView.Visibility = ViewStates.Visible;
                }
                else
                {
                    nothingInDirectoryTextView.Visibility = ViewStates.Gone;
                }

                adapter.DirectoryEntries = directoryEntries;
                adapter.NotifyDataSetChanged();
            } catch {
            }
        }
Esempio n. 10
0
            void ShowUriInfos(global::Android.Net.Uri uri, ContentResolver resolver)
            {
                System.Diagnostics.Debug.WriteLine("URI-Scheme/SchemeSpecificPart: " + uri.Scheme + "; " + uri.SchemeSpecificPart);
                try {
                    System.Diagnostics.Debug.WriteLine("GetDocumentId: " + DocumentsContract.GetDocumentId(uri));
                } catch (Exception ex) {
                }
                try {
                    System.Diagnostics.Debug.WriteLine("GetTreeDocumentId: " + DocumentsContract.GetTreeDocumentId(uri));
                } catch (Exception ex) {
                }
                try {
                    System.Diagnostics.Debug.WriteLine("GetRootId: " + DocumentsContract.GetRootId(uri));
                } catch (Exception ex) {
                }
                global::Android.Database.ICursor cursor = resolver.Query(uri, null, null, null, null);
                if (cursor != null)
                {
                    while (cursor.MoveToNext())
                    {
                        for (int i = 0; i < cursor.ColumnCount; i++)
                        {
                            string val = "";
                            switch (cursor.GetType(i))
                            {
                            case global::Android.Database.FieldType.String: val = cursor.GetString(i); break;

                            case global::Android.Database.FieldType.Integer: val = cursor.GetLong(i).ToString(); break; // GetInt() ist hier falsch

                            case global::Android.Database.FieldType.Float: val = cursor.GetFloat(i).ToString(); break;

                            case global::Android.Database.FieldType.Blob: val = "(blob)"; break;

                            case global::Android.Database.FieldType.Null: val = "(null)"; break;
                            }
                            System.Diagnostics.Debug.WriteLine(string.Format("Column={0}; ColumnName={1}; ColumnType={2}: {3}", i, cursor.GetColumnName(i), cursor.GetType(i).ToString(), val));
                        }
                    }
                }
            }
        /// <summary>
        /// Called when activity started with StartActivityForResult() returns.
        /// </summary>
        /// <param name="requestCode">request code used in StartActivityForResult()</param>
        /// <param name="resultCode">result code</param>
        /// <param name="data">intent data from file picking</param>
        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.
                OnFolderPickCancelled();
                this.Finish();
            }
            else
            {
                try
                {
                    if (data?.Data == null)
                    {
                        throw new Exception("Folder picking returned no valid data");
                    }

                    System.Diagnostics.Debug.Write(data.Data);


                    var uri    = data.Data;
                    var docUri = DocumentsContract.BuildDocumentUriUsingTree(uri, DocumentsContract.GetTreeDocumentId(uri));
                    OnFolderPicked(docUri);
                }
                catch (Exception readEx)
                {
                    System.Diagnostics.Debug.Write(readEx);

                    // Notify user file picking failed.
                    FolderPickCancelled?.Invoke(this, readEx);
                }
                finally
                {
                    this.Finish();
                }
            }
        }
Esempio n. 12
0
        public static string GetDocumentName(ContentResolver resolver, Uri uri)
        {
            string name = null;

            if (uri.Scheme == "content")
            {
                ICursor cursor = null;

                try
                {
                    var documentUri =
                        DocumentsContract.BuildDocumentUriUsingTree(uri, DocumentsContract.GetTreeDocumentId(uri));

                    if (documentUri == null)
                    {
                        throw new IOException("Cannot get document URI");
                    }

                    cursor = resolver.Query(documentUri, null, null, null, null);

                    if (cursor != null && cursor.MoveToFirst())
                    {
                        var index = cursor.GetColumnIndex(DocumentsContract.Document.ColumnDisplayName);
                        name = cursor.GetString(index);
                    }
                }
                finally
                {
                    cursor?.Close();
                }
            }
            else
            {
                name = uri.LastPathSegment?.Split(':', 2).Last();
            }

            return(name);
        }
Esempio n. 13
0
        protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
        {
            base.OnActivityResult(requestCode, resultCode, data);

            if (requestCode == PickImageId)
            {
                if ((resultCode == Result.Ok) && (data != null))
                {
                    // Set the filename as the completion of the Task
                    PickImageTaskCompletionSource.SetResult(data.DataString);
                }
                else
                {
                    PickImageTaskCompletionSource.SetResult(null);
                }
            }

            if (requestCode == SAF)
            {
                // content:/com.android.externalstorage.documents/tree/primary%3AMp

                var pref = this.GetSharedPreferences("pref", FileCreationMode.Private);

                Uri docUriTree =
                    DocumentsContract.BuildDocumentUriUsingTree(data.Data,
                                                                DocumentsContract.GetTreeDocumentId(data.Data));

                var query = this.ContentResolver.Query(docUriTree, null, null,
                                                       null, null);
                query.MoveToFirst();
                var filePath = query.GetString(0);
                query.Close();

                pref.Edit().PutString("Directory", filePath).Commit();

                ContinueInit();
            }
        }
        /// <summary>
        /// Creates a directory under the directory represented as the uri in the argument.
        /// </summary>
        /// <param name="uri">The uri of the directory under which a new directory is created.</param>
        /// <param name="directoryName">The directory name of a new directory.</param>
        void CreateDirectory(Android.Net.Uri uri, string directoryName)
        {
            var contentResolver = Activity.ContentResolver;
            var docUri          = DocumentsContract.BuildDocumentUriUsingTree(uri,
                                                                              DocumentsContract.GetTreeDocumentId(uri));
            var directoryUri = DocumentsContract
                               .CreateDocument(contentResolver, docUri, DocumentsContract.Document.MimeTypeDir, directoryName);

            if (directoryUri != null)
            {
                Log.Info(TAG, string.Format(
                             "Created directory : {0}, Document Uri : {1}, Created directory Uri : {2}",
                             directoryName, docUri, directoryUri));
                Toast.MakeText(Activity, string.Format("Created a directory [{0}]",
                                                       directoryName), ToastLength.Short).Show();
            }
            else
            {
                Log.Warn(TAG, string.Format("Failed to create a directory : {0}, Uri {1}", directoryName,
                                            docUri));
                Toast.MakeText(Activity, string.Format("Failed to created a directory [{0}] : ",
                                                       directoryName), ToastLength.Short).Show();
            }
        }
Esempio n. 15
0
        /// <summary>
        /// Use DocumentsContract API to read the file structure at the given location iteratively
        /// includes children
        ///
        /// from https://stackoverflow.com/questions/41096332/issues-traversing-through-directory-hierarchy-with-android-storage-access-framew\
        /// </summary>
        private void DocumentsContractGetFilesFromSelectedFolder()
        {
            // build the children structure of the root directory
            var childrenUri = DocumentsContract.BuildChildDocumentsUriUsingTree(
                _userSelectedDirectory,
                DocumentsContract.GetTreeDocumentId(_userSelectedDirectory)
                );

            // this stack is used in processing subsequent subdirectories
            // when we encounter one in traversing, push it on the stack to be processed
            // we continue until this stack is empty
            //
            // NOTE: stacks are LIFO, therefore this will produce a depth-first approach
            Stack <Android.Net.Uri> dirNodes = new Stack <Android.Net.Uri>();

            dirNodes.Push(childrenUri);

            // used to keep track of how many directories we've traversed so far
            // this only works because we know the structure of the directory!!!
            int i = 0;

            while (dirNodes.Count != 0)
            {
                // get the next subdirectory
                dirNodes.TryPop(out childrenUri);

                // using this sub directory URI, query it for document information
                // the current seach finds all documents in the tree and returns the below columns: ID, Name, and Mime-type
                // searches can be customized using remaining three arguments (currently null which is why we return everything)
                var cursor = this.ContentResolver.Query(
                    childrenUri,
                    new string[] { DocumentsContract.Document.ColumnDocumentId, DocumentsContract.Document.ColumnDisplayName, DocumentsContract.Document.ColumnMimeType },
                    null, null, null
                    );

                // for each of the documents returned from our search,
                while (cursor.MoveToNext())
                {
                    var docId = cursor.GetString(0);
                    var name  = cursor.GetString(1);
                    var mime  = cursor.GetString(2);

                    // only add the text files we've added
                    // this is just for demonstration purposes
                    if (mime == "text/plain")
                    {
                        // TODO: figure out a way to get directory (aka parent) name here
                        // Add the file name to the list of files found so far
                        _filenames.Add($"Director {i}/{name}");
                    }
                    // if this is a directory, push its URI to the directory nodes stack for later processing
                    else if (mime == DocumentsContract.Document.MimeTypeDir)
                    {
                        dirNodes.Push(
                            DocumentsContract.BuildChildDocumentsUriUsingTree(
                                _parentUri,
                                docId));
                    }
                }
                ++i;
                // cleanup cursor
                cursor.Dispose();
            }
            return;
        }
Esempio n. 16
0
        protected override async void OnActivityResult(int requestCode, Result resultCode, Intent intent)
        {
            base.OnActivityResult(requestCode, resultCode, intent);
            Log.Info("TranslateFGO", $"ActivityResult Code: {resultCode}, Result: {resultCode}, Data: {intent?.DataString}");

            if (resultCode == Result.Ok && requestCode == (int)RequestCodes.FolderIntentRequestCode)
            {
                var service = new ContentManager();

                var uri            = intent.Data;
                var selectedFolder = DocumentsContract.GetTreeDocumentId(uri);

                if (selectedFolder == null || !selectedFolder.EndsWith("Android"))
                {
                    var folderSplit  = selectedFolder?.Split(":").Last();
                    var infoText     = UIFunctions.GetResourceString("AndroidFolderNotSelected");
                    var errorMessage = String.Format(infoText, !string.IsNullOrEmpty(folderSplit) ? folderSplit : "none");
                    Toast.MakeText(this.Context, errorMessage, ToastLength.Long)?.Show();
                    return;
                }

                service.ClearCache();
                var dataChildren = service.GetFolderChildren(uri, "data/"); // Get list of children to find FGO folders

                if (dataChildren.Count == 0)
                {
                    var infoText = UIFunctions.GetResourceString("AndroidDataFolderEmpty");
                    Toast.MakeText(this.Context, infoText, ToastLength.Long)?.Show();
                    return;
                }

                var  appNamesList = ContentManager.ValidAppNames.ToList();
                bool found        = false;
                foreach (var folder in dataChildren)
                {
                    if (appNamesList.Contains(folder.Path.Split("/").Last()))
                    {
                        found = true;
                    }
                }

                if (!found)
                {
                    var infoText = UIFunctions.GetResourceString("NoFGOInstallationFoundToast");
                    Toast.MakeText(this.Context, infoText, ToastLength.Long)?.Show();
                    return;
                }

                // Save URL
                try
                {
                    this.ContentResolver.TakePersistableUriPermission(uri, intent.Flags & (ActivityFlags.GrantReadUriPermission | ActivityFlags.GrantWriteUriPermission));
                }
                catch (Exception ex)
                {
                    Log.Error("BetterFGO", $"Error thrown while persisting uri: {ex}");
                    var errorText    = UIFunctions.GetResourceString("UnknownError");
                    var errorMessage = String.Format(errorText, ex.ToString());
                    Toast.MakeText(this.Context, errorMessage, ToastLength.Long)?.Show();
                }

                // If we got this far, all is well
                var successText = UIFunctions.GetResourceString("Android11SetupSuccessful");
                Toast.MakeText(this.Context, successText, ToastLength.Long)?.Show();

                Log.Info("BetterFGO", $"Saving URI: {uri?.ToString()}");

                Preferences.Set("StorageType", (int)ContentType.StorageFramework);
                Preferences.Set("StorageLocation", uri?.ToString());

                MessagingCenter.Send(Xamarin.Forms.Application.Current, "return_to_main_page");
            }
        }
        public static string ToPhysicalPath(this Uri uri, Context ctx)
        {
            var isKitkat = Build.VERSION.SdkInt >= BuildVersionCodes.Kitkat;

            var isDocumentUri = DocumentsContract.IsDocumentUri(ctx, uri);
            var isTreeUri     = DocumentsContract.IsTreeUri(uri);

            if (isKitkat && (isDocumentUri || isTreeUri))
            {
                var rootUri = isDocumentUri
                    ? DocumentsContract.GetDocumentId(uri)
                    : DocumentsContract.GetTreeDocumentId(uri);

                if (uri.Authority == "com.android.localstorage.documents")
                {
                    return(rootUri);
                }

                if (uri.Authority == "com.android.externalstorage.documents")
                {
                    var splitDocumentId = rootUri.Split(':');
                    var type            = splitDocumentId[0];

                    if (string.Compare(type, "primary", StringComparison.InvariantCultureIgnoreCase) == 0)
                    {
                        return(Path.Combine(Android.OS.Environment.ExternalStorageDirectory.Path, splitDocumentId[1]));
                    }

                    // Handle non-primary
                    //! TODO: This is absolutely disgusting but android offers no easy way to obtain a path to a directory from an Uri to a directory.
                    //! I'm not even sure this is portable.
                    var contentUri = MediaStore.Files.GetContentUri(type);
                    var cursor     = ctx.ContentResolver.Query(contentUri, null, null, null, null);
                    if (cursor != null && cursor.MoveToFirst())
                    {
                        var path = cursor.GetString(0);
                        cursor.Close();
                        return(path);
                    }
                    else
                    {
                        return("/storage/" + rootUri.Replace(':', '/'));
                    }

                    return(contentUri.ToPhysicalPath(ctx));
                }

                if (uri.Authority == "com.android.providers.downloads.documents")
                {
                    var contentUri = ContentUris.WithAppendedId(Uri.Parse("content://downloads/public_downloads"), long.Parse(rootUri));

                    return(ctx.GetDataColumn(contentUri, MediaStore.MediaColumns.Data, null, null));
                }

                if (uri.Authority == "com.android.providers.media.documents")
                {
                    var splitDocumentId = rootUri.Split(':');
                    var type            = splitDocumentId[0];

                    Uri contentUri = null;

                    if ("image" == type)
                    {
                        contentUri = MediaStore.Images.Media.ExternalContentUri;
                    }
                    else if ("video" == type)
                    {
                        contentUri = MediaStore.Video.Media.ExternalContentUri;
                    }
                    else if ("audio" == type)
                    {
                        contentUri = MediaStore.Audio.Media.ExternalContentUri;
                    }

                    return(ctx.GetDataColumn(contentUri, MediaStore.MediaColumns.Data, "_id?=", splitDocumentId[1]));
                }
            }
            // MediaStore and general
            else if (uri.Scheme == "content")
            {
                if (uri.Authority == "com.google.android.apps.photos.content")
                {
                    return(uri.LastPathSegment);
                }

                return(ctx.GetDataColumn(uri, MediaStore.MediaColumns.Data, null, null));
            }
            else if (uri.Scheme == "file")
            {
                return(uri.Path);
            }

            return("");
        }
Esempio n. 18
0
        private List <Track> UpdateDirectoryEntries(Android.Net.Uri uri)
        {
            var contentResolver = Instance.ContentResolver;
            var childrenUri     = DocumentsContract.BuildChildDocumentsUriUsingTree(uri, DocumentsContract.GetTreeDocumentId(uri));

            string[] projection =
            {
                MediaStore.Audio.AudioColumns.Data,
                MediaStore.Audio.AudioColumns.Title,
                MediaStore.Audio.AudioColumns.Album,
                MediaStore.Audio.ArtistColumns.Artist,
                DocumentsContract.Document.ColumnDisplayName,
                DocumentsContract.Document.ColumnMimeType,
                DocumentsContract.Document.ColumnDocumentId,
            };

            var childCursor = contentResolver.Query(childrenUri, projection, MediaStore.Audio.AudioColumns.Data + " like ? ", new String[] { "%utm%" }, null);

            try
            {
                var findTracks = new List <Track>();
                while (childCursor.MoveToNext())
                {
                    string path     = childCursor.GetString(0);
                    string title    = childCursor.GetString(1);
                    string album    = childCursor.GetString(2);
                    string artist   = childCursor.GetString(3);
                    string fileName = childCursor.GetString(4);
                    string mime     = childCursor.GetString(5);
                    string docId    = childCursor.GetString(6);
                    var    childUri = DocumentsContract.BuildChildDocumentsUriUsingTree(uri, docId);
                    //var childUri = DocumentsContract.Bui(childrenUri, docId);

                    if (mime.Contains("audio"))
                    {
                        var file  = new Java.IO.File(childUri.Path);
                        var split = file.Path.Split(":");
                        path = split[1];

                        var track = new Track
                        {
                            FileName = fileName,
                            AlternativePathObject = childUri,//path + Java.IO.File.Separator + fileName,
                        };
                        findTracks.Add(track);
                    }
                }

                return(findTracks);
            }
            catch (Exception)
            {
                return(null);
            }
        }