/// <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() !]);
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); } }
// 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); } }
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 { } }
private StorageEntryBase[] GetEntriesImpl(string searchPattern = null) { var itemProperties = new List <StorageEntryBase>(); var childrenUri = DocumentsContract.BuildChildDocumentsUriUsingTree(AndroidUri, DocumentsContract.GetDocumentId(AndroidUri)); var projection = new string[] { DocumentsContract.Document.ColumnDocumentId, DocumentsContract.Document.ColumnDisplayName, DocumentsContract.Document.ColumnMimeType, DocumentsContract.Document.ColumnSize, DocumentsContract.Document.ColumnLastModified }; //build searchPattern string selection = null; string[] selectionArgs = null; var regXpattern = searchPattern != null?Storage.WildcardToRegex(searchPattern) : null; //it looks doesn't supported for storage //if (!string.IsNullOrEmpty(searchPattern)) //{ // selection = $"{DocumentsContract.Document.ColumnDocumentId}=?"; // selectionArgs = new string[] { searchPattern.Replace("*", "%") }; //} //run the query using (var cursor = Context.ContentResolver.Query(childrenUri, projection, selection, selectionArgs, null)) { while (cursor.MoveToNext()) { var documentId = cursor.GetString(0); var name = cursor.GetString(1); if (regXpattern != null && !Regex.IsMatch(name, regXpattern)) { continue; } StreamAttributes attribute = 0; if (!string.IsNullOrEmpty(name) && name[0] == '.') { attribute |= StreamAttributes.Hidden; } itemProperties.Add( new StorageEntryBase() { Name = name, Uri = AndroidUriToUri(DocumentsContract.BuildDocumentUriUsingTree(AndroidUri, documentId)), IsStorage = cursor.GetString(2) == DocumentsContract.Document.MimeTypeDir, Size = long.Parse(cursor.GetString(3)), LastWriteTime = cursor.GetString(4) != null ? JavaTimeStampToDateTime(double.Parse(cursor.GetString(4))) : DateTime.Now, Attributes = attribute, }); if (!string.IsNullOrEmpty(searchPattern)) { break; } } cursor.Close(); } return(itemProperties.ToArray()); }
/// <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; }