15fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey/*
25fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * Copyright (C) 2014 The Android Open Source Project
35fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey *
45fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
55fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * you may not use this file except in compliance with the License.
65fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * You may obtain a copy of the License at
75fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey *
85fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
95fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey *
105fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * Unless required by applicable law or agreed to in writing, software
115fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
125fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * See the License for the specific language governing permissions and
145fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * limitations under the License.
155fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey */
165fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
175fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkeypackage android.support.v4.provider;
185fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
195fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkeyimport android.content.ContentResolver;
205fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkeyimport android.content.Context;
215fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkeyimport android.content.Intent;
225fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkeyimport android.net.Uri;
235fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkeyimport android.os.Build;
245fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
255fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkeyimport java.io.File;
265fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
275fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey/**
285fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * Representation of a document backed by either a
295fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * {@link android.provider.DocumentsProvider} or a raw file on disk. This is a
305fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * utility class designed to emulate the traditional {@link File} interface. It
315fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * offers a simplified view of a tree of documents, but it has substantial
325fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * overhead. For optimal performance and a richer feature set, use the
335fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * {@link android.provider.DocumentsContract} methods and constants directly.
345fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * <p>
355fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * There are several differences between documents and traditional files:
365fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * <ul>
375fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * <li>Documents express their display name and MIME type as separate fields,
385fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * instead of relying on file extensions. Some documents providers may still
395fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * choose to append extensions to their display names, but that's an
405fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * implementation detail.
415fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * <li>A single document may appear as the child of multiple directories, so it
425fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * doesn't inherently know who its parent is. That is, documents don't have a
435fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * strong notion of path. You can easily traverse a tree of documents from
445fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * parent to child, but not from child to parent.
455fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * <li>Each document has a unique identifier within that provider. This
465fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * identifier is an <em>opaque</em> implementation detail of the provider, and
475fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * as such it must not be parsed.
485fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * </ul>
495fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * <p>
505fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * Before using this class, first consider if you really need access to an
515fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * entire subtree of documents. The principle of least privilege dictates that
525fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * you should only ask for access to documents you really need. If you only need
535fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * the user to pick a single file, use {@link Intent#ACTION_OPEN_DOCUMENT} or
545fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * {@link Intent#ACTION_GET_CONTENT}. If you want to let the user pick multiple
555fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * files, add {@link Intent#EXTRA_ALLOW_MULTIPLE}. If you only need the user to
565fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * save a single file, use {@link Intent#ACTION_CREATE_DOCUMENT}. If you use
575fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * these APIs, you can pass the resulting {@link Intent#getData()} into
585fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * {@link #fromSingleUri(Context, Uri)} to work with that document.
595fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * <p>
605fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * If you really do need full access to an entire subtree of documents, start by
615fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * launching {@link Intent#ACTION_OPEN_DOCUMENT_TREE} to let the user pick a
625fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * directory. Then pass the resulting {@link Intent#getData()} into
635fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * {@link #fromTreeUri(Context, Uri)} to start working with the user selected
645fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * tree.
655fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * <p>
665fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * As you navigate the tree of DocumentFile instances, you can always use
675fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * {@link #getUri()} to obtain the Uri representing the underlying document for
685fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * that object, for use with {@link ContentResolver#openInputStream(Uri)}, etc.
695fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * <p>
705fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * To simplify your code on devices running
715fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * {@link android.os.Build.VERSION_CODES#KITKAT} or earlier, you can use
725fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * {@link #fromFile(File)} which emulates the behavior of a
735fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * {@link android.provider.DocumentsProvider}.
745fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey *
755fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * @see android.provider.DocumentsProvider
765fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * @see android.provider.DocumentsContract
775fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey */
785fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkeypublic abstract class DocumentFile {
795fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    static final String TAG = "DocumentFile";
805fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
815fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    private final DocumentFile mParent;
825fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
835fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    DocumentFile(DocumentFile parent) {
845fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        mParent = parent;
855fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    }
865fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
875fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    /**
885fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * Create a {@link DocumentFile} representing the filesystem tree rooted at
898b977168147ee1135c39de1ac3c1b45aa83376c8Jeff Sharkey     * the given {@link File}. This doesn't give you any additional access to the
905fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * underlying files beyond what your app already has.
915fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * <p>
925fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * {@link #getUri()} will return {@code file://} Uris for files explored
935fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * through this tree.
945fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     */
955fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    public static DocumentFile fromFile(File file) {
965fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        return new RawDocumentFile(null, file);
975fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    }
985fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
995fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    /**
1005fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * Create a {@link DocumentFile} representing the single document at the
1015fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * given {@link Uri}. This is only useful on devices running
1025fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * {@link android.os.Build.VERSION_CODES#KITKAT} or later, and will return
1035fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * {@code null} when called on earlier platform versions.
1045fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *
1055fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @param singleUri the {@link Intent#getData()} from a successful
1065fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *            {@link Intent#ACTION_OPEN_DOCUMENT} or
1075fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *            {@link Intent#ACTION_CREATE_DOCUMENT} request.
1085fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     */
1095fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    public static DocumentFile fromSingleUri(Context context, Uri singleUri) {
1105fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        final int version = Build.VERSION.SDK_INT;
1115fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        if (version >= 19) {
1125fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            return new SingleDocumentFile(null, context, singleUri);
1135fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        } else {
1145fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            return null;
1155fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        }
1165fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    }
1175fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
1185fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    /**
1195fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * Create a {@link DocumentFile} representing the document tree rooted at
1205fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * the given {@link Uri}. This is only useful on devices running
12195a62c18174e92eb2bf90b808cef5fd6f36ad944Dianne Hackborn     * {@link android.os.Build.VERSION_CODES#LOLLIPOP} or later, and will return
1225fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * {@code null} when called on earlier platform versions.
1235fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *
1245fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @param treeUri the {@link Intent#getData()} from a successful
1255fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *            {@link Intent#ACTION_OPEN_DOCUMENT_TREE} request.
1265fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     */
1275fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    public static DocumentFile fromTreeUri(Context context, Uri treeUri) {
1285fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        final int version = Build.VERSION.SDK_INT;
1295fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        if (version >= 21) {
1305fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            return new TreeDocumentFile(null, context,
1315fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                    DocumentsContractApi21.prepareTreeUri(treeUri));
1325fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        } else {
1335fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            return null;
1345fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        }
1355fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    }
1365fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
1375fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    /**
1385fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * Test if given Uri is backed by a
1395fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * {@link android.provider.DocumentsProvider}.
1405fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     */
1415fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    public static boolean isDocumentUri(Context context, Uri uri) {
1425fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        final int version = Build.VERSION.SDK_INT;
1435fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        if (version >= 19) {
1445fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            return DocumentsContractApi19.isDocumentUri(context, uri);
1455fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        } else {
1465fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            return false;
1475fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        }
1485fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    }
1495fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
1505fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    /**
1515fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * Create a new document as a direct child of this directory.
1525fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *
1535fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @param mimeType MIME type of new document, such as {@code image/png} or
1545fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *            {@code audio/flac}
1555fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @param displayName name of new document, without any file extension
1565fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *            appended; the underlying provider may choose to append the
1575fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *            extension
1585fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @return file representing newly created document, or null if failed
1595fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @throws UnsupportedOperationException when working with a single document
1605fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *             created from {@link #fromSingleUri(Context, Uri)}.
1615fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @see android.provider.DocumentsContract#createDocument(ContentResolver,
1625fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *      Uri, String, String)
1635fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     */
1645fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    public abstract DocumentFile createFile(String mimeType, String displayName);
1655fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
1665fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    /**
1675fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * Create a new directory as a direct child of this directory.
1685fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *
1695fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @param displayName name of new directory
1705fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @return file representing newly created directory, or null if failed
1715fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @throws UnsupportedOperationException when working with a single document
1725fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *             created from {@link #fromSingleUri(Context, Uri)}.
1735fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @see android.provider.DocumentsContract#createDocument(ContentResolver,
1745fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *      Uri, String, String)
1755fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     */
1765fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    public abstract DocumentFile createDirectory(String displayName);
1775fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
1785fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    /**
1795fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * Return a Uri for the underlying document represented by this file. This
1805fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * can be used with other platform APIs to manipulate or share the
1815fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * underlying content. You can use {@link #isDocumentUri(Context, Uri)} to
1825fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * test if the returned Uri is backed by a
1835fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * {@link android.provider.DocumentsProvider}.
1845fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *
1855fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @see Intent#setData(Uri)
1865fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @see Intent#setClipData(android.content.ClipData)
1875fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @see ContentResolver#openInputStream(Uri)
1885fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @see ContentResolver#openOutputStream(Uri)
1895fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @see ContentResolver#openFileDescriptor(Uri, String)
1905fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     */
1915fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    public abstract Uri getUri();
1925fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
1935fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    /**
1945fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * Return the display name of this document.
1955fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *
1965fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @see android.provider.DocumentsContract.Document#COLUMN_DISPLAY_NAME
1975fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     */
1985fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    public abstract String getName();
1995fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
2005fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    /**
2015fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * Return the MIME type of this document.
2025fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *
2035fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @see android.provider.DocumentsContract.Document#COLUMN_MIME_TYPE
2045fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     */
2055fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    public abstract String getType();
2065fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
2075fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    /**
2085fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * Return the parent file of this document. Only defined inside of the
2095fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * user-selected tree; you can never escape above the top of the tree.
2105fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * <p>
2115fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * The underlying {@link android.provider.DocumentsProvider} only defines a
2125fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * forward mapping from parent to child, so the reverse mapping of child to
2135fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * parent offered here is purely a convenience method, and it may be
2145fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * incorrect if the underlying tree structure changes.
2155fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     */
2165fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    public DocumentFile getParentFile() {
2175fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        return mParent;
2185fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    }
2195fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
2205fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    /**
2215fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * Indicates if this file represents a <em>directory</em>.
2225fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *
2235fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @return {@code true} if this file is a directory, {@code false}
2245fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *         otherwise.
2255fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @see android.provider.DocumentsContract.Document#MIME_TYPE_DIR
2265fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     */
2275fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    public abstract boolean isDirectory();
2285fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
2295fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    /**
2305fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * Indicates if this file represents a <em>file</em>.
2315fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *
2325fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @return {@code true} if this file is a file, {@code false} otherwise.
2335fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @see android.provider.DocumentsContract.Document#COLUMN_MIME_TYPE
2345fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     */
2355fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    public abstract boolean isFile();
2365fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
2375fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    /**
2385fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * Returns the time when this file was last modified, measured in
2395fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * milliseconds since January 1st, 1970, midnight. Returns 0 if the file
2405fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * does not exist, or if the modified time is unknown.
2415fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *
2425fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @return the time when this file was last modified.
2435fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @see android.provider.DocumentsContract.Document#COLUMN_LAST_MODIFIED
2445fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     */
2455fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    public abstract long lastModified();
2465fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
2475fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    /**
2485fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * Returns the length of this file in bytes. Returns 0 if the file does not
2495fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * exist, or if the length is unknown. The result for a directory is not
2505fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * defined.
2515fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *
2525fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @return the number of bytes in this file.
2535fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @see android.provider.DocumentsContract.Document#COLUMN_SIZE
2545fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     */
2555fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    public abstract long length();
2565fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
2575fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    /**
2585fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * Indicates whether the current context is allowed to read from this file.
2595fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *
2605fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @return {@code true} if this file can be read, {@code false} otherwise.
2615fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     */
2625fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    public abstract boolean canRead();
2635fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
2645fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    /**
2655fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * Indicates whether the current context is allowed to write to this file.
2665fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *
2675fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @return {@code true} if this file can be written, {@code false}
2685fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *         otherwise.
2695fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @see android.provider.DocumentsContract.Document#COLUMN_FLAGS
2705fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @see android.provider.DocumentsContract.Document#FLAG_SUPPORTS_DELETE
2715fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @see android.provider.DocumentsContract.Document#FLAG_SUPPORTS_WRITE
2725fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @see android.provider.DocumentsContract.Document#FLAG_DIR_SUPPORTS_CREATE
2735fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     */
2745fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    public abstract boolean canWrite();
2755fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
2765fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    /**
2775fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * Deletes this file.
2785fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * <p>
2795fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * Note that this method does <i>not</i> throw {@code IOException} on
2805fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * failure. Callers must check the return value.
2815fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *
2825fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @return {@code true} if this file was deleted, {@code false} otherwise.
2835fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @see android.provider.DocumentsContract#deleteDocument(ContentResolver,
2845fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *      Uri)
2855fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     */
2865fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    public abstract boolean delete();
2875fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
2885fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    /**
2895fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * Returns a boolean indicating whether this file can be found.
2905fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *
2915fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @return {@code true} if this file exists, {@code false} otherwise.
2925fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     */
2935fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    public abstract boolean exists();
2945fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
2955fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    /**
2965fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * Returns an array of files contained in the directory represented by this
2975fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * file.
2985fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *
2995fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @return an array of files or {@code null}.
3005fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @throws UnsupportedOperationException when working with a single document
3015fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *             created from {@link #fromSingleUri(Context, Uri)}.
3025fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @see android.provider.DocumentsContract#buildChildDocumentsUriUsingTree(Uri,
3035fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *      String)
3045fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     */
3055fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    public abstract DocumentFile[] listFiles();
3065fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
3075fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    /**
3085fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * Search through {@link #listFiles()} for the first document matching the
3095fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * given display name. Returns {@code null} when no matching document is
3105fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * found.
3115fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *
3125fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @throws UnsupportedOperationException when working with a single document
3135fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *             created from {@link #fromSingleUri(Context, Uri)}.
3145fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     */
3155fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    public DocumentFile findFile(String displayName) {
3165fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        for (DocumentFile doc : listFiles()) {
3175fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            if (displayName.equals(doc.getName())) {
3185fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                return doc;
3195fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            }
3205fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        }
3215fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        return null;
3225fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    }
3235fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
3245fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    /**
3255fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * Renames this file to {@code displayName}.
3265fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * <p>
3275fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * Note that this method does <i>not</i> throw {@code IOException} on
3285fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * failure. Callers must check the return value.
3295fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * <p>
3305fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * Some providers may need to create a new document to reflect the rename,
3315fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * potentially with a different MIME type, so {@link #getUri()} and
3325fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * {@link #getType()} may change to reflect the rename.
3335fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * <p>
3345fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * When renaming a directory, children previously enumerated through
3355fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * {@link #listFiles()} may no longer be valid.
3365fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *
3375fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @param displayName the new display name.
3385fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @return true on success.
3395fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @throws UnsupportedOperationException when working with a single document
3405fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *             created from {@link #fromSingleUri(Context, Uri)}.
3415fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     * @see android.provider.DocumentsContract#renameDocument(ContentResolver,
3425fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     *      Uri, String)
3435fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey     */
3445fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    public abstract boolean renameTo(String displayName);
3455fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey}
346