public async Task <bool> RemoveFileIfExists(ContentType accessType, string filename, string storageLocationBase) { var fileIfExists = GetPathIfFileExists(accessType, filename, storageLocationBase); if (!fileIfExists.Exists) { return(false); } switch (accessType) { case ContentType.DirectAccess: File.Delete(fileIfExists.Path); await Task.Delay(50); return(true); case ContentType.StorageFramework: var doc = DocumentsContract.BuildDocumentUriUsingTree(Uri.Parse(storageLocationBase), fileIfExists.Path); DocumentFile file = DocumentFile.FromTreeUri(Android.App.Application.Context, doc); await Task.Delay(50); return(file.Delete()); default: throw new ArgumentOutOfRangeException(nameof(accessType), accessType, null); } }
private async Task <byte[]> ReadExistingFileAsync(ContentType accessType, string filePath, string storageLocationBase) { switch (accessType) { case ContentType.DirectAccess: return(await File.ReadAllBytesAsync(filePath)); case ContentType.StorageFramework: var baseUri = Uri.Parse(storageLocationBase); var contentPath = DocumentsContract.BuildDocumentUriUsingTree(baseUri, filePath); var descriptor = AppContentResolver.OpenAssetFileDescriptor(contentPath !, "r"); if (descriptor == null) { throw new Exception($"File descriptor null, tried to open {contentPath}."); } var readStream = descriptor.CreateInputStream(); if (!readStream.CanRead) { throw new Exception("Cannot read the readStream."); } byte[] outputBuffer = new byte[readStream.Length]; await readStream.ReadAsync(outputBuffer); return(outputBuffer); default: throw new ArgumentOutOfRangeException(nameof(accessType), accessType, null); } }
internal static string GetPathForDocTree(Context context, Uri uri) { var docUri = DocumentsContract.BuildDocumentUriUsingTree(uri, DocumentsContract.GetTreeDocumentId(uri)); string path = GetPath(context, docUri); return(path); }
/// <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())); }
/// <summary> /// z.B.: //com.android.externalstorage.documents/tree/19F4-0903:/document/19F4-0903:abc/def/ghi.txt aus /abc/def/ghi.txt (API level 21 / Lollipop / 5.0) /// </summary> /// <param name="storagename">z.B. "primary" oder "19F4-0903"</param> /// <param name="volpath">abs. Pfad im Volume</param> /// <returns></returns> global::Android.Net.Uri GetDocumentUriUsingTree(string storagename, string volpath) { if (volpath.Length > 0 && volpath[0] == '/') { volpath = volpath.Substring(1); } // Build URI representing the target Document#COLUMN_DOCUMENT_ID in a document provider. (API level 21 / Lollipop / 5.0) return(DocumentsContract.BuildDocumentUriUsingTree(GetTreeDocumentUri(storagename), storagename + ":" + volpath)); }
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); } }
/// <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); } }
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 { } }
/// <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(); } } }
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); }
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(); } }
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()); }