java.lang.Object
↳androidx.documentfile.provider.DocumentFile
Gradle dependencies
compile group: 'androidx.documentfile', name: 'documentfile', version: '1.1.0-alpha01'
- groupId: androidx.documentfile
- artifactId: documentfile
- version: 1.1.0-alpha01
Artifact androidx.documentfile:documentfile:1.1.0-alpha01 it located at Google repository (https://maven.google.com/)
Androidx artifact mapping:
androidx.documentfile:documentfile com.android.support:documentfile
Androidx class mapping:
androidx.documentfile.provider.DocumentFile android.support.v4.provider.DocumentFile
Overview
Representation of a document backed by either a
or a raw file on disk. This is a
utility class designed to emulate the traditional java.io.File
interface. It
offers a simplified view of a tree of documents, but it has substantial
overhead. For optimal performance and a richer feature set, use the
android.provider.DocumentsContract
methods and constants directly.
There are several differences between documents and traditional files:
- Documents express their display name and MIME type as separate fields,
instead of relying on file extensions. Some documents providers may still
choose to append extensions to their display names, but that's an
implementation detail.
- A single document may appear as the child of multiple directories, so it
doesn't inherently know who its parent is. That is, documents don't have a
strong notion of path. You can easily traverse a tree of documents from
parent to child, but not from child to parent.
- Each document has a unique identifier within that provider. This
identifier is an opaque implementation detail of the provider, and
as such it must not be parsed.
Before using this class, first consider if you really need access to an
entire subtree of documents. The principle of least privilege dictates that
you should only ask for access to documents you really need. If you only need
the user to pick a single file, use or
. If you want to let the user pick multiple
files, add . If you only need the user to
save a single file, use . If you use
these APIs, you can pass the resulting into
DocumentFile.fromSingleUri(Context, Uri) to work with that document.
If you really do need full access to an entire subtree of documents, start by
launching to let the user pick a
directory. Then pass the resulting into
DocumentFile.fromTreeUri(Context, Uri) to start working with the user selected
tree.
As you navigate the tree of DocumentFile instances, you can always use
DocumentFile.getUri() to obtain the Uri representing the underlying document for
that object, for use with , etc.
To simplify your code on devices running
or earlier, you can use
DocumentFile.fromFile(File) which emulates the behavior of a
.
Summary
Methods |
---|
public abstract boolean | canRead()
Indicates whether the current context is allowed to read from this file. |
public abstract boolean | canWrite()
Indicates whether the current context is allowed to write to this file. |
public abstract DocumentFile | createDirectory(java.lang.String displayName)
Create a new directory as a direct child of this directory. |
public abstract DocumentFile | createFile(java.lang.String mimeType, java.lang.String displayName)
Create a new document as a direct child of this directory. |
public abstract boolean | delete()
Deletes this file. |
public abstract boolean | exists()
Returns a boolean indicating whether this file can be found. |
public DocumentFile | findFile(java.lang.String displayName)
Search through DocumentFile.listFiles() for the first document matching the
given display name. |
public static DocumentFile | fromFile(java.io.File file)
Create a DocumentFile representing the filesystem tree rooted at
the given java.io.File . |
public static DocumentFile | fromSingleUri(Context context, Uri singleUri)
Create a DocumentFile representing the single document at the
given . |
public static DocumentFile | fromTreeUri(Context context, Uri treeUri)
Create a DocumentFile representing the document tree rooted at
the given . |
public abstract java.lang.String | getName()
Return the display name of this document. |
public DocumentFile | getParentFile()
Return the parent file of this document. |
public abstract java.lang.String | getType()
Return the MIME type of this document. |
public abstract Uri | getUri()
Return a Uri for the underlying document represented by this file. |
public abstract boolean | isDirectory()
Indicates if this file represents a directory. |
public static boolean | isDocumentUri(Context context, Uri uri)
Test if given Uri is backed by a
. |
public abstract boolean | isFile()
Indicates if this file represents a file. |
public abstract boolean | isVirtual()
Indicates if this file represents a virtual document. |
public abstract long | lastModified()
Returns the time when this file was last modified, measured in
milliseconds since January 1st, 1970, midnight. |
public abstract long | length()
Returns the length of this file in bytes. |
public abstract DocumentFile | listFiles()
Returns an array of files contained in the directory represented by this
file. |
public abstract boolean | renameTo(java.lang.String displayName)
Renames this file to displayName. |
from java.lang.Object | clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Methods
Create a DocumentFile representing the filesystem tree rooted at
the given java.io.File
. This doesn't give you any additional access to the
underlying files beyond what your app already has.
DocumentFile.getUri() will return file:// Uris for files explored
through this tree.
public static
DocumentFile fromSingleUri(Context context, Uri singleUri)
Create a DocumentFile representing the single document at the
given . This is only useful on devices running
or later, and will return
null when called on earlier platform versions.
Parameters:
singleUri: the from a successful
or
request.
public static
DocumentFile fromTreeUri(Context context, Uri treeUri)
Create a DocumentFile representing the document tree rooted at
the given . This is only useful on devices running
or later, and will return
null when called on earlier platform versions.
Parameters:
treeUri: the from a successful
request.
public static boolean
isDocumentUri(Context context, Uri uri)
Test if given Uri is backed by a
.
public abstract
DocumentFile createFile(java.lang.String mimeType, java.lang.String displayName)
Create a new document as a direct child of this directory.
Parameters:
mimeType: MIME type of new document, such as image/png or
audio/flac
displayName: name of new document, without any file extension
appended; the underlying provider may choose to append the
extension
Returns:
file representing newly created document, or null if failed
See also: android.provider.DocumentsContract
public abstract
DocumentFile createDirectory(java.lang.String displayName)
Create a new directory as a direct child of this directory.
Parameters:
displayName: name of new directory
Returns:
file representing newly created directory, or null if failed
See also: android.provider.DocumentsContract
public abstract Uri
getUri()
Return a Uri for the underlying document represented by this file. This
can be used with other platform APIs to manipulate or share the
underlying content. You can use DocumentFile.isDocumentUri(Context, Uri) to
test if the returned Uri is backed by a
.
See also:
public abstract java.lang.String
getName()
Return the display name of this document.
See also:
public abstract java.lang.String
getType()
Return the MIME type of this document.
See also:
Return the parent file of this document. Only defined inside of the
user-selected tree; you can never escape above the top of the tree.
The underlying only defines a
forward mapping from parent to child, so the reverse mapping of child to
parent offered here is purely a convenience method, and it may be
incorrect if the underlying tree structure changes.
public abstract boolean
isDirectory()
Indicates if this file represents a directory.
Returns:
true if this file is a directory, false
otherwise.
See also:
public abstract boolean
isFile()
Indicates if this file represents a file.
Returns:
true if this file is a file, false otherwise.
See also:
public abstract boolean
isVirtual()
Indicates if this file represents a virtual document.
Returns:
true if this file is a virtual document.
See also:
public abstract long
lastModified()
Returns the time when this file was last modified, measured in
milliseconds since January 1st, 1970, midnight. Returns 0 if the file
does not exist, or if the modified time is unknown.
Returns:
the time when this file was last modified.
See also:
public abstract long
length()
Returns the length of this file in bytes. Returns 0 if the file does not
exist, or if the length is unknown. The result for a directory is not
defined.
Returns:
the number of bytes in this file.
See also:
public abstract boolean
canRead()
Indicates whether the current context is allowed to read from this file.
Returns:
true if this file can be read, false otherwise.
public abstract boolean
canWrite()
Indicates whether the current context is allowed to write to this file.
Returns:
true if this file can be written, false
otherwise.
See also:
public abstract boolean
delete()
Deletes this file.
Note that this method does not throw IOException on
failure. Callers must check the return value.
Returns:
true if this file was deleted, false otherwise.
See also: android.provider.DocumentsContract
public abstract boolean
exists()
Returns a boolean indicating whether this file can be found.
Returns:
true if this file exists, false otherwise.
Returns an array of files contained in the directory represented by this
file.
Returns:
an array of files.
See also: android.provider.DocumentsContract
Search through DocumentFile.listFiles() for the first document matching the
given display name. Returns null when no matching document is
found.
public abstract boolean
renameTo(java.lang.String displayName)
Renames this file to displayName.
Note that this method does not throw IOException on
failure. Callers must check the return value.
Some providers may need to create a new document to reflect the rename,
potentially with a different MIME type, so DocumentFile.getUri() and
DocumentFile.getType() may change to reflect the rename.
When renaming a directory, children previously enumerated through
DocumentFile.listFiles() may no longer be valid.
Parameters:
displayName: the new display name.
Returns:
true on success.
See also: android.provider.DocumentsContract
Source
/*
* Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.documentfile.provider;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.io.File;
/**
* Representation of a document backed by either a
* {@link android.provider.DocumentsProvider} or a raw file on disk. This is a
* utility class designed to emulate the traditional {@link File} interface. It
* offers a simplified view of a tree of documents, but it has substantial
* overhead. For optimal performance and a richer feature set, use the
* {@link android.provider.DocumentsContract} methods and constants directly.
* <p>
* There are several differences between documents and traditional files:
* <ul>
* <li>Documents express their display name and MIME type as separate fields,
* instead of relying on file extensions. Some documents providers may still
* choose to append extensions to their display names, but that's an
* implementation detail.
* <li>A single document may appear as the child of multiple directories, so it
* doesn't inherently know who its parent is. That is, documents don't have a
* strong notion of path. You can easily traverse a tree of documents from
* parent to child, but not from child to parent.
* <li>Each document has a unique identifier within that provider. This
* identifier is an <em>opaque</em> implementation detail of the provider, and
* as such it must not be parsed.
* </ul>
* <p>
* Before using this class, first consider if you really need access to an
* entire subtree of documents. The principle of least privilege dictates that
* you should only ask for access to documents you really need. If you only need
* the user to pick a single file, use {@link Intent#ACTION_OPEN_DOCUMENT} or
* {@link Intent#ACTION_GET_CONTENT}. If you want to let the user pick multiple
* files, add {@link Intent#EXTRA_ALLOW_MULTIPLE}. If you only need the user to
* save a single file, use {@link Intent#ACTION_CREATE_DOCUMENT}. If you use
* these APIs, you can pass the resulting {@link Intent#getData()} into
* {@link #fromSingleUri(Context, Uri)} to work with that document.
* <p>
* If you really do need full access to an entire subtree of documents, start by
* launching {@link Intent#ACTION_OPEN_DOCUMENT_TREE} to let the user pick a
* directory. Then pass the resulting {@link Intent#getData()} into
* {@link #fromTreeUri(Context, Uri)} to start working with the user selected
* tree.
* <p>
* As you navigate the tree of DocumentFile instances, you can always use
* {@link #getUri()} to obtain the Uri representing the underlying document for
* that object, for use with {@link ContentResolver#openInputStream(Uri)}, etc.
* <p>
* To simplify your code on devices running
* {@link android.os.Build.VERSION_CODES#KITKAT} or earlier, you can use
* {@link #fromFile(File)} which emulates the behavior of a
* {@link android.provider.DocumentsProvider}.
*
* @see android.provider.DocumentsProvider
* @see android.provider.DocumentsContract
*/
public abstract class DocumentFile {
static final String TAG = "DocumentFile";
@Nullable
private final DocumentFile mParent;
DocumentFile(@Nullable DocumentFile parent) {
mParent = parent;
}
/**
* Create a {@link DocumentFile} representing the filesystem tree rooted at
* the given {@link File}. This doesn't give you any additional access to the
* underlying files beyond what your app already has.
* <p>
* {@link #getUri()} will return {@code file://} Uris for files explored
* through this tree.
*/
@NonNull
public static DocumentFile fromFile(@NonNull File file) {
return new RawDocumentFile(null, file);
}
/**
* Create a {@link DocumentFile} representing the single document at the
* given {@link Uri}. This is only useful on devices running
* {@link android.os.Build.VERSION_CODES#KITKAT} or later, and will return
* {@code null} when called on earlier platform versions.
*
* @param singleUri the {@link Intent#getData()} from a successful
* {@link Intent#ACTION_OPEN_DOCUMENT} or
* {@link Intent#ACTION_CREATE_DOCUMENT} request.
*/
@Nullable
public static DocumentFile fromSingleUri(@NonNull Context context, @NonNull Uri singleUri) {
if (Build.VERSION.SDK_INT >= 19) {
return new SingleDocumentFile(null, context, singleUri);
} else {
return null;
}
}
/**
* Create a {@link DocumentFile} representing the document tree rooted at
* the given {@link Uri}. This is only useful on devices running
* {@link android.os.Build.VERSION_CODES#LOLLIPOP} or later, and will return
* {@code null} when called on earlier platform versions.
*
* @param treeUri the {@link Intent#getData()} from a successful
* {@link Intent#ACTION_OPEN_DOCUMENT_TREE} request.
*/
@Nullable
public static DocumentFile fromTreeUri(@NonNull Context context, @NonNull Uri treeUri) {
if (Build.VERSION.SDK_INT >= 21) {
String documentId = DocumentsContractApi.getTreeDocumentId(treeUri);
if (DocumentsContractApi.isDocumentUri(context, treeUri)) {
documentId = DocumentsContractApi.getDocumentId(treeUri);
}
if (documentId == null) {
throw new IllegalArgumentException(
"Could not get document ID from Uri: " + treeUri);
}
Uri treeDocumentUri =
DocumentsContractApi.buildDocumentUriUsingTree(treeUri, documentId);
if (treeDocumentUri == null) {
throw new NullPointerException(
"Failed to build documentUri from a tree: " + treeUri);
}
return new TreeDocumentFile(null, context, treeDocumentUri);
} else {
return null;
}
}
/**
* Test if given Uri is backed by a
* {@link android.provider.DocumentsProvider}.
*/
public static boolean isDocumentUri(@NonNull Context context, @Nullable Uri uri) {
return DocumentsContractApi.isDocumentUri(context, uri);
}
/**
* Create a new document as a direct child of this directory.
*
* @param mimeType MIME type of new document, such as {@code image/png} or
* {@code audio/flac}
* @param displayName name of new document, without any file extension
* appended; the underlying provider may choose to append the
* extension
* @return file representing newly created document, or null if failed
* @throws UnsupportedOperationException when working with a single document
* created from {@link #fromSingleUri(Context, Uri)}.
* @see android.provider.DocumentsContract#createDocument(ContentResolver,
* Uri, String, String)
*/
@Nullable
public abstract DocumentFile createFile(@NonNull String mimeType, @NonNull String displayName);
/**
* Create a new directory as a direct child of this directory.
*
* @param displayName name of new directory
* @return file representing newly created directory, or null if failed
* @throws UnsupportedOperationException when working with a single document
* created from {@link #fromSingleUri(Context, Uri)}.
* @see android.provider.DocumentsContract#createDocument(ContentResolver,
* Uri, String, String)
*/
@Nullable
public abstract DocumentFile createDirectory(@NonNull String displayName);
/**
* Return a Uri for the underlying document represented by this file. This
* can be used with other platform APIs to manipulate or share the
* underlying content. You can use {@link #isDocumentUri(Context, Uri)} to
* test if the returned Uri is backed by a
* {@link android.provider.DocumentsProvider}.
*
* @see Intent#setData(Uri)
* @see Intent#setClipData(android.content.ClipData)
* @see ContentResolver#openInputStream(Uri)
* @see ContentResolver#openOutputStream(Uri)
* @see ContentResolver#openFileDescriptor(Uri, String)
*/
@NonNull
public abstract Uri getUri();
/**
* Return the display name of this document.
*
* @see android.provider.DocumentsContract.Document#COLUMN_DISPLAY_NAME
*/
@Nullable
public abstract String getName();
/**
* Return the MIME type of this document.
*
* @see android.provider.DocumentsContract.Document#COLUMN_MIME_TYPE
*/
@Nullable
public abstract String getType();
/**
* Return the parent file of this document. Only defined inside of the
* user-selected tree; you can never escape above the top of the tree.
* <p>
* The underlying {@link android.provider.DocumentsProvider} only defines a
* forward mapping from parent to child, so the reverse mapping of child to
* parent offered here is purely a convenience method, and it may be
* incorrect if the underlying tree structure changes.
*/
@Nullable
public DocumentFile getParentFile() {
return mParent;
}
/**
* Indicates if this file represents a <em>directory</em>.
*
* @return {@code true} if this file is a directory, {@code false}
* otherwise.
* @see android.provider.DocumentsContract.Document#MIME_TYPE_DIR
*/
public abstract boolean isDirectory();
/**
* Indicates if this file represents a <em>file</em>.
*
* @return {@code true} if this file is a file, {@code false} otherwise.
* @see android.provider.DocumentsContract.Document#COLUMN_MIME_TYPE
*/
public abstract boolean isFile();
/**
* Indicates if this file represents a <em>virtual</em> document.
*
* @return {@code true} if this file is a virtual document.
* @see android.provider.DocumentsContract.Document#FLAG_VIRTUAL_DOCUMENT
*/
public abstract boolean isVirtual();
/**
* Returns the time when this file was last modified, measured in
* milliseconds since January 1st, 1970, midnight. Returns 0 if the file
* does not exist, or if the modified time is unknown.
*
* @return the time when this file was last modified.
* @see android.provider.DocumentsContract.Document#COLUMN_LAST_MODIFIED
*/
public abstract long lastModified();
/**
* Returns the length of this file in bytes. Returns 0 if the file does not
* exist, or if the length is unknown. The result for a directory is not
* defined.
*
* @return the number of bytes in this file.
* @see android.provider.DocumentsContract.Document#COLUMN_SIZE
*/
public abstract long length();
/**
* Indicates whether the current context is allowed to read from this file.
*
* @return {@code true} if this file can be read, {@code false} otherwise.
*/
public abstract boolean canRead();
/**
* Indicates whether the current context is allowed to write to this file.
*
* @return {@code true} if this file can be written, {@code false}
* otherwise.
* @see android.provider.DocumentsContract.Document#COLUMN_FLAGS
* @see android.provider.DocumentsContract.Document#FLAG_SUPPORTS_DELETE
* @see android.provider.DocumentsContract.Document#FLAG_SUPPORTS_WRITE
* @see android.provider.DocumentsContract.Document#FLAG_DIR_SUPPORTS_CREATE
*/
public abstract boolean canWrite();
/**
* Deletes this file.
* <p>
* Note that this method does <i>not</i> throw {@code IOException} on
* failure. Callers must check the return value.
*
* @return {@code true} if this file was deleted, {@code false} otherwise.
* @see android.provider.DocumentsContract#deleteDocument(ContentResolver,
* Uri)
*/
public abstract boolean delete();
/**
* Returns a boolean indicating whether this file can be found.
*
* @return {@code true} if this file exists, {@code false} otherwise.
*/
public abstract boolean exists();
/**
* Returns an array of files contained in the directory represented by this
* file.
*
* @return an array of files.
* @throws UnsupportedOperationException when working with a single document
* created from {@link #fromSingleUri(Context, Uri)}.
* @see android.provider.DocumentsContract#buildChildDocumentsUriUsingTree(Uri,
* String)
*/
@NonNull
public abstract DocumentFile[] listFiles();
/**
* Search through {@link #listFiles()} for the first document matching the
* given display name. Returns {@code null} when no matching document is
* found.
*
* @throws UnsupportedOperationException when working with a single document
* created from {@link #fromSingleUri(Context, Uri)}.
*/
@Nullable
public DocumentFile findFile(@NonNull String displayName) {
for (DocumentFile doc : listFiles()) {
if (displayName.equals(doc.getName())) {
return doc;
}
}
return null;
}
/**
* Renames this file to {@code displayName}.
* <p>
* Note that this method does <i>not</i> throw {@code IOException} on
* failure. Callers must check the return value.
* <p>
* Some providers may need to create a new document to reflect the rename,
* potentially with a different MIME type, so {@link #getUri()} and
* {@link #getType()} may change to reflect the rename.
* <p>
* When renaming a directory, children previously enumerated through
* {@link #listFiles()} may no longer be valid.
*
* @param displayName the new display name.
* @return true on success.
* @throws UnsupportedOperationException when working with a single document
* created from {@link #fromSingleUri(Context, Uri)}.
* @see android.provider.DocumentsContract#renameDocument(ContentResolver,
* Uri, String)
*/
public abstract boolean renameTo(@NonNull String displayName);
}