DocumentsContract.java revision bd3b902567b09379e1b62c60b3319ad82102efad
123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck/* 223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * Copyright (C) 2013 The Android Open Source Project 323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * 423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * Licensed under the Apache License, Version 2.0 (the "License"); 523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * you may not use this file except in compliance with the License. 623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * You may obtain a copy of the License at 723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * 823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * http://www.apache.org/licenses/LICENSE-2.0 923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * 1023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * Unless required by applicable law or agreed to in writing, software 1123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * distributed under the License is distributed on an "AS IS" BASIS, 1223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * See the License for the specific language governing permissions and 1423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * limitations under the License. 1523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck */ 1623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck 1738e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reckpackage android.provider; 1823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck 1923b797ab5151eb2474f3bdd679f2f07bfd723042John Reckimport android.content.ContentProvider; 20d04794a9a3f9edc8b7ca336175d66eb81a8f55faJohn Reckimport android.content.ContentResolver; 21d04794a9a3f9edc8b7ca336175d66eb81a8f55faJohn Reckimport android.content.ContentValues; 22d04794a9a3f9edc8b7ca336175d66eb81a8f55faJohn Reckimport android.content.Context; 233b20251a355c88193c439f928a84ae69483fb488John Reckimport android.content.Intent; 240b7e8245db728d127ada698be63d78b33fc6e4daChris Craikimport android.content.pm.PackageManager; 25d04794a9a3f9edc8b7ca336175d66eb81a8f55faJohn Reckimport android.content.pm.ProviderInfo; 26d04794a9a3f9edc8b7ca336175d66eb81a8f55faJohn Reckimport android.content.res.AssetFileDescriptor; 27d04794a9a3f9edc8b7ca336175d66eb81a8f55faJohn Reckimport android.database.Cursor; 284f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckimport android.graphics.Bitmap; 29dccca44ffda4836b56a21da95a046c9708ffd49csergeyvimport android.graphics.BitmapFactory; 30d04794a9a3f9edc8b7ca336175d66eb81a8f55faJohn Reckimport android.graphics.Point; 31d04794a9a3f9edc8b7ca336175d66eb81a8f55faJohn Reckimport android.net.Uri; 32e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reckimport android.os.Bundle; 339372ac3621848085e77b867f220c0b5ffce4010dJohn Reckimport android.os.ParcelFileDescriptor; 34e486d932ca5a10446a3c98d6d065213913277268John Reckimport android.os.ParcelFileDescriptor.OnCloseListener; 3523b797ab5151eb2474f3bdd679f2f07bfd723042John Reckimport android.util.Log; 36240ff6246a29602539fd0295274e1c769e743a2eJohn Reck 37e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reckimport com.google.android.collect.Lists; 3865fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik 39e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reckimport libcore.io.IoUtils; 40e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck 41e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reckimport java.io.FileDescriptor; 42e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reckimport java.io.IOException; 43e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reckimport java.util.List; 4465fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik 45290b23a1e11d532b39098bb58693ef97ba98a622Colin Cross/** 46290b23a1e11d532b39098bb58693ef97ba98a622Colin Cross * Defines the contract between a documents provider and the platform. 47f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck * <p> 48f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck * A document provider is a {@link ContentProvider} that presents a set of 49f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck * documents in a hierarchical structure. The system provides UI that visualizes 50e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck * all available document providers, offering users the ability to open existing 51e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck * documents or create new documents. 52149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck * <p> 53149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck * Each provider expresses one or more "roots" which each serve as the top-level 54149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck * of a tree. For example, a root could represent an account, or a physical 55149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck * storage device. Under each root, documents are referenced by a unique 56149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck * {@link DocumentColumns#DOC_ID}, and each root starts at the 57149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck * {@link Documents#DOC_ID_ROOT} document. 58149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck * <p> 59149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck * Documents can be either an openable file (with a specific MIME type), or a 6023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * directory containing additional documents (with the 6123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * {@link Documents#MIME_TYPE_DIR} MIME type). Each document can have different 6223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * capabilities, as described by {@link DocumentColumns#FLAGS}. The same 6323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * {@link DocumentColumns#DOC_ID} can be included in multiple directories. 64119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck * <p> 65119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck * Document providers must be protected with the 663b20251a355c88193c439f928a84ae69483fb488John Reck * {@link android.Manifest.permission#MANAGE_DOCUMENTS} permission, which can 673b20251a355c88193c439f928a84ae69483fb488John Reck * only be requested by the system. The system-provided UI then issues narrow 684f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck * Uri permission grants for individual documents when the user explicitly picks 6951d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik * documents. 704c9e59d03c2bca38001225b79d01740b8999adfbJohn Reck * 71ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * @see Intent#ACTION_OPEN_DOCUMENT 72b816087962aba0019b022303330f03b897b580edSkuhne * @see Intent#ACTION_CREATE_DOCUMENT 73ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne */ 74443a714fa7c0dd07fee3527cc5bc3d3ca1fb7d44John Reckpublic final class DocumentsContract { 75b36016c65f1d1b5846dba0349aab491dbd3a746aJohn Reck private static final String TAG = "Documents"; 7623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck 7723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck // content://com.example/roots/ 7823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck // content://com.example/roots/sdcard/ 7951f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck // content://com.example/roots/sdcard/docs/0/ 80443a714fa7c0dd07fee3527cc5bc3d3ca1fb7d44John Reck // content://com.example/roots/sdcard/docs/0/contents/ 814f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck // content://com.example/roots/sdcard/docs/0/search/?query=pony 824f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck 8351f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck /** {@hide} */ 8417035b0211a3c9d45ea46a99217a6acbe76e8fbeJohn Reck public static final String META_DATA_DOCUMENT_PROVIDER = "android.content.DOCUMENT_PROVIDER"; 85d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik 8651f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck /** {@hide} */ 8751f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck public static final String ACTION_DOCUMENT_CHANGED = "android.provider.action.DOCUMENT_CHANGED"; 88e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck 896246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik /** 904f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck * Constants for individual documents. 914f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck */ 92d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik public static class Documents { 934f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck private Documents() { 946246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 9523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck 9623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck /** 97f648108f83d4e74811919e9811efb8fcc184b8a3John Reck * MIME type of a document which is a directory that may contain additional 98fbc8df03e498baf47ff1a5e05e182f1bcd60c770John Reck * documents. 99fbc8df03e498baf47ff1a5e05e182f1bcd60c770John Reck * 100f648108f83d4e74811919e9811efb8fcc184b8a3John Reck * @see #buildContentsUri(String, String, String) 101a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck */ 10223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck public static final String MIME_TYPE_DIR = "vnd.android.cursor.dir/doc"; 1033b20251a355c88193c439f928a84ae69483fb488John Reck 10423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck /** 10523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * {@link DocumentColumns#DOC_ID} value representing the root directory of a 10623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * documents root. 107f648108f83d4e74811919e9811efb8fcc184b8a3John Reck */ 108f648108f83d4e74811919e9811efb8fcc184b8a3John Reck public static final String DOC_ID_ROOT = "0"; 10923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck 11023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck /** 11128912a508493e583c48772e2a234e0ed66849490John Reck * Flag indicating that a document is a directory that supports creation of 11228912a508493e583c48772e2a234e0ed66849490John Reck * new files within it. 11323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * 1141125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck * @see DocumentColumns#FLAGS 1151125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck * @see #createDocument(ContentResolver, Uri, String, String) 1164f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck */ 117e486d932ca5a10446a3c98d6d065213913277268John Reck public static final int FLAG_SUPPORTS_CREATE = 1; 118368cdd85268999997fb495cf90c4417221797de0John Reck 119368cdd85268999997fb495cf90c4417221797de0John Reck /** 1204f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck * Flag indicating that a document is renamable. 1214f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck * 1224f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck * @see DocumentColumns#FLAGS 1231125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck * @see #renameDocument(ContentResolver, Uri, String) 1241125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck */ 1251125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck public static final int FLAG_SUPPORTS_RENAME = 1 << 1; 1261125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck 127f648108f83d4e74811919e9811efb8fcc184b8a3John Reck /** 128f648108f83d4e74811919e9811efb8fcc184b8a3John Reck * Flag indicating that a document is deletable. 129b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * 1300bcd0cb6b1193168fa2840855195347488daab9eThomas Buhot * @see DocumentColumns#FLAGS 1313b20251a355c88193c439f928a84ae69483fb488John Reck */ 1324f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck public static final int FLAG_SUPPORTS_DELETE = 1 << 2; 133b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 1344f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck /** 1354f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck * Flag indicating that a document can be represented as a thumbnail. 136f648108f83d4e74811919e9811efb8fcc184b8a3John Reck * 137f648108f83d4e74811919e9811efb8fcc184b8a3John Reck * @see DocumentColumns#FLAGS 138f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck * @see #getThumbnail(ContentResolver, Uri, Point) 139f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck */ 140f648108f83d4e74811919e9811efb8fcc184b8a3John Reck public static final int FLAG_SUPPORTS_THUMBNAIL = 1 << 3; 14101a5ea35fbba4c5bb1d7790ae1677a2fa752e042John Reck 1424f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck /** 1434f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck * Flag indicating that a document is a directory that supports search. 1448afcc76920499d0a384dba1470c5a377f80ed768John Reck * 1458afcc76920499d0a384dba1470c5a377f80ed768John Reck * @see DocumentColumns#FLAGS 1468afcc76920499d0a384dba1470c5a377f80ed768John Reck */ 1478afcc76920499d0a384dba1470c5a377f80ed768John Reck public static final int FLAG_SUPPORTS_SEARCH = 1 << 4; 1488afcc76920499d0a384dba1470c5a377f80ed768John Reck 1498afcc76920499d0a384dba1470c5a377f80ed768John Reck /** 1508afcc76920499d0a384dba1470c5a377f80ed768John Reck * Flag indicating that a document is writable. 1518afcc76920499d0a384dba1470c5a377f80ed768John Reck * 152306f331f91a86da271ce30d4f14d6badf0d25704John Reck * @see DocumentColumns#FLAGS 153306f331f91a86da271ce30d4f14d6badf0d25704John Reck */ 1548afcc76920499d0a384dba1470c5a377f80ed768John Reck public static final int FLAG_SUPPORTS_WRITE = 1 << 5; 1558afcc76920499d0a384dba1470c5a377f80ed768John Reck 1568afcc76920499d0a384dba1470c5a377f80ed768John Reck /** 1578afcc76920499d0a384dba1470c5a377f80ed768John Reck * Flag indicating that a document is a directory that prefers its contents 158284b24358410cb0200e525a5ba36994090c83f20Chris Craik * be shown in a larger format grid. Usually suitable when a directory 15950210d912925aef14e4ce69be82e4949122a3cd9Alan Viverette * contains mostly pictures. 16064bb413a664001c95c8439cf097dc3033f4ed733Andreas Gampe * 16198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik * @see DocumentColumns#FLAGS 1626e068c0182f6f85bccb855a647510724d1c65a13Chris Craik */ 16398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik public static final int FLAG_PREFERS_GRID = 1 << 6; 16498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 16598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 1664f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck /** 16750210d912925aef14e4ce69be82e4949122a3cd9Alan Viverette * Optimal dimensions for a document thumbnail request, stored as a 16898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik * {@link Point} object. This is only a hint, and the returned thumbnail may 16950210d912925aef14e4ce69be82e4949122a3cd9Alan Viverette * have different dimensions. 17050210d912925aef14e4ce69be82e4949122a3cd9Alan Viverette * 17150210d912925aef14e4ce69be82e4949122a3cd9Alan Viverette * @see ContentProvider#openTypedAssetFile(Uri, String, Bundle) 17298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik */ 1736e068c0182f6f85bccb855a647510724d1c65a13Chris Craik public static final String EXTRA_THUMBNAIL_SIZE = "thumbnail_size"; 17498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 17550210d912925aef14e4ce69be82e4949122a3cd9Alan Viverette /** 17650210d912925aef14e4ce69be82e4949122a3cd9Alan Viverette * Extra boolean flag included in a directory {@link Cursor#getExtras()} 17798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik * indicating that the document provider can provide additional data if 1784f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck * requested, such as additional search results. 1794f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck */ 18063a06673253914510bbeebd500655008682dade1John Reck public static final String EXTRA_HAS_MORE = "has_more"; 18163a06673253914510bbeebd500655008682dade1John Reck 18263a06673253914510bbeebd500655008682dade1John Reck /** 18363a06673253914510bbeebd500655008682dade1John Reck * Extra boolean flag included in a {@link Cursor#respond(Bundle)} call to a 1848afcc76920499d0a384dba1470c5a377f80ed768John Reck * directory to request that additional data should be fetched. When 1858afcc76920499d0a384dba1470c5a377f80ed768John Reck * requested data is ready, the provider should send a change notification 1868afcc76920499d0a384dba1470c5a377f80ed768John Reck * to cause a requery. 187dbc9a86d05e5e835051de22f6cb30ec1921e9705John Reck * 188dbc9a86d05e5e835051de22f6cb30ec1921e9705John Reck * @see Cursor#respond(Bundle) 189f2dcc2aecb94e726096256c47b913ed0a57ae7e2John Reck * @see ContentResolver#notifyChange(Uri, android.database.ContentObserver, 190f2dcc2aecb94e726096256c47b913ed0a57ae7e2John Reck * boolean) 191f2dcc2aecb94e726096256c47b913ed0a57ae7e2John Reck */ 192f2dcc2aecb94e726096256c47b913ed0a57ae7e2John Reck public static final String EXTRA_REQUEST_MORE = "request_more"; 193f2dcc2aecb94e726096256c47b913ed0a57ae7e2John Reck 1948afcc76920499d0a384dba1470c5a377f80ed768John Reck private static final String PATH_ROOTS = "roots"; 195860d155f866cc15a725e7ce03763280987f24901John Reck private static final String PATH_DOCS = "docs"; 196860d155f866cc15a725e7ce03763280987f24901John Reck private static final String PATH_CONTENTS = "contents"; 197bf3c602284f9a344faf185c3a5e94a264ba44c4fJohn Reck private static final String PATH_SEARCH = "search"; 1981b54fb27ac48495ed0b33868fda5776fb49fe0f3Chris Craik 199bf3c602284f9a344faf185c3a5e94a264ba44c4fJohn Reck private static final String PARAM_QUERY = "query"; 200bf3c602284f9a344faf185c3a5e94a264ba44c4fJohn Reck private static final String PARAM_LOCAL_ONLY = "localOnly"; 201ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 202ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne /** 203f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck * Build Uri representing the roots offered by a document provider. 20418f16e6fba74eda173e1e7c869e6e2e2acc073ffJohn Reck */ 205bf3c602284f9a344faf185c3a5e94a264ba44c4fJohn Reck public static Uri buildRootsUri(String authority) { 206bf3c602284f9a344faf185c3a5e94a264ba44c4fJohn Reck return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) 207bf3c602284f9a344faf185c3a5e94a264ba44c4fJohn Reck .authority(authority).appendPath(PATH_ROOTS).build(); 208bf3c602284f9a344faf185c3a5e94a264ba44c4fJohn Reck } 209bf3c602284f9a344faf185c3a5e94a264ba44c4fJohn Reck 210ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck /** 211be3fba05e823f740f65b2679929347dc3dd282adJohn Reck * Build Uri representing a specific root offered by a document provider. 212ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck */ 213ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck public static Uri buildRootUri(String authority, String rootId) { 214e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) 2150b7e8245db728d127ada698be63d78b33fc6e4daChris Craik .authority(authority).appendPath(PATH_ROOTS).appendPath(rootId).build(); 2160b7e8245db728d127ada698be63d78b33fc6e4daChris Craik } 2170b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 21825fbb3fa1138675379102a44405852555cefccbdJohn Reck /** 2190b7e8245db728d127ada698be63d78b33fc6e4daChris Craik * Build Uri representing the given {@link DocumentColumns#DOC_ID} in a 22000e79c9947b741194ff6c0d08ede9b3befbf9c9dJohn Reck * document provider. 221ec845a215e343cdb3b2e4c7b6aff7b24beb0236bJohn Reck */ 222ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne public static Uri buildDocumentUri(String authority, String rootId, String docId) { 223ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(authority) 224ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne .appendPath(PATH_ROOTS).appendPath(rootId).appendPath(PATH_DOCS).appendPath(docId) 225ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne .build(); 226ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 227ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 228975591a7af883d866d86ab819e164c6004694744John Reck /** 229ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * Build Uri representing the contents of the given directory in a document 230119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck * provider. The given document must be {@link Documents#MIME_TYPE_DIR}. 231975591a7af883d866d86ab819e164c6004694744John Reck */ 232e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck public static Uri buildContentsUri(String authority, String rootId, String docId) { 23351f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(authority) 234975591a7af883d866d86ab819e164c6004694744John Reck .appendPath(PATH_ROOTS).appendPath(rootId).appendPath(PATH_DOCS).appendPath(docId) 235998a6d81896df8b662cc10ddeb35087b78b38d72John Reck .appendPath(PATH_CONTENTS).build(); 236306f331f91a86da271ce30d4f14d6badf0d25704John Reck } 237306f331f91a86da271ce30d4f14d6badf0d25704John Reck 238f648108f83d4e74811919e9811efb8fcc184b8a3John Reck /** 2391b54fb27ac48495ed0b33868fda5776fb49fe0f3Chris Craik * Build Uri representing a search for matching documents under a specific 240aa95a88327d9a3ac8a4a00b065b78ac0f28b3a19John Reck * directory in a document provider. The given document must have 241aa95a88327d9a3ac8a4a00b065b78ac0f28b3a19John Reck * {@link Documents#FLAG_SUPPORTS_SEARCH}. 242aa95a88327d9a3ac8a4a00b065b78ac0f28b3a19John Reck */ 243aa95a88327d9a3ac8a4a00b065b78ac0f28b3a19John Reck public static Uri buildSearchUri(String authority, String rootId, String docId, String query) { 244e486d932ca5a10446a3c98d6d065213913277268John Reck return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(authority) 245e486d932ca5a10446a3c98d6d065213913277268John Reck .appendPath(PATH_ROOTS).appendPath(rootId).appendPath(PATH_DOCS).appendPath(docId) 246e486d932ca5a10446a3c98d6d065213913277268John Reck .appendPath(PATH_SEARCH).appendQueryParameter(PARAM_QUERY, query).build(); 24752b783f76af58a948dad4d3b4d1b7ad7979347ceJohn Reck } 248e486d932ca5a10446a3c98d6d065213913277268John Reck 249e486d932ca5a10446a3c98d6d065213913277268John Reck /** 250e486d932ca5a10446a3c98d6d065213913277268John Reck * Convenience method for {@link #buildDocumentUri(String, String, String)}, 251e486d932ca5a10446a3c98d6d065213913277268John Reck * extracting authority and root from the given Uri. 252e486d932ca5a10446a3c98d6d065213913277268John Reck */ 253e486d932ca5a10446a3c98d6d065213913277268John Reck public static Uri buildDocumentUri(Uri relatedUri, String docId) { 254e486d932ca5a10446a3c98d6d065213913277268John Reck return buildDocumentUri(relatedUri.getAuthority(), getRootId(relatedUri), docId); 255e486d932ca5a10446a3c98d6d065213913277268John Reck } 256e486d932ca5a10446a3c98d6d065213913277268John Reck 257e486d932ca5a10446a3c98d6d065213913277268John Reck /** 258e486d932ca5a10446a3c98d6d065213913277268John Reck * Convenience method for {@link #buildContentsUri(String, String, String)}, 259e486d932ca5a10446a3c98d6d065213913277268John Reck * extracting authority and root from the given Uri. 260e486d932ca5a10446a3c98d6d065213913277268John Reck */ 261f648108f83d4e74811919e9811efb8fcc184b8a3John Reck public static Uri buildContentsUri(Uri relatedUri) { 262f648108f83d4e74811919e9811efb8fcc184b8a3John Reck return buildContentsUri( 263f648108f83d4e74811919e9811efb8fcc184b8a3John Reck relatedUri.getAuthority(), getRootId(relatedUri), getDocId(relatedUri)); 264e486d932ca5a10446a3c98d6d065213913277268John Reck } 265e486d932ca5a10446a3c98d6d065213913277268John Reck 266e486d932ca5a10446a3c98d6d065213913277268John Reck /** 267e486d932ca5a10446a3c98d6d065213913277268John Reck * Convenience method for 268e486d932ca5a10446a3c98d6d065213913277268John Reck * {@link #buildSearchUri(String, String, String, String)}, extracting 269a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck * authority and root from the given Uri. 270aef9dc8d186bd5f78068ab2d5240b5e9c8ab44b6John Reck */ 2711b54fb27ac48495ed0b33868fda5776fb49fe0f3Chris Craik public static Uri buildSearchUri(Uri relatedUri, String query) { 272aef9dc8d186bd5f78068ab2d5240b5e9c8ab44b6John Reck return buildSearchUri( 273aef9dc8d186bd5f78068ab2d5240b5e9c8ab44b6John Reck relatedUri.getAuthority(), getRootId(relatedUri), getDocId(relatedUri), query); 274a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck } 275cd028f336e36b22dbe8cf623eb5bd2361314495cJohn Reck 276f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck /** 277f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck * Extract the {@link RootColumns#ROOT_ID} from the given Uri. 278f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck */ 279f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck public static String getRootId(Uri documentUri) { 280e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck final List<String> paths = documentUri.getPathSegments(); 281e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck if (paths.size() < 2) { 282e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck throw new IllegalArgumentException("Not a root: " + documentUri); 283f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck } 284f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck if (!PATH_ROOTS.equals(paths.get(0))) { 285f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck throw new IllegalArgumentException("Not a root: " + documentUri); 286f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck } 287a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck return paths.get(1); 288a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck } 289a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck 290a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck /** 291a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck * Extract the {@link DocumentColumns#DOC_ID} from the given Uri. 292e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck */ 293b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik public static String getDocId(Uri documentUri) { 2944f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck final List<String> paths = documentUri.getPathSegments(); 295a7090e0cfd7c719a6d4c03aae34f5db98754cbddChris Craik if (paths.size() < 4) { 296b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik throw new IllegalArgumentException("Not a document: " + documentUri); 2974f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck } 298e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck if (!PATH_ROOTS.equals(paths.get(0))) { 299e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck throw new IllegalArgumentException("Not a document: " + documentUri); 300e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck } 3016d4d0db312fa8a9fce629dd92aa133c6f8249cf8John Reck if (!PATH_DOCS.equals(paths.get(2))) { 3026d4d0db312fa8a9fce629dd92aa133c6f8249cf8John Reck throw new IllegalArgumentException("Not a document: " + documentUri); 3036d4d0db312fa8a9fce629dd92aa133c6f8249cf8John Reck } 3046d4d0db312fa8a9fce629dd92aa133c6f8249cf8John Reck return paths.get(3); 3056d4d0db312fa8a9fce629dd92aa133c6f8249cf8John Reck } 306240ff6246a29602539fd0295274e1c769e743a2eJohn Reck 307240ff6246a29602539fd0295274e1c769e743a2eJohn Reck /** 308240ff6246a29602539fd0295274e1c769e743a2eJohn Reck * Return requested search query from the given Uri, as constructed by 309149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck * {@link #buildSearchUri(String, String, String, String)}. 310b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik */ 31177c40109cf25d29f85ee6c13aeb96e22e55f33abJohn Reck public static String getSearchQuery(Uri documentUri) { 31264e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik return documentUri.getQueryParameter(PARAM_QUERY); 313e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck } 31477c40109cf25d29f85ee6c13aeb96e22e55f33abJohn Reck 31577c40109cf25d29f85ee6c13aeb96e22e55f33abJohn Reck /** 316149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck * Mark the given Uri to indicate that only locally-available data should be 317149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck * returned. That is, no network connections should be initiated to provide 318e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck * the metadata or content. 319fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck */ 320149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck public static Uri setLocalOnly(Uri documentUri) { 3210a97330b98dd633b58dcfff405d94476c89e867dJohn Reck return documentUri.buildUpon() 322149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck .appendQueryParameter(PARAM_LOCAL_ONLY, String.valueOf(true)).build(); 3230a97330b98dd633b58dcfff405d94476c89e867dJohn Reck } 3240a97330b98dd633b58dcfff405d94476c89e867dJohn Reck 325e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck /** 3264f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck * Return if the given Uri is requesting that only locally-available data be 3274f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck * returned. That is, no network connections should be initiated to provide 328149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck * the metadata or content. 329149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck */ 33013d1b4ab10fbee5e81a2ba1ac59cfae1e51d3ef0Season Li public static boolean isLocalOnly(Uri documentUri) { 33113d1b4ab10fbee5e81a2ba1ac59cfae1e51d3ef0Season Li return documentUri.getBooleanQueryParameter(PARAM_LOCAL_ONLY, false); 332149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck } 333149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck 334149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck /** 335149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck * Standard columns for document queries. Document providers <em>must</em> 336149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck * support at least these columns when queried. 337149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck * 338149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck * @see DocumentsContract#buildDocumentUri(String, String, String) 339149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck * @see DocumentsContract#buildContentsUri(String, String, String) 340149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck * @see DocumentsContract#buildSearchUri(String, String, String, String) 341149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck */ 342e486d932ca5a10446a3c98d6d065213913277268John Reck public interface DocumentColumns extends OpenableColumns { 343149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck /** 344149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck * The ID for a document under a storage backend root. Values 345149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck * <em>must</em> never change once returned. This field is read-only to 346149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck * document clients. 347149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck * <p> 348149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck * Type: STRING 349149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck */ 350e486d932ca5a10446a3c98d6d065213913277268John Reck public static final String DOC_ID = "doc_id"; 351e486d932ca5a10446a3c98d6d065213913277268John Reck 352e486d932ca5a10446a3c98d6d065213913277268John Reck /** 353149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck * MIME type of a document, matching the value returned by 354149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck * {@link ContentResolver#getType(android.net.Uri)}. This field must be 3554f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck * provided when a new document is created. This field is read-only to 3564f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck * document clients. 357149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck * <p> 358ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik * Type: STRING 359ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik * 3603a5811b50157e7ba50854caf957e806aee794d39Chris Craik * @see Documents#MIME_TYPE_DIR 3619cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik */ 3629cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik public static final String MIME_TYPE = "mime_type"; 3639cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 3640b7e8245db728d127ada698be63d78b33fc6e4daChris Craik /** 3659cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik * Timestamp when a document was last modified, in milliseconds since 3669cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik * January 1, 1970 00:00:00.0 UTC. This field is read-only to document 3679cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik * clients. Document providers can update this field using events from 3681dfa0704964c17e45775b9e01f1fa0b1a10774f7Chris Craik * {@link OnCloseListener} or other reliable 36998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik * {@link ParcelFileDescriptor} transport. 370f158b49c888f722194afe5a80539a2b020c130bcChris Craik * <p> 3711dfa0704964c17e45775b9e01f1fa0b1a10774f7Chris Craik * Type: INTEGER (long) 3725854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * 373ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik * @see System#currentTimeMillis() 3741dfa0704964c17e45775b9e01f1fa0b1a10774f7Chris Craik */ 3751dfa0704964c17e45775b9e01f1fa0b1a10774f7Chris Craik public static final String LAST_MODIFIED = "last_modified"; 3761dfa0704964c17e45775b9e01f1fa0b1a10774f7Chris Craik 3771dfa0704964c17e45775b9e01f1fa0b1a10774f7Chris Craik /** 3781dfa0704964c17e45775b9e01f1fa0b1a10774f7Chris Craik * Flags that apply to a specific document. This field is read-only to 3791dfa0704964c17e45775b9e01f1fa0b1a10774f7Chris Craik * document clients. 3801dfa0704964c17e45775b9e01f1fa0b1a10774f7Chris Craik * <p> 3811dfa0704964c17e45775b9e01f1fa0b1a10774f7Chris Craik * Type: INTEGER (int) 3821dfa0704964c17e45775b9e01f1fa0b1a10774f7Chris Craik */ 3831dfa0704964c17e45775b9e01f1fa0b1a10774f7Chris Craik public static final String FLAGS = "flags"; 3841dfa0704964c17e45775b9e01f1fa0b1a10774f7Chris Craik 3851dfa0704964c17e45775b9e01f1fa0b1a10774f7Chris Craik /** 3861dfa0704964c17e45775b9e01f1fa0b1a10774f7Chris Craik * Summary for this document, or {@code null} to omit. This field is 387ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik * read-only to document clients. 38864e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik * <p> 38964e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik * Type: STRING 390149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck */ 3914f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck public static final String SUMMARY = "summary"; 392b6c2624c8d9ee71d1c8d0aaf8082f92bb84b1418Robert Carr } 393b6c2624c8d9ee71d1c8d0aaf8082f92bb84b1418Robert Carr 394b816087962aba0019b022303330f03b897b580edSkuhne /** 395b6c2624c8d9ee71d1c8d0aaf8082f92bb84b1418Robert Carr * Constants for individual document roots. 396ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne */ 397ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne public static class Roots { 398b6c2624c8d9ee71d1c8d0aaf8082f92bb84b1418Robert Carr private Roots() { 399b6c2624c8d9ee71d1c8d0aaf8082f92bb84b1418Robert Carr } 400b6c2624c8d9ee71d1c8d0aaf8082f92bb84b1418Robert Carr 401b6c2624c8d9ee71d1c8d0aaf8082f92bb84b1418Robert Carr public static final String MIME_TYPE_DIR = "vnd.android.cursor.dir/root"; 402b6c2624c8d9ee71d1c8d0aaf8082f92bb84b1418Robert Carr public static final String MIME_TYPE_ITEM = "vnd.android.cursor.item/root"; 403ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 404b816087962aba0019b022303330f03b897b580edSkuhne /** 405b816087962aba0019b022303330f03b897b580edSkuhne * Root that represents a storage service, such as a cloud-based 406b816087962aba0019b022303330f03b897b580edSkuhne * service. 407b816087962aba0019b022303330f03b897b580edSkuhne * 408ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * @see RootColumns#ROOT_TYPE 409b6c2624c8d9ee71d1c8d0aaf8082f92bb84b1418Robert Carr */ 410ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne public static final int ROOT_TYPE_SERVICE = 1; 411ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 412ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne /** 413b816087962aba0019b022303330f03b897b580edSkuhne * Root that represents a shortcut to content that may be available 414b816087962aba0019b022303330f03b897b580edSkuhne * elsewhere through another storage root. 415ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * 416ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * @see RootColumns#ROOT_TYPE 417ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne */ 418b816087962aba0019b022303330f03b897b580edSkuhne public static final int ROOT_TYPE_SHORTCUT = 2; 419b816087962aba0019b022303330f03b897b580edSkuhne 420b816087962aba0019b022303330f03b897b580edSkuhne /** 421b816087962aba0019b022303330f03b897b580edSkuhne * Root that represents a physical storage device. 422b816087962aba0019b022303330f03b897b580edSkuhne * 423ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * @see RootColumns#ROOT_TYPE 424ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne */ 425b816087962aba0019b022303330f03b897b580edSkuhne public static final int ROOT_TYPE_DEVICE = 3; 426ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik 427ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne /** 428b816087962aba0019b022303330f03b897b580edSkuhne * Root that represents a physical storage device that should only be 429eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita * displayed to advanced users. 430ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * 431b816087962aba0019b022303330f03b897b580edSkuhne * @see RootColumns#ROOT_TYPE 432ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne */ 433ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne public static final int ROOT_TYPE_DEVICE_ADVANCED = 4; 434ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 435ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 436b816087962aba0019b022303330f03b897b580edSkuhne /** 437ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * Standard columns for document root queries. 438ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * 439ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * @see DocumentsContract#buildRootsUri(String) 440b816087962aba0019b022303330f03b897b580edSkuhne * @see DocumentsContract#buildRootUri(String, String) 441ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne */ 442eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita public interface RootColumns { 443b816087962aba0019b022303330f03b897b580edSkuhne public static final String ROOT_ID = "root_id"; 444ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 445ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne /** 446ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * Storage root type, use for clustering. This field is read-only to 447ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * document clients. 448ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * <p> 449b816087962aba0019b022303330f03b897b580edSkuhne * Type: INTEGER (int) 450ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * 451ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * @see Roots#ROOT_TYPE_SERVICE 452ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * @see Roots#ROOT_TYPE_DEVICE 453b816087962aba0019b022303330f03b897b580edSkuhne */ 454ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne public static final String ROOT_TYPE = "root_type"; 455eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita 456ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne /** 457b816087962aba0019b022303330f03b897b580edSkuhne * Icon resource ID for this storage root, or {@code null} to use the 458ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * default {@link ProviderInfo#icon}. This field is read-only to 459ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * document clients. 460ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * <p> 461ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * Type: INTEGER (int) 462b816087962aba0019b022303330f03b897b580edSkuhne */ 463ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne public static final String ICON = "icon"; 464ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 465ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne /** 466b816087962aba0019b022303330f03b897b580edSkuhne * Title for this storage root, or {@code null} to use the default 467ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * {@link ProviderInfo#labelRes}. This field is read-only to document 468eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita * clients. 469b816087962aba0019b022303330f03b897b580edSkuhne * <p> 470ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * Type: STRING 471ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne */ 472ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne public static final String TITLE = "title"; 473ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 474ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne /** 475ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * Summary for this storage root, or {@code null} to omit. This field is 476ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * read-only to document clients. 477eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita * <p> 478b816087962aba0019b022303330f03b897b580edSkuhne * Type: STRING 479b816087962aba0019b022303330f03b897b580edSkuhne */ 480b816087962aba0019b022303330f03b897b580edSkuhne public static final String SUMMARY = "summary"; 481b816087962aba0019b022303330f03b897b580edSkuhne 482b816087962aba0019b022303330f03b897b580edSkuhne /** 483b816087962aba0019b022303330f03b897b580edSkuhne * Number of free bytes of available in this storage root, or 484b816087962aba0019b022303330f03b897b580edSkuhne * {@code null} if unknown or unbounded. This field is read-only to 485b816087962aba0019b022303330f03b897b580edSkuhne * document clients. 486b6c2624c8d9ee71d1c8d0aaf8082f92bb84b1418Robert Carr * <p> 487b816087962aba0019b022303330f03b897b580edSkuhne * Type: INTEGER (long) 488b816087962aba0019b022303330f03b897b580edSkuhne */ 489ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne public static final String AVAILABLE_BYTES = "available_bytes"; 490ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne } 491ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne 492ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne /** 493ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * Return list of all documents that the calling package has "open." These 494ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * are Uris matching {@link DocumentsContract} to which persistent 495ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * read/write access has been granted, usually through 496ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * {@link Intent#ACTION_OPEN_DOCUMENT} or 4974f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck * {@link Intent#ACTION_CREATE_DOCUMENT}. 498fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck * 4994f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck * @see Context#grantUriPermission(String, Uri, int) 500107843de4507b3511006cb9c77b8d0364374385aTom Hudson * @see ContentResolver#getIncomingUriPermissionGrants(int, int) 501ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik */ 5029372ac3621848085e77b867f220c0b5ffce4010dJohn Reck public static Uri[] getOpenDocuments(Context context) { 50338f6c034d153bb648d45bce09d80a69ba3e03360John Reck final int openedFlags = Intent.FLAG_GRANT_READ_URI_PERMISSION 50438f6c034d153bb648d45bce09d80a69ba3e03360John Reck | Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_PERSIST_GRANT_URI_PERMISSION; 505975591a7af883d866d86ab819e164c6004694744John Reck final Uri[] uris = context.getContentResolver() 5069372ac3621848085e77b867f220c0b5ffce4010dJohn Reck .getIncomingUriPermissionGrants(openedFlags, openedFlags); 507ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck 508ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck // Filter to only include document providers 509ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck final PackageManager pm = context.getPackageManager(); 510306f331f91a86da271ce30d4f14d6badf0d25704John Reck final List<Uri> result = Lists.newArrayList(); 511ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck for (Uri uri : uris) { 512c96955d9bb997b51be5fa929b5a67349d0459c3aJohn Reck final ProviderInfo info = pm.resolveContentProvider( 513149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck uri.getAuthority(), PackageManager.GET_META_DATA); 514149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck if (info.metaData.containsKey(META_DATA_DOCUMENT_PROVIDER)) { 515149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck result.add(uri); 516e486d932ca5a10446a3c98d6d065213913277268John Reck } 517e486d932ca5a10446a3c98d6d065213913277268John Reck } 518e486d932ca5a10446a3c98d6d065213913277268John Reck 519e486d932ca5a10446a3c98d6d065213913277268John Reck return result.toArray(new Uri[result.size()]); 520149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck } 52128912a508493e583c48772e2a234e0ed66849490John Reck 52223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck /** 523fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck * Return thumbnail representing the document at the given URI. Callers are 524ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * responsible for their own in-memory caching. Given document must have 525ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * {@link Documents#FLAG_SUPPORTS_THUMBNAIL} set. 526149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck * 527149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck * @return decoded thumbnail, or {@code null} if problem was encountered. 528149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck */ 529149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck public static Bitmap getThumbnail(ContentResolver resolver, Uri documentUri, Point size) { 530149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck final Bundle opts = new Bundle(); 531149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck opts.putParcelable(EXTRA_THUMBNAIL_SIZE, size); 532149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck 533149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck AssetFileDescriptor afd = null; 534149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck try { 535149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck afd = resolver.openTypedAssetFileDescriptor(documentUri, "image/*", opts); 536149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck 537149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck final FileDescriptor fd = afd.getFileDescriptor(); 538149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck final BitmapFactory.Options bitmapOpts = new BitmapFactory.Options(); 539149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck 540149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck bitmapOpts.inJustDecodeBounds = true; 541149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck BitmapFactory.decodeFileDescriptor(fd, null, bitmapOpts); 542edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck 543ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck final int widthSample = bitmapOpts.outWidth / size.x; 544910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales final int heightSample = bitmapOpts.outHeight / size.y; 545910beb8f5d9042163e2ad0dbb744d9f147db9604Andres Morales 54606f5bc70a667a02b14e31d3f53f91d3661e30666Andres Morales bitmapOpts.inJustDecodeBounds = false; 54738e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck bitmapOpts.inSampleSize = Math.min(widthSample, heightSample); 54838e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck return BitmapFactory.decodeFileDescriptor(fd, null, bitmapOpts); 54923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck } catch (IOException e) { 55023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck Log.w(TAG, "Failed to load thumbnail for " + documentUri + ": " + e); 551e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck return null; 55218f16e6fba74eda173e1e7c869e6e2e2acc073ffJohn Reck } finally { 553adfeec94560c6661c5e6600b10c05f34a40f6454Chris Craik IoUtils.closeQuietly(afd); 554adfeec94560c6661c5e6600b10c05f34a40f6454Chris Craik } 555adfeec94560c6661c5e6600b10c05f34a40f6454Chris Craik } 556adfeec94560c6661c5e6600b10c05f34a40f6454Chris Craik 557adfeec94560c6661c5e6600b10c05f34a40f6454Chris Craik /** 558ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * Create a new document under a specific parent document with the given 559ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * display name and MIME type. 560368cdd85268999997fb495cf90c4417221797de0John Reck * 561ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne * @param parentDocumentUri document with 562e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck * {@link Documents#FLAG_SUPPORTS_CREATE} 563e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck * @param displayName name for new document 5647f667e7a0823d52eed2ed64a31b125f6b8da21cbMatthew Bouyack * @param mimeType MIME type for new document, which cannot be changed 565ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * @return newly created document Uri, or {@code null} if failed 566ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck */ 5671b54fb27ac48495ed0b33868fda5776fb49fe0f3Chris Craik public static Uri createDocument( 5687f667e7a0823d52eed2ed64a31b125f6b8da21cbMatthew Bouyack ContentResolver resolver, Uri parentDocumentUri, String displayName, String mimeType) { 569fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck final ContentValues values = new ContentValues(); 570e2e53a7079733694bd52dbce665e9ceff21e9727Chris Craik values.put(DocumentColumns.MIME_TYPE, mimeType); 571ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne values.put(DocumentColumns.DISPLAY_NAME, displayName); 572a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck return resolver.insert(parentDocumentUri, values); 573e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck } 574a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck 575e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck /** 576e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck * Rename the document at the given URI. Given document must have 5773b20251a355c88193c439f928a84ae69483fb488John Reck * {@link Documents#FLAG_SUPPORTS_RENAME} set. 578d3d8dafc2f61fb118c060720b52684c59303f3dbJohn Reck * 5790d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck * @return if rename was successful. 5803b20251a355c88193c439f928a84ae69483fb488John Reck */ 5810d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck public static boolean renameDocument( 5820d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck ContentResolver resolver, Uri documentUri, String displayName) { 5836f07a0dc875a9eac67312085a8e0133b9e2f4771John Reck final ContentValues values = new ContentValues(); 584d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik values.put(DocumentColumns.DISPLAY_NAME, displayName); 58523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck return (resolver.update(documentUri, values, null, null) == 1); 58623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck } 587998a6d81896df8b662cc10ddeb35087b78b38d72John Reck 58851f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck /** 589d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik * Notify the system that roots have changed for the given storage provider. 590998a6d81896df8b662cc10ddeb35087b78b38d72John Reck * This signal is used to invalidate internal caches. 591998a6d81896df8b662cc10ddeb35087b78b38d72John Reck */ 592998a6d81896df8b662cc10ddeb35087b78b38d72John Reck public static void notifyRootsChanged(Context context, String authority) { 59351f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck final Intent intent = new Intent(ACTION_DOCUMENT_CHANGED); 59451f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck intent.setData(buildRootsUri(authority)); 59551f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck context.sendBroadcast(intent); 59651f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck } 59751f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck} 59851f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck