19ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey/* 29ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey * Copyright (C) 2013 The Android Open Source Project 39ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey * 49ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 59ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey * you may not use this file except in compliance with the License. 69ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey * You may obtain a copy of the License at 79ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey * 89ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 99ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey * 109ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey * Unless required by applicable law or agreed to in writing, software 119ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 129ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey * See the License for the specific language governing permissions and 149ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey * limitations under the License. 159ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey */ 169ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey 179ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkeypackage android.provider; 189ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey 196398343e83b3fd11dd6536cf6f390a52c1e19d2eJeff Sharkeyimport static android.net.TrafficStats.KB_IN_BYTES; 2034385d352da19805ae948215e2edbeedd16b7941Elliott Hughesimport static android.system.OsConstants.SEEK_SET; 216398343e83b3fd11dd6536cf6f390a52c1e19d2eJeff Sharkey 22323ee3ec094b78b9f96a8ab55b5c3b291028eeafSteve McKayimport android.annotation.Nullable; 23de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkeyimport android.content.ContentProviderClient; 249ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkeyimport android.content.ContentResolver; 25ee2f7df9ee8a4f43c3b0858bad08a4f0a59a627fJeff Sharkeyimport android.content.Context; 269ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkeyimport android.content.Intent; 27d2e1e810a79ce0988df57c0bcbcd184e14a067b4Jeff Sharkeyimport android.content.pm.ResolveInfo; 289ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkeyimport android.content.res.AssetFileDescriptor; 2920d96d8aff2193d548977e23ce5158657cac94e0Jeff Sharkeyimport android.database.Cursor; 309ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkeyimport android.graphics.Bitmap; 319ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkeyimport android.graphics.BitmapFactory; 32c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkeyimport android.graphics.Matrix; 339ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkeyimport android.graphics.Point; 34c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkeyimport android.media.ExifInterface; 359ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkeyimport android.net.Uri; 369ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkeyimport android.os.Bundle; 37ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkeyimport android.os.CancellationSignal; 3833819318f61224cdda45e5e9a70dc9cdb9f33911Jeff Sharkeyimport android.os.OperationCanceledException; 39bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkeyimport android.os.ParcelFileDescriptor; 40bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkeyimport android.os.ParcelFileDescriptor.OnCloseListener; 41de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkeyimport android.os.RemoteException; 4204a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Lemeimport android.os.storage.StorageVolume; 4334385d352da19805ae948215e2edbeedd16b7941Elliott Hughesimport android.system.ErrnoException; 4434385d352da19805ae948215e2edbeedd16b7941Elliott Hughesimport android.system.Os; 459ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkeyimport android.util.Log; 469ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey 479ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkeyimport libcore.io.IoUtils; 489ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey 49de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkeyimport java.io.BufferedInputStream; 50c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkeyimport java.io.File; 519d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkeyimport java.io.FileDescriptor; 52de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkeyimport java.io.FileInputStream; 53c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkeyimport java.io.FileNotFoundException; 549ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkeyimport java.io.IOException; 55dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkeyimport java.util.List; 569ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey 579ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey/** 58bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey * Defines the contract between a documents provider and the platform. 59bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey * <p> 60aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * To create a document provider, extend {@link DocumentsProvider}, which 61aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * provides a foundational implementation of this contract. 6221de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey * <p> 6321de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey * All client apps must hold a valid URI permission grant to access documents, 6421de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey * typically issued when a user makes a selection through 65b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * {@link Intent#ACTION_OPEN_DOCUMENT}, {@link Intent#ACTION_CREATE_DOCUMENT}, 6604a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme * {@link Intent#ACTION_OPEN_DOCUMENT_TREE}, or 6704a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme * {@link StorageVolume#createAccessIntent(String) StorageVolume.createAccessIntent}. 68bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey * 69aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * @see DocumentsProvider 709ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey */ 719ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkeypublic final class DocumentsContract { 72d3afdeebeb9dcfbb5f24e4afac988e2e96de26deSteve McKay private static final String TAG = "DocumentsContract"; 739ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey 74ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey // content://com.example/root/ 75ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey // content://com.example/root/sdcard/ 76ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey // content://com.example/root/sdcard/recent/ 773e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey // content://com.example/root/sdcard/search/?query=pony 78ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey // content://com.example/document/12/ 79ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey // content://com.example/document/12/children/ 80b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey // content://com.example/tree/12/document/24/ 81b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey // content://com.example/tree/12/document/24/children/ 82aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey 83aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey private DocumentsContract() { 84aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey } 859ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey 8685f5f8132015d8a5043ea4413702420d0d157c9fJeff Sharkey /** 87e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * Intent action used to identify {@link DocumentsProvider} instances. This 88e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * is used in the {@code <intent-filter>} of a {@code <provider>}. 8985f5f8132015d8a5043ea4413702420d0d157c9fJeff Sharkey */ 9085f5f8132015d8a5043ea4413702420d0d157c9fJeff Sharkey public static final String PROVIDER_INTERFACE = "android.content.action.DOCUMENTS_PROVIDER"; 9185f5f8132015d8a5043ea4413702420d0d157c9fJeff Sharkey 925b83f854d9cbd6dc9e5a31892dbe8515b4c29683Jeff Sharkey /** {@hide} */ 9315be83612c34b65404f15d0feafdb4a329467769Jeff Sharkey public static final String EXTRA_PACKAGE_NAME = "android.content.extra.PACKAGE_NAME"; 9415be83612c34b65404f15d0feafdb4a329467769Jeff Sharkey 9596c620595bd0585f934b0971b4552c57845e9a78Jeff Sharkey /** {@hide} */ 961719b3555dc9bff5394045585051e7d5684bceb1Aga Wronska public static final String EXTRA_SHOW_ADVANCED = "android.content.extra.SHOW_ADVANCED"; 971719b3555dc9bff5394045585051e7d5684bceb1Aga Wronska 981719b3555dc9bff5394045585051e7d5684bceb1Aga Wronska /** {@hide} */ 9983df8c072ddd01a5adc11da0869103c4645e6d76Steve McKay public static final String EXTRA_SHOW_FILESIZE = "android.content.extra.SHOW_FILESIZE"; 10083df8c072ddd01a5adc11da0869103c4645e6d76Steve McKay 10183df8c072ddd01a5adc11da0869103c4645e6d76Steve McKay /** {@hide} */ 102f570c771f23792837fb63f708bfa5c948d5fcad7Steve McKay public static final String EXTRA_FANCY_FEATURES = "android.content.extra.FANCY"; 103f570c771f23792837fb63f708bfa5c948d5fcad7Steve McKay 104f570c771f23792837fb63f708bfa5c948d5fcad7Steve McKay /** {@hide} */ 10574fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski public static final String EXTRA_TARGET_URI = "android.content.extra.TARGET_URI"; 10674fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski 107c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey /** 10877797400ec103b1691e1c3fa602c329b49ac18caBen Kwa * Set this in a DocumentsUI intent to cause a package's own roots to be 10977797400ec103b1691e1c3fa602c329b49ac18caBen Kwa * excluded from the roots list. 11077797400ec103b1691e1c3fa602c329b49ac18caBen Kwa */ 11177797400ec103b1691e1c3fa602c329b49ac18caBen Kwa public static final String EXTRA_EXCLUDE_SELF = "android.provider.extra.EXCLUDE_SELF"; 11277797400ec103b1691e1c3fa602c329b49ac18caBen Kwa 11377797400ec103b1691e1c3fa602c329b49ac18caBen Kwa /** 114c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey * Included in {@link AssetFileDescriptor#getExtras()} when returned 115c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey * thumbnail should be rotated. 116c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey * 117c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey * @see MediaStore.Images.ImageColumns#ORIENTATION 118c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey */ 1195f53f6531176d503d0bb26b50581091372a1478fTomasz Mikolajewski public static final String EXTRA_ORIENTATION = "android.provider.extra.ORIENTATION"; 120c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey 1210e591f95bd023fc153520efe0852180bb580a442Tomasz Mikolajewski /** 1220e591f95bd023fc153520efe0852180bb580a442Tomasz Mikolajewski * Overrides the default prompt text in DocumentsUI when set in an intent. 1230e591f95bd023fc153520efe0852180bb580a442Tomasz Mikolajewski */ 1240e591f95bd023fc153520efe0852180bb580a442Tomasz Mikolajewski public static final String EXTRA_PROMPT = "android.provider.extra.PROMPT"; 1250e591f95bd023fc153520efe0852180bb580a442Tomasz Mikolajewski 12615be83612c34b65404f15d0feafdb4a329467769Jeff Sharkey /** {@hide} */ 127a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey public static final String ACTION_MANAGE_DOCUMENT = "android.provider.action.MANAGE_DOCUMENT"; 128aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey 12959d577a518333f4b4514315b6d10e8dba160abcdJeff Sharkey /** {@hide} */ 13084cebbeb69e5b473f0cb4d1575bdc57aac48e32eBen Kwa public static final String ACTION_BROWSE = "android.provider.action.BROWSE"; 1311407d4c77732c7fad34c6b813d05771de6ed970fJeff Sharkey 1321407d4c77732c7fad34c6b813d05771de6ed970fJeff Sharkey /** {@hide} */ 1331407d4c77732c7fad34c6b813d05771de6ed970fJeff Sharkey public static final String 1341407d4c77732c7fad34c6b813d05771de6ed970fJeff Sharkey ACTION_DOCUMENT_ROOT_SETTINGS = "android.provider.action.DOCUMENT_ROOT_SETTINGS"; 13559d577a518333f4b4514315b6d10e8dba160abcdJeff Sharkey 136bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey /** 137de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey * Buffer is large enough to rewind past any EXIF headers. 138de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey */ 139de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey private static final int THUMBNAIL_BUFFER_SIZE = (int) (128 * KB_IN_BYTES); 140de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey 141cc2ae6b421353e03160df3b05ce9042b8a5ff8ccJeff Sharkey /** {@hide} */ 142cc2ae6b421353e03160df3b05ce9042b8a5ff8ccJeff Sharkey public static final String PACKAGE_DOCUMENTS_UI = "com.android.documentsui"; 143cc2ae6b421353e03160df3b05ce9042b8a5ff8ccJeff Sharkey 144de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey /** 145e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * Constants related to a document, including {@link Cursor} column names 146ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * and flags. 147ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * <p> 148e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * A document can be either an openable stream (with a specific MIME type), 149e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * or a directory containing additional documents (with the 150e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * {@link #MIME_TYPE_DIR} MIME type). A directory represents the top of a 151e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * subtree containing zero or more documents, which can recursively contain 152e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * even more documents and directories. 153ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * <p> 154ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * All columns are <em>read-only</em> to client applications. 155bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey */ 156ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public final static class Document { 157ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey private Document() { 158a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey } 1599ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey 160a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey /** 161ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * Unique ID of a document. This ID is both provided by and interpreted 162ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * by a {@link DocumentsProvider}, and should be treated as an opaque 1636efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey * value by client applications. This column is required. 164ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * <p> 165ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * Each document must have a unique ID within a provider, but that 166ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * single document may be included as a child of multiple directories. 167ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * <p> 168ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * A provider must always return durable IDs, since they will be used to 169e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * issue long-term URI permission grants when an application interacts 170ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * with {@link Intent#ACTION_OPEN_DOCUMENT} and 171ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * {@link Intent#ACTION_CREATE_DOCUMENT}. 172ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * <p> 173ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * Type: STRING 174a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey */ 175ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static final String COLUMN_DOCUMENT_ID = "document_id"; 1769ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey 177a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey /** 178ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * Concrete MIME type of a document. For example, "image/png" or 179ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * "application/pdf" for openable files. A document can also be a 180ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * directory containing additional documents, which is represented with 1816efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey * the {@link #MIME_TYPE_DIR} MIME type. This column is required. 182ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * <p> 183ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * Type: STRING 184a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey * 185ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @see #MIME_TYPE_DIR 186a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey */ 187ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static final String COLUMN_MIME_TYPE = "mime_type"; 18820d96d8aff2193d548977e23ce5158657cac94e0Jeff Sharkey 189a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey /** 190ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * Display name of a document, used as the primary title displayed to a 1916efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey * user. This column is required. 192ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * <p> 193ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * Type: STRING 194ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey */ 195ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static final String COLUMN_DISPLAY_NAME = OpenableColumns.DISPLAY_NAME; 196ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey 197ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey /** 1986efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey * Summary of a document, which may be shown to a user. This column is 1996efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey * optional, and may be {@code null}. 200ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * <p> 201ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * Type: STRING 202ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey */ 203ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static final String COLUMN_SUMMARY = "summary"; 204ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey 205ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey /** 206ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * Timestamp when a document was last modified, in milliseconds since 2076efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey * January 1, 1970 00:00:00.0 UTC. This column is required, and may be 2086efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey * {@code null} if unknown. A {@link DocumentsProvider} can update this 2096efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey * field using events from {@link OnCloseListener} or other reliable 210ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * {@link ParcelFileDescriptor} transports. 211ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * <p> 212ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * Type: INTEGER (long) 213a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey * 214ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @see System#currentTimeMillis() 215a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey */ 216ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static final String COLUMN_LAST_MODIFIED = "last_modified"; 21720d96d8aff2193d548977e23ce5158657cac94e0Jeff Sharkey 218a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey /** 2196efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey * Specific icon resource ID for a document. This column is optional, 2206efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey * and may be {@code null} to use a platform-provided default icon based 2216efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey * on {@link #COLUMN_MIME_TYPE}. 222ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * <p> 223ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * Type: INTEGER (int) 224ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey */ 225ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static final String COLUMN_ICON = "icon"; 226ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey 227ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey /** 2286efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey * Flags that apply to a document. This column is required. 229ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * <p> 230ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * Type: INTEGER (int) 231a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey * 232ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @see #FLAG_SUPPORTS_WRITE 233ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @see #FLAG_SUPPORTS_DELETE 234ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @see #FLAG_SUPPORTS_THUMBNAIL 235ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @see #FLAG_DIR_PREFERS_GRID 2366efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey * @see #FLAG_DIR_PREFERS_LAST_MODIFIED 237a8057a9dcef71f9b3e0f31e830d750337a4349baTomasz Mikolajewski * @see #FLAG_VIRTUAL_DOCUMENT 238cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski * @see #FLAG_SUPPORTS_COPY 239cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski * @see #FLAG_SUPPORTS_MOVE 240cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski * @see #FLAG_SUPPORTS_REMOVE 241a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey */ 242ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static final String COLUMN_FLAGS = "flags"; 2439ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey 244a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey /** 2456efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey * Size of a document, in bytes, or {@code null} if unknown. This column 2466efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey * is required. 247ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * <p> 248ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * Type: INTEGER (long) 249ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey */ 250ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static final String COLUMN_SIZE = OpenableColumns.SIZE; 251ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey 252ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey /** 253ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * MIME type of a document which is a directory that may contain 254ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * additional documents. 255a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey * 256ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @see #COLUMN_MIME_TYPE 257a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey */ 258ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static final String MIME_TYPE_DIR = "vnd.android.document/directory"; 2595b83f854d9cbd6dc9e5a31892dbe8515b4c29683Jeff Sharkey 260a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey /** 261ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * Flag indicating that a document can be represented as a thumbnail. 262a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey * 263ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @see #COLUMN_FLAGS 264ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @see DocumentsContract#getDocumentThumbnail(ContentResolver, Uri, 265ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * Point, CancellationSignal) 266ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @see DocumentsProvider#openDocumentThumbnail(String, Point, 267ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * android.os.CancellationSignal) 268a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey */ 269ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static final int FLAG_SUPPORTS_THUMBNAIL = 1; 270a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey 271a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey /** 272aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * Flag indicating that a document supports writing. 273ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * <p> 274ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * When a document is opened with {@link Intent#ACTION_OPEN_DOCUMENT}, 275ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * the calling application is granted both 276ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION} and 277ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION}. However, the actual 278ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * writability of a document may change over time, for example due to 279ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * remote access changes. This flag indicates that a document client can 280ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * expect {@link ContentResolver#openOutputStream(Uri)} to succeed. 28183df8c072ddd01a5adc11da0869103c4645e6d76Steve McKay * 282ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @see #COLUMN_FLAGS 283a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey */ 284ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static final int FLAG_SUPPORTS_WRITE = 1 << 1; 285a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey 286a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey /** 287ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * Flag indicating that a document is deletable. 288a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey * 289ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @see #COLUMN_FLAGS 290ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @see DocumentsContract#deleteDocument(ContentResolver, Uri) 291ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @see DocumentsProvider#deleteDocument(String) 292a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey */ 293ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static final int FLAG_SUPPORTS_DELETE = 1 << 2; 29492d7e697a864a3e18bef4ef256bb3eb339a66b4eJeff Sharkey 295ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey /** 296ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * Flag indicating that a document is a directory that supports creation 297ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * of new files within it. Only valid when {@link #COLUMN_MIME_TYPE} is 298ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * {@link #MIME_TYPE_DIR}. 299ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * 300ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @see #COLUMN_FLAGS 301ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @see DocumentsProvider#createDocument(String, String, String) 302ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey */ 303ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static final int FLAG_DIR_SUPPORTS_CREATE = 1 << 3; 30492d7e697a864a3e18bef4ef256bb3eb339a66b4eJeff Sharkey 305ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey /** 306ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * Flag indicating that a directory prefers its contents be shown in a 307ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * larger format grid. Usually suitable when a directory contains mostly 308ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * pictures. Only valid when {@link #COLUMN_MIME_TYPE} is 309ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * {@link #MIME_TYPE_DIR}. 310ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * 311ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @see #COLUMN_FLAGS 312ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey */ 3133e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey public static final int FLAG_DIR_PREFERS_GRID = 1 << 4; 314d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey 315d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey /** 316d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey * Flag indicating that a directory prefers its contents be sorted by 317d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey * {@link #COLUMN_LAST_MODIFIED}. Only valid when 318d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey * {@link #COLUMN_MIME_TYPE} is {@link #MIME_TYPE_DIR}. 319d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey * 320d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey * @see #COLUMN_FLAGS 321d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey */ 3223e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey public static final int FLAG_DIR_PREFERS_LAST_MODIFIED = 1 << 5; 323f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey 324f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey /** 325b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey * Flag indicating that a document can be renamed. 326b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey * 327b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey * @see #COLUMN_FLAGS 32890a753330d1cccdb844cedcb3e01ad642f2a5542Tomasz Mikolajewski * @see DocumentsContract#renameDocument(ContentResolver, Uri, 329b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey * String) 330b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey * @see DocumentsProvider#renameDocument(String, String) 331b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey */ 332b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey public static final int FLAG_SUPPORTS_RENAME = 1 << 6; 333b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey 334b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey /** 33574fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski * Flag indicating that a document can be copied to another location 33674fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski * within the same document provider. 33774fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski * 33874fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski * @see #COLUMN_FLAGS 33990a753330d1cccdb844cedcb3e01ad642f2a5542Tomasz Mikolajewski * @see DocumentsContract#copyDocument(ContentResolver, Uri, Uri) 340a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski * @see DocumentsProvider#copyDocument(String, String) 34174fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski */ 34274fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski public static final int FLAG_SUPPORTS_COPY = 1 << 7; 34374fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski 34474fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski /** 345a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski * Flag indicating that a document can be moved to another location 346a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski * within the same document provider. 347a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski * 348a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski * @see #COLUMN_FLAGS 34990a753330d1cccdb844cedcb3e01ad642f2a5542Tomasz Mikolajewski * @see DocumentsContract#moveDocument(ContentResolver, Uri, Uri, Uri) 350d46ecbcc5322cf817e64591e985f1f2a6167e9a7Tomasz Mikolajewski * @see DocumentsProvider#moveDocument(String, String, String) 351a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski */ 352a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski public static final int FLAG_SUPPORTS_MOVE = 1 << 8; 353a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski 354a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski /** 355a8057a9dcef71f9b3e0f31e830d750337a4349baTomasz Mikolajewski * Flag indicating that a document is virtual, and doesn't have byte 356a8057a9dcef71f9b3e0f31e830d750337a4349baTomasz Mikolajewski * representation in the MIME type specified as {@link #COLUMN_MIME_TYPE}. 357a8057a9dcef71f9b3e0f31e830d750337a4349baTomasz Mikolajewski * 358a8057a9dcef71f9b3e0f31e830d750337a4349baTomasz Mikolajewski * @see #COLUMN_FLAGS 359a8057a9dcef71f9b3e0f31e830d750337a4349baTomasz Mikolajewski * @see #COLUMN_MIME_TYPE 360a8057a9dcef71f9b3e0f31e830d750337a4349baTomasz Mikolajewski * @see DocumentsProvider#openTypedDocument(String, String, Bundle, 361a8057a9dcef71f9b3e0f31e830d750337a4349baTomasz Mikolajewski * android.os.CancellationSignal) 362d99964fd66dc4dabe431ff995995de508f614216Tomasz Mikolajewski * @see DocumentsProvider#getDocumentStreamTypes(String, String) 363a8057a9dcef71f9b3e0f31e830d750337a4349baTomasz Mikolajewski */ 36475395651c272b3df746e0e5fede0a8fedd81e44bTomasz Mikolajewski public static final int FLAG_VIRTUAL_DOCUMENT = 1 << 9; 365a8057a9dcef71f9b3e0f31e830d750337a4349baTomasz Mikolajewski 366a8057a9dcef71f9b3e0f31e830d750337a4349baTomasz Mikolajewski /** 3679b055e1d842c5c68be168807bcf5b84a7c95db80Tomasz Mikolajewski * Flag indicating that a document can be removed from a parent. 3689b055e1d842c5c68be168807bcf5b84a7c95db80Tomasz Mikolajewski * 3699b055e1d842c5c68be168807bcf5b84a7c95db80Tomasz Mikolajewski * @see #COLUMN_FLAGS 37090a753330d1cccdb844cedcb3e01ad642f2a5542Tomasz Mikolajewski * @see DocumentsContract#removeDocument(ContentResolver, Uri, Uri) 3719b055e1d842c5c68be168807bcf5b84a7c95db80Tomasz Mikolajewski * @see DocumentsProvider#removeDocument(String, String) 3729b055e1d842c5c68be168807bcf5b84a7c95db80Tomasz Mikolajewski */ 3739b055e1d842c5c68be168807bcf5b84a7c95db80Tomasz Mikolajewski public static final int FLAG_SUPPORTS_REMOVE = 1 << 10; 3749b055e1d842c5c68be168807bcf5b84a7c95db80Tomasz Mikolajewski 3759b055e1d842c5c68be168807bcf5b84a7c95db80Tomasz Mikolajewski /** 376a4c338aea611096dc67d445708f4474fd93e4d62Tomasz Mikolajewski * Flag indicating that a document is an archive, and it's contents can be 377a4c338aea611096dc67d445708f4474fd93e4d62Tomasz Mikolajewski * obtained via {@link DocumentsProvider#queryChildDocuments}. 378a4c338aea611096dc67d445708f4474fd93e4d62Tomasz Mikolajewski * <p> 379a4c338aea611096dc67d445708f4474fd93e4d62Tomasz Mikolajewski * The <em>provider</em> support library offers utility classes to add common 380a4c338aea611096dc67d445708f4474fd93e4d62Tomasz Mikolajewski * archive support. 381a4c338aea611096dc67d445708f4474fd93e4d62Tomasz Mikolajewski * 382a4c338aea611096dc67d445708f4474fd93e4d62Tomasz Mikolajewski * @see #COLUMN_FLAGS 383a4c338aea611096dc67d445708f4474fd93e4d62Tomasz Mikolajewski * @see DocumentsProvider#queryChildDocuments(String, String[], String) 3849b055e1d842c5c68be168807bcf5b84a7c95db80Tomasz Mikolajewski * @hide 385a4c338aea611096dc67d445708f4474fd93e4d62Tomasz Mikolajewski */ 3869b055e1d842c5c68be168807bcf5b84a7c95db80Tomasz Mikolajewski public static final int FLAG_ARCHIVE = 1 << 15; 387168e464812341fdc64c3b85659b60114bee3b86eSteve McKay 388168e464812341fdc64c3b85659b60114bee3b86eSteve McKay /** 389168e464812341fdc64c3b85659b60114bee3b86eSteve McKay * Flag indicating that a document is not complete, likely its 390168e464812341fdc64c3b85659b60114bee3b86eSteve McKay * contents are being downloaded. Partial files cannot be opened, 391168e464812341fdc64c3b85659b60114bee3b86eSteve McKay * copied, moved in the UI. But they can be deleted and retried 392168e464812341fdc64c3b85659b60114bee3b86eSteve McKay * if they represent a failed download. 393168e464812341fdc64c3b85659b60114bee3b86eSteve McKay * 394168e464812341fdc64c3b85659b60114bee3b86eSteve McKay * @see #COLUMN_FLAGS 395168e464812341fdc64c3b85659b60114bee3b86eSteve McKay * @hide 396168e464812341fdc64c3b85659b60114bee3b86eSteve McKay */ 397168e464812341fdc64c3b85659b60114bee3b86eSteve McKay public static final int FLAG_PARTIAL = 1 << 16; 398dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey } 399dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey 400bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey /** 401e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * Constants related to a root of documents, including {@link Cursor} column 402e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * names and flags. A root is the start of a tree of documents, such as a 403e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * physical storage device, or an account. Each root starts at the directory 404e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * referenced by {@link Root#COLUMN_DOCUMENT_ID}, which can recursively 405e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * contain both documents and directories. 406ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * <p> 407ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * All columns are <em>read-only</em> to client applications. 408bd3b902567b09379e1b62c60b3319ad82102efadJeff Sharkey */ 409ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public final static class Root { 410ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey private Root() { 411dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey } 4129ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey 4139ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey /** 414ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * Unique ID of a root. This ID is both provided by and interpreted by a 415ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * {@link DocumentsProvider}, and should be treated as an opaque value 4166efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey * by client applications. This column is required. 4179ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey * <p> 4189ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey * Type: STRING 4199ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey */ 420ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static final String COLUMN_ROOT_ID = "root_id"; 4219ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey 4229ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey /** 4236efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey * Flags that apply to a root. This column is required. 4249ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey * <p> 425ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * Type: INTEGER (int) 4269ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey * 427ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @see #FLAG_LOCAL_ONLY 428ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @see #FLAG_SUPPORTS_CREATE 4293e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey * @see #FLAG_SUPPORTS_RECENTS 4303e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey * @see #FLAG_SUPPORTS_SEARCH 4319ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey */ 432ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static final String COLUMN_FLAGS = "flags"; 4339ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey 4349ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey /** 4356efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey * Icon resource ID for a root. This column is required. 4369ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey * <p> 4379ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey * Type: INTEGER (int) 4389ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey */ 439ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static final String COLUMN_ICON = "icon"; 44066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey 44166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey /** 4426efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey * Title for a root, which will be shown to a user. This column is 443e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * required. For a single storage service surfacing multiple accounts as 444e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * different roots, this title should be the name of the service. 44566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * <p> 44666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * Type: STRING 44766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey */ 448ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static final String COLUMN_TITLE = "title"; 449aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey 450aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey /** 4516efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey * Summary for this root, which may be shown to a user. This column is 452e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * optional, and may be {@code null}. For a single storage service 453e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * surfacing multiple accounts as different roots, this summary should 454e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * be the name of the account. 455aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * <p> 456ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * Type: STRING 457aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey */ 458ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static final String COLUMN_SUMMARY = "summary"; 4599ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey 460a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey /** 461ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * Document which is a directory that represents the top directory of 4626efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey * this root. This column is required. 463ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * <p> 464ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * Type: STRING 465a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey * 466ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @see Document#COLUMN_DOCUMENT_ID 467a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey */ 468ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static final String COLUMN_DOCUMENT_ID = "document_id"; 469ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey 470ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey /** 4716efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey * Number of bytes available in this root. This column is optional, and 4726efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey * may be {@code null} if unknown or unbounded. 473ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * <p> 474ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * Type: INTEGER (long) 475ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey */ 476ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static final String COLUMN_AVAILABLE_BYTES = "available_bytes"; 47766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey 478a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey /** 4793f78e175ac647daf7184aaf6ba768777cfdd2ff5Tomasz Mikolajewski * Capacity of a root in bytes. This column is optional, and may be 4803f78e175ac647daf7184aaf6ba768777cfdd2ff5Tomasz Mikolajewski * {@code null} if unknown or unbounded. 4813f78e175ac647daf7184aaf6ba768777cfdd2ff5Tomasz Mikolajewski * <p> 4823f78e175ac647daf7184aaf6ba768777cfdd2ff5Tomasz Mikolajewski * Type: INTEGER (long) 4833f78e175ac647daf7184aaf6ba768777cfdd2ff5Tomasz Mikolajewski */ 4843f78e175ac647daf7184aaf6ba768777cfdd2ff5Tomasz Mikolajewski public static final String COLUMN_CAPACITY_BYTES = "capacity_bytes"; 4853f78e175ac647daf7184aaf6ba768777cfdd2ff5Tomasz Mikolajewski 4863f78e175ac647daf7184aaf6ba768777cfdd2ff5Tomasz Mikolajewski /** 4876efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey * MIME types supported by this root. This column is optional, and if 4886efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey * {@code null} the root is assumed to support all MIME types. Multiple 4896efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey * MIME types can be separated by a newline. For example, a root 4906efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey * supporting audio might return "audio/*\napplication/x-flac". 491923396b7720367ec99c889725fddfa556e703971Jeff Sharkey * <p> 4926efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey * Type: STRING 493923396b7720367ec99c889725fddfa556e703971Jeff Sharkey */ 494923396b7720367ec99c889725fddfa556e703971Jeff Sharkey public static final String COLUMN_MIME_TYPES = "mime_types"; 495923396b7720367ec99c889725fddfa556e703971Jeff Sharkey 496a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey /** {@hide} */ 497a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey public static final String MIME_TYPE_ITEM = "vnd.android.document/root"; 498a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey 499923396b7720367ec99c889725fddfa556e703971Jeff Sharkey /** 500aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * Flag indicating that at least one directory under this root supports 501ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * creating content. Roots with this flag will be shown when an 502ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * application interacts with {@link Intent#ACTION_CREATE_DOCUMENT}. 503aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * 504ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @see #COLUMN_FLAGS 505aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey */ 506aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey public static final int FLAG_SUPPORTS_CREATE = 1; 50792d7e697a864a3e18bef4ef256bb3eb339a66b4eJeff Sharkey 50820d96d8aff2193d548977e23ce5158657cac94e0Jeff Sharkey /** 509aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * Flag indicating that this root offers content that is strictly local 510aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * on the device. That is, no network requests are made for the content. 51120d96d8aff2193d548977e23ce5158657cac94e0Jeff Sharkey * 512ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @see #COLUMN_FLAGS 513ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @see Intent#EXTRA_LOCAL_ONLY 51420d96d8aff2193d548977e23ce5158657cac94e0Jeff Sharkey */ 515aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey public static final int FLAG_LOCAL_ONLY = 1 << 1; 516aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey 51720d96d8aff2193d548977e23ce5158657cac94e0Jeff Sharkey /** 518e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * Flag indicating that this root can be queried to provide recently 519e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * modified documents. 520251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey * 521251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey * @see #COLUMN_FLAGS 522251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey * @see DocumentsContract#buildRecentDocumentsUri(String, String) 523e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * @see DocumentsProvider#queryRecentDocuments(String, String[]) 524251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey */ 5256efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey public static final int FLAG_SUPPORTS_RECENTS = 1 << 2; 5263e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey 5273e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey /** 5283e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey * Flag indicating that this root supports search. 5293e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey * 5303e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey * @see #COLUMN_FLAGS 531e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * @see DocumentsContract#buildSearchDocumentsUri(String, String, 532e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * String) 5333e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey * @see DocumentsProvider#querySearchDocuments(String, String, 5343e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey * String[]) 5353e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey */ 5366efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey public static final int FLAG_SUPPORTS_SEARCH = 1 << 3; 5373e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey 5383e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey /** 539b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * Flag indicating that this root supports testing parent child 540b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * relationships. 54121de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey * 54221de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey * @see #COLUMN_FLAGS 54321de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey * @see DocumentsProvider#isChildDocument(String, String) 54421de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey */ 545b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey public static final int FLAG_SUPPORTS_IS_CHILD = 1 << 4; 54621de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey 54721de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey /** 5483e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey * Flag indicating that this root is currently empty. This may be used 5493e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey * to hide the root when opening documents, but the root will still be 5503e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey * shown when creating documents and {@link #FLAG_SUPPORTS_CREATE} is 5516efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey * also set. If the value of this flag changes, such as when a root 5526efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey * becomes non-empty, you must send a content changed notification for 5536efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey * {@link DocumentsContract#buildRootsUri(String)}. 5543e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey * 5553e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey * @see #COLUMN_FLAGS 5566efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey * @see ContentResolver#notifyChange(Uri, 5576efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey * android.database.ContentObserver, boolean) 5586efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey * @hide 5596efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey */ 5606efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey public static final int FLAG_EMPTY = 1 << 16; 5616efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey 5626efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey /** 5631719b3555dc9bff5394045585051e7d5684bceb1Aga Wronska * Flag indicating that this root should only be visible to advanced 5641719b3555dc9bff5394045585051e7d5684bceb1Aga Wronska * users. 5651719b3555dc9bff5394045585051e7d5684bceb1Aga Wronska * 5661719b3555dc9bff5394045585051e7d5684bceb1Aga Wronska * @see #COLUMN_FLAGS 5671719b3555dc9bff5394045585051e7d5684bceb1Aga Wronska * @hide 5681719b3555dc9bff5394045585051e7d5684bceb1Aga Wronska */ 5691719b3555dc9bff5394045585051e7d5684bceb1Aga Wronska public static final int FLAG_ADVANCED = 1 << 17; 5701719b3555dc9bff5394045585051e7d5684bceb1Aga Wronska 5711719b3555dc9bff5394045585051e7d5684bceb1Aga Wronska /** 5721407d4c77732c7fad34c6b813d05771de6ed970fJeff Sharkey * Flag indicating that this root has settings. 5731407d4c77732c7fad34c6b813d05771de6ed970fJeff Sharkey * 5741407d4c77732c7fad34c6b813d05771de6ed970fJeff Sharkey * @see #COLUMN_FLAGS 5751407d4c77732c7fad34c6b813d05771de6ed970fJeff Sharkey * @see DocumentsContract#ACTION_DOCUMENT_ROOT_SETTINGS 5761407d4c77732c7fad34c6b813d05771de6ed970fJeff Sharkey * @hide 5771407d4c77732c7fad34c6b813d05771de6ed970fJeff Sharkey */ 5781719b3555dc9bff5394045585051e7d5684bceb1Aga Wronska public static final int FLAG_HAS_SETTINGS = 1 << 18; 579ba23e54d263fefaac96b3ce6b068e70ec6f06128Steve McKay 580ba23e54d263fefaac96b3ce6b068e70ec6f06128Steve McKay /** 581ba23e54d263fefaac96b3ce6b068e70ec6f06128Steve McKay * Flag indicating that this root is on removable SD card storage. 582ba23e54d263fefaac96b3ce6b068e70ec6f06128Steve McKay * 583ba23e54d263fefaac96b3ce6b068e70ec6f06128Steve McKay * @see #COLUMN_FLAGS 584ba23e54d263fefaac96b3ce6b068e70ec6f06128Steve McKay * @hide 585ba23e54d263fefaac96b3ce6b068e70ec6f06128Steve McKay */ 5861719b3555dc9bff5394045585051e7d5684bceb1Aga Wronska public static final int FLAG_REMOVABLE_SD = 1 << 19; 587ba23e54d263fefaac96b3ce6b068e70ec6f06128Steve McKay 588ba23e54d263fefaac96b3ce6b068e70ec6f06128Steve McKay /** 589ba23e54d263fefaac96b3ce6b068e70ec6f06128Steve McKay * Flag indicating that this root is on removable USB storage. 590ba23e54d263fefaac96b3ce6b068e70ec6f06128Steve McKay * 591ba23e54d263fefaac96b3ce6b068e70ec6f06128Steve McKay * @see #COLUMN_FLAGS 592ba23e54d263fefaac96b3ce6b068e70ec6f06128Steve McKay * @hide 593ba23e54d263fefaac96b3ce6b068e70ec6f06128Steve McKay */ 5941719b3555dc9bff5394045585051e7d5684bceb1Aga Wronska public static final int FLAG_REMOVABLE_USB = 1 << 20; 595ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey } 596aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey 597ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey /** 598ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * Optional boolean flag included in a directory {@link Cursor#getExtras()} 599ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * indicating that a document provider is still loading data. For example, a 600ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * provider has returned some results, but is still waiting on an 601ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * outstanding network request. The provider must send a content changed 602ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * notification when loading is finished. 603ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * 604ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @see ContentResolver#notifyChange(Uri, android.database.ContentObserver, 605ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * boolean) 606ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey */ 607ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static final String EXTRA_LOADING = "loading"; 608aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey 609ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey /** 610ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * Optional string included in a directory {@link Cursor#getExtras()} 611ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * providing an informational message that should be shown to a user. For 612ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * example, a provider may wish to indicate that not all documents are 613ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * available. 614ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey */ 615ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static final String EXTRA_INFO = "info"; 616aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey 617ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey /** 618ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * Optional string included in a directory {@link Cursor#getExtras()} 619ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * providing an error message that should be shown to a user. For example, a 620ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * provider may wish to indicate that a network error occurred. The user may 621ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * choose to retry, resulting in a new query. 622ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey */ 623ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static final String EXTRA_ERROR = "error"; 624aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey 625d3afdeebeb9dcfbb5f24e4afac988e2e96de26deSteve McKay /** 626d3afdeebeb9dcfbb5f24e4afac988e2e96de26deSteve McKay * Optional result (I'm thinking boolean) answer to a question. 627d3afdeebeb9dcfbb5f24e4afac988e2e96de26deSteve McKay * {@hide} 628d3afdeebeb9dcfbb5f24e4afac988e2e96de26deSteve McKay */ 629d3afdeebeb9dcfbb5f24e4afac988e2e96de26deSteve McKay public static final String EXTRA_RESULT = "result"; 630d3afdeebeb9dcfbb5f24e4afac988e2e96de26deSteve McKay 631ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey /** {@hide} */ 632ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static final String METHOD_CREATE_DOCUMENT = "android:createDocument"; 633ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey /** {@hide} */ 634b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey public static final String METHOD_RENAME_DOCUMENT = "android:renameDocument"; 635b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey /** {@hide} */ 636ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static final String METHOD_DELETE_DOCUMENT = "android:deleteDocument"; 63774fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski /** {@hide} */ 63874fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski public static final String METHOD_COPY_DOCUMENT = "android:copyDocument"; 639a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski /** {@hide} */ 640a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski public static final String METHOD_MOVE_DOCUMENT = "android:moveDocument"; 641d3afdeebeb9dcfbb5f24e4afac988e2e96de26deSteve McKay /** {@hide} */ 642d3afdeebeb9dcfbb5f24e4afac988e2e96de26deSteve McKay public static final String METHOD_IS_CHILD_DOCUMENT = "android:isChildDocument"; 643cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski /** {@hide} */ 644cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski public static final String METHOD_REMOVE_DOCUMENT = "android:removeDocument"; 645aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey 646ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey /** {@hide} */ 647d46ecbcc5322cf817e64591e985f1f2a6167e9a7Tomasz Mikolajewski public static final String EXTRA_PARENT_URI = "parentUri"; 648d46ecbcc5322cf817e64591e985f1f2a6167e9a7Tomasz Mikolajewski /** {@hide} */ 64921de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey public static final String EXTRA_URI = "uri"; 650aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey 651ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey private static final String PATH_ROOT = "root"; 652ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey private static final String PATH_RECENT = "recent"; 653ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey private static final String PATH_DOCUMENT = "document"; 654ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey private static final String PATH_CHILDREN = "children"; 655ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey private static final String PATH_SEARCH = "search"; 656b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey private static final String PATH_TREE = "tree"; 657aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey 658ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey private static final String PARAM_QUERY = "query"; 6594ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey private static final String PARAM_MANAGE = "manage"; 660aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey 661ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey /** 662e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * Build URI representing the roots of a document provider. When queried, a 663ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * provider will return one or more rows with columns defined by 664ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * {@link Root}. 665ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * 666ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @see DocumentsProvider#queryRoots(String[]) 667ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey */ 668ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static Uri buildRootsUri(String authority) { 669ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) 670ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey .authority(authority).appendPath(PATH_ROOT).build(); 671ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey } 672aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey 673ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey /** 674e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * Build URI representing the given {@link Root#COLUMN_ROOT_ID} in a 675a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey * document provider. 676a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey * 677a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey * @see #getRootId(Uri) 678a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey */ 679a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey public static Uri buildRootUri(String authority, String rootId) { 680a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) 681a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey .authority(authority).appendPath(PATH_ROOT).appendPath(rootId).build(); 682a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey } 683a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey 684a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey /** 685b67bfbf975a453a67300f24fac6e4687a676a378Steve McKay * Builds URI for user home directory on external (local) storage. 686b67bfbf975a453a67300f24fac6e4687a676a378Steve McKay * {@hide} 687b67bfbf975a453a67300f24fac6e4687a676a378Steve McKay */ 688b67bfbf975a453a67300f24fac6e4687a676a378Steve McKay public static Uri buildHomeUri() { 689b67bfbf975a453a67300f24fac6e4687a676a378Steve McKay // TODO: Avoid this type of interpackage copying. Added here to avoid 690b67bfbf975a453a67300f24fac6e4687a676a378Steve McKay // direct coupling, but not ideal. 691b67bfbf975a453a67300f24fac6e4687a676a378Steve McKay return DocumentsContract.buildRootUri("com.android.externalstorage.documents", "home"); 692b67bfbf975a453a67300f24fac6e4687a676a378Steve McKay } 693b67bfbf975a453a67300f24fac6e4687a676a378Steve McKay 694b67bfbf975a453a67300f24fac6e4687a676a378Steve McKay /** 695e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * Build URI representing the recently modified documents of a specific root 6963e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey * in a document provider. When queried, a provider will return zero or more 6973e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey * rows with columns defined by {@link Document}. 698ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * 699ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @see DocumentsProvider#queryRecentDocuments(String, String[]) 700ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @see #getRootId(Uri) 701ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey */ 702ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static Uri buildRecentDocumentsUri(String authority, String rootId) { 703ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) 704ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey .authority(authority).appendPath(PATH_ROOT).appendPath(rootId) 705ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey .appendPath(PATH_RECENT).build(); 706ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey } 707ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey 708ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey /** 70921de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey * Build URI representing access to descendant documents of the given 71021de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey * {@link Document#COLUMN_DOCUMENT_ID}. 71121de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey * 712b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * @see #getTreeDocumentId(Uri) 71321de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey */ 714b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey public static Uri buildTreeDocumentUri(String authority, String documentId) { 71521de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(authority) 716b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey .appendPath(PATH_TREE).appendPath(documentId).build(); 71721de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey } 71821de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey 71921de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey /** 720b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * Build URI representing the target {@link Document#COLUMN_DOCUMENT_ID} in 721b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * a document provider. When queried, a provider will return a single row 722b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * with columns defined by {@link Document}. 723ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * 724ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @see DocumentsProvider#queryDocument(String, String[]) 725ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @see #getDocumentId(Uri) 726ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey */ 727ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static Uri buildDocumentUri(String authority, String documentId) { 728ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) 729ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey .authority(authority).appendPath(PATH_DOCUMENT).appendPath(documentId).build(); 730ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey } 731ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey 732ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey /** 733b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * Build URI representing the target {@link Document#COLUMN_DOCUMENT_ID} in 734b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * a document provider. When queried, a provider will return a single row 735b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * with columns defined by {@link Document}. 736b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * <p> 737b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * However, instead of directly accessing the target document, the returned 738b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * URI will leverage access granted through a subtree URI, typically 739b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * returned by {@link Intent#ACTION_OPEN_DOCUMENT_TREE}. The target document 740b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * must be a descendant (child, grandchild, etc) of the subtree. 74121de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey * <p> 74221de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey * This is typically used to access documents under a user-selected 743b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * directory tree, since it doesn't require the user to separately confirm 744b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * each new document access. 74521de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey * 746b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * @param treeUri the subtree to leverage to gain access to the target 747b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * document. The target directory must be a descendant of this 748b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * subtree. 74921de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey * @param documentId the target document, which the caller may not have 75021de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey * direct access to. 751b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * @see Intent#ACTION_OPEN_DOCUMENT_TREE 75221de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey * @see DocumentsProvider#isChildDocument(String, String) 75321de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey * @see #buildDocumentUri(String, String) 75421de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey */ 755b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey public static Uri buildDocumentUriUsingTree(Uri treeUri, String documentId) { 75621de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) 757b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey .authority(treeUri.getAuthority()).appendPath(PATH_TREE) 758b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey .appendPath(getTreeDocumentId(treeUri)).appendPath(PATH_DOCUMENT) 75921de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey .appendPath(documentId).build(); 76021de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey } 76121de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey 76221de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey /** {@hide} */ 763b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey public static Uri buildDocumentUriMaybeUsingTree(Uri baseUri, String documentId) { 764b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey if (isTreeUri(baseUri)) { 765b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey return buildDocumentUriUsingTree(baseUri, documentId); 76621de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey } else { 76721de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey return buildDocumentUri(baseUri.getAuthority(), documentId); 76821de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey } 76921de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey } 77021de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey 77121de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey /** 772b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * Build URI representing the children of the target directory in a document 773ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * provider. When queried, a provider will return zero or more rows with 774ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * columns defined by {@link Document}. 775ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * 776ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @param parentDocumentId the document to return children for, which must 777ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * be a directory with MIME type of 778ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * {@link Document#MIME_TYPE_DIR}. 779ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @see DocumentsProvider#queryChildDocuments(String, String[], String) 780ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @see #getDocumentId(Uri) 781ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey */ 782ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static Uri buildChildDocumentsUri(String authority, String parentDocumentId) { 783ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(authority) 784ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey .appendPath(PATH_DOCUMENT).appendPath(parentDocumentId).appendPath(PATH_CHILDREN) 785ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey .build(); 786ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey } 787aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey 788ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey /** 789b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * Build URI representing the children of the target directory in a document 790b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * provider. When queried, a provider will return zero or more rows with 791b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * columns defined by {@link Document}. 792b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * <p> 793b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * However, instead of directly accessing the target directory, the returned 794b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * URI will leverage access granted through a subtree URI, typically 795b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * returned by {@link Intent#ACTION_OPEN_DOCUMENT_TREE}. The target 796b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * directory must be a descendant (child, grandchild, etc) of the subtree. 79721de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey * <p> 79821de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey * This is typically used to access documents under a user-selected 799b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * directory tree, since it doesn't require the user to separately confirm 800b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * each new document access. 80121de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey * 802b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * @param treeUri the subtree to leverage to gain access to the target 803b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * document. The target directory must be a descendant of this 804b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * subtree. 805b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * @param parentDocumentId the document to return children for, which the 806b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * caller may not have direct access to, and which must be a 807b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * directory with MIME type of {@link Document#MIME_TYPE_DIR}. 808b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * @see Intent#ACTION_OPEN_DOCUMENT_TREE 80921de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey * @see DocumentsProvider#isChildDocument(String, String) 81021de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey * @see #buildChildDocumentsUri(String, String) 81121de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey */ 812b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey public static Uri buildChildDocumentsUriUsingTree(Uri treeUri, String parentDocumentId) { 81321de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) 814b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey .authority(treeUri.getAuthority()).appendPath(PATH_TREE) 815b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey .appendPath(getTreeDocumentId(treeUri)).appendPath(PATH_DOCUMENT) 81621de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey .appendPath(parentDocumentId).appendPath(PATH_CHILDREN).build(); 81721de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey } 81821de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey 81921de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey /** 820e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * Build URI representing a search for matching documents under a specific 8213e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey * root in a document provider. When queried, a provider will return zero or 8223e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey * more rows with columns defined by {@link Document}. 823ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * 824ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @see DocumentsProvider#querySearchDocuments(String, String, String[]) 8253e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey * @see #getRootId(Uri) 826ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @see #getSearchDocumentsQuery(Uri) 827ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey */ 828ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static Uri buildSearchDocumentsUri( 8293e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey String authority, String rootId, String query) { 830ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(authority) 8313e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey .appendPath(PATH_ROOT).appendPath(rootId).appendPath(PATH_SEARCH) 832ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey .appendQueryParameter(PARAM_QUERY, query).build(); 833ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey } 834ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey 835ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey /** 836e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * Test if the given URI represents a {@link Document} backed by a 837ee2f7df9ee8a4f43c3b0858bad08a4f0a59a627fJeff Sharkey * {@link DocumentsProvider}. 83821de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey * 83921de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey * @see #buildDocumentUri(String, String) 840b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey * @see #buildDocumentUriUsingTree(Uri, String) 841ee2f7df9ee8a4f43c3b0858bad08a4f0a59a627fJeff Sharkey */ 842323ee3ec094b78b9f96a8ab55b5c3b291028eeafSteve McKay public static boolean isDocumentUri(Context context, @Nullable Uri uri) { 843323ee3ec094b78b9f96a8ab55b5c3b291028eeafSteve McKay if (isContentUri(uri) && isDocumentsProvider(context, uri.getAuthority())) { 844323ee3ec094b78b9f96a8ab55b5c3b291028eeafSteve McKay final List<String> paths = uri.getPathSegments(); 845323ee3ec094b78b9f96a8ab55b5c3b291028eeafSteve McKay if (paths.size() == 2) { 846323ee3ec094b78b9f96a8ab55b5c3b291028eeafSteve McKay return PATH_DOCUMENT.equals(paths.get(0)); 847323ee3ec094b78b9f96a8ab55b5c3b291028eeafSteve McKay } else if (paths.size() == 4) { 848323ee3ec094b78b9f96a8ab55b5c3b291028eeafSteve McKay return PATH_TREE.equals(paths.get(0)) && PATH_DOCUMENT.equals(paths.get(2)); 849323ee3ec094b78b9f96a8ab55b5c3b291028eeafSteve McKay } 850b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey } 851323ee3ec094b78b9f96a8ab55b5c3b291028eeafSteve McKay return false; 852323ee3ec094b78b9f96a8ab55b5c3b291028eeafSteve McKay } 853323ee3ec094b78b9f96a8ab55b5c3b291028eeafSteve McKay 854323ee3ec094b78b9f96a8ab55b5c3b291028eeafSteve McKay /** {@hide} */ 855323ee3ec094b78b9f96a8ab55b5c3b291028eeafSteve McKay public static boolean isRootUri(Context context, @Nullable Uri uri) { 856323ee3ec094b78b9f96a8ab55b5c3b291028eeafSteve McKay if (isContentUri(uri) && isDocumentsProvider(context, uri.getAuthority())) { 857323ee3ec094b78b9f96a8ab55b5c3b291028eeafSteve McKay final List<String> paths = uri.getPathSegments(); 858323ee3ec094b78b9f96a8ab55b5c3b291028eeafSteve McKay return (paths.size() == 2 && PATH_ROOT.equals(paths.get(0))); 859ee2f7df9ee8a4f43c3b0858bad08a4f0a59a627fJeff Sharkey } 86021de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey return false; 86121de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey } 86221de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey 86321de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey /** {@hide} */ 864323ee3ec094b78b9f96a8ab55b5c3b291028eeafSteve McKay public static boolean isContentUri(@Nullable Uri uri) { 865323ee3ec094b78b9f96a8ab55b5c3b291028eeafSteve McKay return uri != null && ContentResolver.SCHEME_CONTENT.equals(uri.getScheme()); 866323ee3ec094b78b9f96a8ab55b5c3b291028eeafSteve McKay } 867323ee3ec094b78b9f96a8ab55b5c3b291028eeafSteve McKay 8687db9c8193797ad8bca6d191d5bbb2ec2f7dd1868Tomasz Mikolajewski /** 8697db9c8193797ad8bca6d191d5bbb2ec2f7dd1868Tomasz Mikolajewski * Test if the given URI represents a {@link Document} tree. 8707db9c8193797ad8bca6d191d5bbb2ec2f7dd1868Tomasz Mikolajewski * 8717db9c8193797ad8bca6d191d5bbb2ec2f7dd1868Tomasz Mikolajewski * @see #buildTreeDocumentUri(String, String) 87290a753330d1cccdb844cedcb3e01ad642f2a5542Tomasz Mikolajewski * @see #getTreeDocumentId(Uri) 8737db9c8193797ad8bca6d191d5bbb2ec2f7dd1868Tomasz Mikolajewski */ 874b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey public static boolean isTreeUri(Uri uri) { 87521de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey final List<String> paths = uri.getPathSegments(); 876b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey return (paths.size() >= 2 && PATH_TREE.equals(paths.get(0))); 87721de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey } 878ee2f7df9ee8a4f43c3b0858bad08a4f0a59a627fJeff Sharkey 87921de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey private static boolean isDocumentsProvider(Context context, String authority) { 880d2e1e810a79ce0988df57c0bcbcd184e14a067b4Jeff Sharkey final Intent intent = new Intent(PROVIDER_INTERFACE); 881d2e1e810a79ce0988df57c0bcbcd184e14a067b4Jeff Sharkey final List<ResolveInfo> infos = context.getPackageManager() 882d2e1e810a79ce0988df57c0bcbcd184e14a067b4Jeff Sharkey .queryIntentContentProviders(intent, 0); 883d2e1e810a79ce0988df57c0bcbcd184e14a067b4Jeff Sharkey for (ResolveInfo info : infos) { 88421de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey if (authority.equals(info.providerInfo.authority)) { 885d2e1e810a79ce0988df57c0bcbcd184e14a067b4Jeff Sharkey return true; 886d2e1e810a79ce0988df57c0bcbcd184e14a067b4Jeff Sharkey } 887ee2f7df9ee8a4f43c3b0858bad08a4f0a59a627fJeff Sharkey } 888ee2f7df9ee8a4f43c3b0858bad08a4f0a59a627fJeff Sharkey return false; 889ee2f7df9ee8a4f43c3b0858bad08a4f0a59a627fJeff Sharkey } 890ee2f7df9ee8a4f43c3b0858bad08a4f0a59a627fJeff Sharkey 891ee2f7df9ee8a4f43c3b0858bad08a4f0a59a627fJeff Sharkey /** 892e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * Extract the {@link Root#COLUMN_ROOT_ID} from the given URI. 893ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey */ 894ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static String getRootId(Uri rootUri) { 895ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey final List<String> paths = rootUri.getPathSegments(); 89621de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey if (paths.size() >= 2 && PATH_ROOT.equals(paths.get(0))) { 89721de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey return paths.get(1); 898aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey } 89921de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey throw new IllegalArgumentException("Invalid URI: " + rootUri); 900ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey } 901aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey 902ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey /** 903e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * Extract the {@link Document#COLUMN_DOCUMENT_ID} from the given URI. 90421de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey * 90521de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey * @see #isDocumentUri(Context, Uri) 906ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey */ 907ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static String getDocumentId(Uri documentUri) { 908ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey final List<String> paths = documentUri.getPathSegments(); 90921de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey if (paths.size() >= 2 && PATH_DOCUMENT.equals(paths.get(0))) { 91021de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey return paths.get(1); 911ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey } 912b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey if (paths.size() >= 4 && PATH_TREE.equals(paths.get(0)) 91321de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey && PATH_DOCUMENT.equals(paths.get(2))) { 91421de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey return paths.get(3); 915ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey } 91621de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey throw new IllegalArgumentException("Invalid URI: " + documentUri); 91721de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey } 91821de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey 91921de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey /** 92021de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey * Extract the via {@link Document#COLUMN_DOCUMENT_ID} from the given URI. 92121de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey */ 922b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey public static String getTreeDocumentId(Uri documentUri) { 92321de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey final List<String> paths = documentUri.getPathSegments(); 924b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey if (paths.size() >= 2 && PATH_TREE.equals(paths.get(0))) { 92521de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey return paths.get(1); 92621de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey } 92721de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey throw new IllegalArgumentException("Invalid URI: " + documentUri); 928ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey } 929aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey 930ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey /** 931e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * Extract the search query from a URI built by 932ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * {@link #buildSearchDocumentsUri(String, String, String)}. 933ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey */ 934ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static String getSearchDocumentsQuery(Uri searchDocumentsUri) { 935ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey return searchDocumentsUri.getQueryParameter(PARAM_QUERY); 93620d96d8aff2193d548977e23ce5158657cac94e0Jeff Sharkey } 93720d96d8aff2193d548977e23ce5158657cac94e0Jeff Sharkey 9384ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey /** {@hide} */ 9394ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey public static Uri setManageMode(Uri uri) { 9404ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey return uri.buildUpon().appendQueryParameter(PARAM_MANAGE, "true").build(); 9414ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey } 9424ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey 9434ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey /** {@hide} */ 9444ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey public static boolean isManageMode(Uri uri) { 9454ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey return uri.getBooleanQueryParameter(PARAM_MANAGE, false); 9464ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey } 9474ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey 9489ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey /** 949e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * Return thumbnail representing the document at the given URI. Callers are 950ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * responsible for their own in-memory caching. 9519ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey * 952ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @param documentUri document to return thumbnail for, which must have 953ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * {@link Document#FLAG_SUPPORTS_THUMBNAIL} set. 954ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @param size optimal thumbnail size desired. A provider may return a 955ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * thumbnail of a different size, but never more than double the 956ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * requested size. 957e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * @param signal signal used to indicate if caller is no longer interested 958ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * in the thumbnail. 9599ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey * @return decoded thumbnail, or {@code null} if problem was encountered. 960ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @see DocumentsProvider#openDocumentThumbnail(String, Point, 961ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * android.os.CancellationSignal) 9629ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey */ 963ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static Bitmap getDocumentThumbnail( 964ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey ContentResolver resolver, Uri documentUri, Point size, CancellationSignal signal) { 965de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey final ContentProviderClient client = resolver.acquireUnstableContentProviderClient( 966de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey documentUri.getAuthority()); 967de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey try { 968de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey return getDocumentThumbnail(client, documentUri, size, signal); 9697aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey } catch (Exception e) { 97033819318f61224cdda45e5e9a70dc9cdb9f33911Jeff Sharkey if (!(e instanceof OperationCanceledException)) { 97133819318f61224cdda45e5e9a70dc9cdb9f33911Jeff Sharkey Log.w(TAG, "Failed to load thumbnail for " + documentUri + ": " + e); 97233819318f61224cdda45e5e9a70dc9cdb9f33911Jeff Sharkey } 973de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey return null; 974de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey } finally { 9757aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey ContentProviderClient.releaseQuietly(client); 976de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey } 977de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey } 978de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey 979de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey /** {@hide} */ 980de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey public static Bitmap getDocumentThumbnail( 981de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey ContentProviderClient client, Uri documentUri, Point size, CancellationSignal signal) 9827aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey throws RemoteException, IOException { 9836398343e83b3fd11dd6536cf6f390a52c1e19d2eJeff Sharkey final Bundle openOpts = new Bundle(); 9845b836f29a3f56f9d13b6004417330c41ec0c18aeJeff Sharkey openOpts.putParcelable(ContentResolver.EXTRA_SIZE, size); 9859ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey 9869d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey AssetFileDescriptor afd = null; 987c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey Bitmap bitmap = null; 9889ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey try { 989de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey afd = client.openTypedAssetFileDescriptor(documentUri, "image/*", openOpts, signal); 9909d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey 9919d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey final FileDescriptor fd = afd.getFileDescriptor(); 9926398343e83b3fd11dd6536cf6f390a52c1e19d2eJeff Sharkey final long offset = afd.getStartOffset(); 993de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey 994de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey // Try seeking on the returned FD, since it gives us the most 995de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey // optimal decode path; otherwise fall back to buffering. 996de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey BufferedInputStream is = null; 997de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey try { 99834385d352da19805ae948215e2edbeedd16b7941Elliott Hughes Os.lseek(fd, offset, SEEK_SET); 999de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey } catch (ErrnoException e) { 1000de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey is = new BufferedInputStream(new FileInputStream(fd), THUMBNAIL_BUFFER_SIZE); 1001de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey is.mark(THUMBNAIL_BUFFER_SIZE); 10026398343e83b3fd11dd6536cf6f390a52c1e19d2eJeff Sharkey } 10039d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey 10046398343e83b3fd11dd6536cf6f390a52c1e19d2eJeff Sharkey // We requested a rough thumbnail size, but the remote size may have 10056398343e83b3fd11dd6536cf6f390a52c1e19d2eJeff Sharkey // returned something giant, so defensively scale down as needed. 10066398343e83b3fd11dd6536cf6f390a52c1e19d2eJeff Sharkey final BitmapFactory.Options opts = new BitmapFactory.Options(); 10076398343e83b3fd11dd6536cf6f390a52c1e19d2eJeff Sharkey opts.inJustDecodeBounds = true; 1008de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey if (is != null) { 1009de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey BitmapFactory.decodeStream(is, null, opts); 10106398343e83b3fd11dd6536cf6f390a52c1e19d2eJeff Sharkey } else { 10116398343e83b3fd11dd6536cf6f390a52c1e19d2eJeff Sharkey BitmapFactory.decodeFileDescriptor(fd, null, opts); 10126398343e83b3fd11dd6536cf6f390a52c1e19d2eJeff Sharkey } 10139d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey 10146398343e83b3fd11dd6536cf6f390a52c1e19d2eJeff Sharkey final int widthSample = opts.outWidth / size.x; 10156398343e83b3fd11dd6536cf6f390a52c1e19d2eJeff Sharkey final int heightSample = opts.outHeight / size.y; 10169d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey 10176398343e83b3fd11dd6536cf6f390a52c1e19d2eJeff Sharkey opts.inJustDecodeBounds = false; 10186398343e83b3fd11dd6536cf6f390a52c1e19d2eJeff Sharkey opts.inSampleSize = Math.min(widthSample, heightSample); 1019de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey if (is != null) { 1020de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey is.reset(); 1021c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey bitmap = BitmapFactory.decodeStream(is, null, opts); 10226398343e83b3fd11dd6536cf6f390a52c1e19d2eJeff Sharkey } else { 1023de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey try { 102434385d352da19805ae948215e2edbeedd16b7941Elliott Hughes Os.lseek(fd, offset, SEEK_SET); 1025de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey } catch (ErrnoException e) { 1026de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey e.rethrowAsIOException(); 1027de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey } 1028c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey bitmap = BitmapFactory.decodeFileDescriptor(fd, null, opts); 1029c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey } 1030c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey 1031c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey // Transform the bitmap if requested. We use a side-channel to 1032c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey // communicate the orientation, since EXIF thumbnails don't contain 1033c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey // the rotation flags of the original image. 1034c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey final Bundle extras = afd.getExtras(); 1035c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey final int orientation = (extras != null) ? extras.getInt(EXTRA_ORIENTATION, 0) : 0; 1036c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey if (orientation != 0) { 1037c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey final int width = bitmap.getWidth(); 1038c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey final int height = bitmap.getHeight(); 1039c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey 1040c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey final Matrix m = new Matrix(); 1041c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey m.setRotate(orientation, width / 2, height / 2); 1042c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, m, false); 10436398343e83b3fd11dd6536cf6f390a52c1e19d2eJeff Sharkey } 10449ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey } finally { 10459d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey IoUtils.closeQuietly(afd); 10469ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey } 1047c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey 1048c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey return bitmap; 10499ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey } 10509ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey 10519ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey /** 1052ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * Create a new document with given MIME type and display name. 10535b83f854d9cbd6dc9e5a31892dbe8515b4c29683Jeff Sharkey * 1054ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @param parentDocumentUri directory with 1055ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * {@link Document#FLAG_DIR_SUPPORTS_CREATE} 1056aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * @param mimeType MIME type of new document 1057aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * @param displayName name of new document 1058aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * @return newly created document, or {@code null} if failed 10595b83f854d9cbd6dc9e5a31892dbe8515b4c29683Jeff Sharkey */ 1060ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static Uri createDocument(ContentResolver resolver, Uri parentDocumentUri, 1061ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey String mimeType, String displayName) { 1062de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey final ContentProviderClient client = resolver.acquireUnstableContentProviderClient( 1063de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey parentDocumentUri.getAuthority()); 1064de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey try { 1065de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey return createDocument(client, parentDocumentUri, mimeType, displayName); 10667aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey } catch (Exception e) { 10677aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey Log.w(TAG, "Failed to create document", e); 10687aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey return null; 1069de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey } finally { 10707aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey ContentProviderClient.releaseQuietly(client); 1071de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey } 1072de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey } 1073de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey 1074de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey /** {@hide} */ 1075de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey public static Uri createDocument(ContentProviderClient client, Uri parentDocumentUri, 10767aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey String mimeType, String displayName) throws RemoteException { 1077aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey final Bundle in = new Bundle(); 107821de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey in.putParcelable(DocumentsContract.EXTRA_URI, parentDocumentUri); 1079ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey in.putString(Document.COLUMN_MIME_TYPE, mimeType); 1080ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey in.putString(Document.COLUMN_DISPLAY_NAME, displayName); 1081aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey 10827aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey final Bundle out = client.call(METHOD_CREATE_DOCUMENT, null, in); 108321de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey return out.getParcelable(DocumentsContract.EXTRA_URI); 10845b83f854d9cbd6dc9e5a31892dbe8515b4c29683Jeff Sharkey } 10855b83f854d9cbd6dc9e5a31892dbe8515b4c29683Jeff Sharkey 1086d3afdeebeb9dcfbb5f24e4afac988e2e96de26deSteve McKay /** {@hide} */ 1087d3afdeebeb9dcfbb5f24e4afac988e2e96de26deSteve McKay public static boolean isChildDocument(ContentProviderClient client, Uri parentDocumentUri, 1088d3afdeebeb9dcfbb5f24e4afac988e2e96de26deSteve McKay Uri childDocumentUri) throws RemoteException { 1089d3afdeebeb9dcfbb5f24e4afac988e2e96de26deSteve McKay 1090d3afdeebeb9dcfbb5f24e4afac988e2e96de26deSteve McKay final Bundle in = new Bundle(); 1091d3afdeebeb9dcfbb5f24e4afac988e2e96de26deSteve McKay in.putParcelable(DocumentsContract.EXTRA_URI, parentDocumentUri); 1092d3afdeebeb9dcfbb5f24e4afac988e2e96de26deSteve McKay in.putParcelable(DocumentsContract.EXTRA_TARGET_URI, childDocumentUri); 1093d3afdeebeb9dcfbb5f24e4afac988e2e96de26deSteve McKay 1094d3afdeebeb9dcfbb5f24e4afac988e2e96de26deSteve McKay final Bundle out = client.call(METHOD_IS_CHILD_DOCUMENT, null, in); 1095d3afdeebeb9dcfbb5f24e4afac988e2e96de26deSteve McKay if (out == null) { 1096d3afdeebeb9dcfbb5f24e4afac988e2e96de26deSteve McKay throw new RemoteException("Failed to get a reponse from isChildDocument query."); 1097d3afdeebeb9dcfbb5f24e4afac988e2e96de26deSteve McKay } 1098d3afdeebeb9dcfbb5f24e4afac988e2e96de26deSteve McKay if (!out.containsKey(DocumentsContract.EXTRA_RESULT)) { 1099d3afdeebeb9dcfbb5f24e4afac988e2e96de26deSteve McKay throw new RemoteException("Response did not include result field.."); 1100d3afdeebeb9dcfbb5f24e4afac988e2e96de26deSteve McKay } 1101d3afdeebeb9dcfbb5f24e4afac988e2e96de26deSteve McKay return out.getBoolean(DocumentsContract.EXTRA_RESULT); 1102d3afdeebeb9dcfbb5f24e4afac988e2e96de26deSteve McKay } 1103d3afdeebeb9dcfbb5f24e4afac988e2e96de26deSteve McKay 11045b83f854d9cbd6dc9e5a31892dbe8515b4c29683Jeff Sharkey /** 1105b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey * Change the display name of an existing document. 1106b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey * <p> 1107b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey * If the underlying provider needs to create a new 1108b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey * {@link Document#COLUMN_DOCUMENT_ID} to represent the updated display 1109b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey * name, that new document is returned and the original document is no 1110b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey * longer valid. Otherwise, the original document is returned. 1111b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey * 1112b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey * @param documentUri document with {@link Document#FLAG_SUPPORTS_RENAME} 1113b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey * @param displayName updated name for document 1114b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey * @return the existing or new document after the rename, or {@code null} if 1115b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey * failed. 1116b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey */ 1117b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey public static Uri renameDocument(ContentResolver resolver, Uri documentUri, 1118b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey String displayName) { 1119b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey final ContentProviderClient client = resolver.acquireUnstableContentProviderClient( 1120b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey documentUri.getAuthority()); 1121b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey try { 1122b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey return renameDocument(client, documentUri, displayName); 1123b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey } catch (Exception e) { 1124b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey Log.w(TAG, "Failed to rename document", e); 1125b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey return null; 1126b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey } finally { 1127b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey ContentProviderClient.releaseQuietly(client); 1128b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey } 1129b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey } 1130b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey 1131b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey /** {@hide} */ 1132b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey public static Uri renameDocument(ContentProviderClient client, Uri documentUri, 1133b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey String displayName) throws RemoteException { 1134b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey final Bundle in = new Bundle(); 1135b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey in.putParcelable(DocumentsContract.EXTRA_URI, documentUri); 1136b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey in.putString(Document.COLUMN_DISPLAY_NAME, displayName); 1137b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey 1138b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey final Bundle out = client.call(METHOD_RENAME_DOCUMENT, null, in); 1139b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey final Uri outUri = out.getParcelable(DocumentsContract.EXTRA_URI); 1140b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey return (outUri != null) ? outUri : documentUri; 1141b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey } 1142b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey 1143b7e1255d5c8d9e4fa8dd389afb9f5aab35434df3Jeff Sharkey /** 1144aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * Delete the given document. 1145aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * 1146ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * @param documentUri document with {@link Document#FLAG_SUPPORTS_DELETE} 11477aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey * @return if the document was deleted successfully. 11485b83f854d9cbd6dc9e5a31892dbe8515b4c29683Jeff Sharkey */ 1149ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey public static boolean deleteDocument(ContentResolver resolver, Uri documentUri) { 1150de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey final ContentProviderClient client = resolver.acquireUnstableContentProviderClient( 1151de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey documentUri.getAuthority()); 1152de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey try { 11537aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey deleteDocument(client, documentUri); 11547aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey return true; 11557aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey } catch (Exception e) { 11567aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey Log.w(TAG, "Failed to delete document", e); 11577aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey return false; 1158de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey } finally { 11597aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey ContentProviderClient.releaseQuietly(client); 1160de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey } 1161de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey } 1162de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey 1163de2b22fbc60b29dd8af60cf05862066c04559dc0Jeff Sharkey /** {@hide} */ 11647aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey public static void deleteDocument(ContentProviderClient client, Uri documentUri) 11657aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey throws RemoteException { 1166aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey final Bundle in = new Bundle(); 116721de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey in.putParcelable(DocumentsContract.EXTRA_URI, documentUri); 1168aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey 11697aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey client.call(METHOD_DELETE_DOCUMENT, null, in); 11705b83f854d9cbd6dc9e5a31892dbe8515b4c29683Jeff Sharkey } 1171c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey 1172c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey /** 117374fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski * Copies the given document. 117474fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski * 117574fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski * @param sourceDocumentUri document with {@link Document#FLAG_SUPPORTS_COPY} 117674fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski * @param targetParentDocumentUri document which will become a parent of the source 117774fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski * document's copy. 117874fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski * @return the copied document, or {@code null} if failed. 117974fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski */ 118074fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski public static Uri copyDocument(ContentResolver resolver, Uri sourceDocumentUri, 118174fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski Uri targetParentDocumentUri) { 118274fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski final ContentProviderClient client = resolver.acquireUnstableContentProviderClient( 118374fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski sourceDocumentUri.getAuthority()); 118474fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski try { 118574fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski return copyDocument(client, sourceDocumentUri, targetParentDocumentUri); 118674fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski } catch (Exception e) { 118774fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski Log.w(TAG, "Failed to copy document", e); 118874fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski return null; 118974fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski } finally { 119074fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski ContentProviderClient.releaseQuietly(client); 119174fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski } 119274fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski } 119374fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski 119474fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski /** {@hide} */ 119574fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski public static Uri copyDocument(ContentProviderClient client, Uri sourceDocumentUri, 119674fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski Uri targetParentDocumentUri) throws RemoteException { 119774fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski final Bundle in = new Bundle(); 119874fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski in.putParcelable(DocumentsContract.EXTRA_URI, sourceDocumentUri); 119974fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski in.putParcelable(DocumentsContract.EXTRA_TARGET_URI, targetParentDocumentUri); 120074fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski 120174fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski final Bundle out = client.call(METHOD_COPY_DOCUMENT, null, in); 120274fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski return out.getParcelable(DocumentsContract.EXTRA_URI); 120374fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski } 120474fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski 120574fe1816e84fc097adc5af1b6e866b4a219dca91Tomasz Mikolajewski /** 1206a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski * Moves the given document under a new parent. 1207a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski * 1208a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski * @param sourceDocumentUri document with {@link Document#FLAG_SUPPORTS_MOVE} 1209d46ecbcc5322cf817e64591e985f1f2a6167e9a7Tomasz Mikolajewski * @param sourceParentDocumentUri parent document of the document to move. 1210a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski * @param targetParentDocumentUri document which will become a new parent of the source 1211a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski * document. 1212a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski * @return the moved document, or {@code null} if failed. 1213a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski */ 1214a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski public static Uri moveDocument(ContentResolver resolver, Uri sourceDocumentUri, 1215d46ecbcc5322cf817e64591e985f1f2a6167e9a7Tomasz Mikolajewski Uri sourceParentDocumentUri, Uri targetParentDocumentUri) { 1216a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski final ContentProviderClient client = resolver.acquireUnstableContentProviderClient( 1217a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski sourceDocumentUri.getAuthority()); 1218a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski try { 1219dcb4efeed54dd17c9af1fe75625d179d3f042f2bTomasz Mikolajewski return moveDocument(client, sourceDocumentUri, sourceParentDocumentUri, 1220d46ecbcc5322cf817e64591e985f1f2a6167e9a7Tomasz Mikolajewski targetParentDocumentUri); 1221a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski } catch (Exception e) { 1222a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski Log.w(TAG, "Failed to move document", e); 1223a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski return null; 1224a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski } finally { 1225a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski ContentProviderClient.releaseQuietly(client); 1226a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski } 1227a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski } 1228a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski 1229a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski /** {@hide} */ 1230a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski public static Uri moveDocument(ContentProviderClient client, Uri sourceDocumentUri, 1231d46ecbcc5322cf817e64591e985f1f2a6167e9a7Tomasz Mikolajewski Uri sourceParentDocumentUri, Uri targetParentDocumentUri) throws RemoteException { 1232a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski final Bundle in = new Bundle(); 1233a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski in.putParcelable(DocumentsContract.EXTRA_URI, sourceDocumentUri); 1234d46ecbcc5322cf817e64591e985f1f2a6167e9a7Tomasz Mikolajewski in.putParcelable(DocumentsContract.EXTRA_PARENT_URI, sourceParentDocumentUri); 1235a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski in.putParcelable(DocumentsContract.EXTRA_TARGET_URI, targetParentDocumentUri); 1236a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski 1237a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski final Bundle out = client.call(METHOD_MOVE_DOCUMENT, null, in); 1238a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski return out.getParcelable(DocumentsContract.EXTRA_URI); 1239a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski } 1240a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski 1241a375a9988419791649ed7f42b662f1afe5953982Tomasz Mikolajewski /** 1242cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski * Removes the given document from a parent directory. 1243cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski * 1244cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski * <p>In contrast to {@link #deleteDocument} it requires specifying the parent. 1245cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski * This method is especially useful if the document can be in multiple parents. 1246cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski * 1247cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski * @param documentUri document with {@link Document#FLAG_SUPPORTS_REMOVE} 1248cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski * @param parentDocumentUri parent document of the document to remove. 1249cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski * @return true if the document was removed successfully. 1250cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski */ 1251cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski public static boolean removeDocument(ContentResolver resolver, Uri documentUri, 1252cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski Uri parentDocumentUri) { 1253cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski final ContentProviderClient client = resolver.acquireUnstableContentProviderClient( 1254cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski documentUri.getAuthority()); 1255cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski try { 1256cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski removeDocument(client, documentUri, parentDocumentUri); 1257cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski return true; 1258cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski } catch (Exception e) { 1259cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski Log.w(TAG, "Failed to remove document", e); 1260cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski return false; 1261cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski } finally { 1262cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski ContentProviderClient.releaseQuietly(client); 1263cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski } 1264cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski } 1265cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski 1266cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski /** {@hide} */ 1267cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski public static void removeDocument(ContentProviderClient client, Uri documentUri, 1268cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski Uri parentDocumentUri) throws RemoteException { 1269cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski final Bundle in = new Bundle(); 1270cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski in.putParcelable(DocumentsContract.EXTRA_URI, documentUri); 1271cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski in.putParcelable(DocumentsContract.EXTRA_PARENT_URI, parentDocumentUri); 1272cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski 1273cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski client.call(METHOD_REMOVE_DOCUMENT, null, in); 1274cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski } 1275cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski 1276cbcd39488b4bddfaa84dfe378ede2f707aedd6caTomasz Mikolajewski /** 1277c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey * Open the given image for thumbnail purposes, using any embedded EXIF 1278c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey * thumbnail if available, and providing orientation hints from the parent 1279c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey * image. 1280c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey * 1281c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey * @hide 1282c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey */ 1283c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey public static AssetFileDescriptor openImageThumbnail(File file) throws FileNotFoundException { 1284c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey final ParcelFileDescriptor pfd = ParcelFileDescriptor.open( 1285c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey file, ParcelFileDescriptor.MODE_READ_ONLY); 1286c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey Bundle extras = null; 1287c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey 1288c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey try { 1289c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey final ExifInterface exif = new ExifInterface(file.getAbsolutePath()); 1290c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey 1291c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey switch (exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, -1)) { 1292c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey case ExifInterface.ORIENTATION_ROTATE_90: 1293c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey extras = new Bundle(1); 1294c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey extras.putInt(EXTRA_ORIENTATION, 90); 1295c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey break; 1296c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey case ExifInterface.ORIENTATION_ROTATE_180: 1297c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey extras = new Bundle(1); 1298c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey extras.putInt(EXTRA_ORIENTATION, 180); 1299c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey break; 1300c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey case ExifInterface.ORIENTATION_ROTATE_270: 1301c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey extras = new Bundle(1); 1302c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey extras.putInt(EXTRA_ORIENTATION, 270); 1303c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey break; 1304c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey } 1305c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey 1306c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey final long[] thumb = exif.getThumbnailRange(); 1307c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey if (thumb != null) { 1308c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey return new AssetFileDescriptor(pfd, thumb[0], thumb[1], extras); 1309c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey } 1310c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey } catch (IOException e) { 1311c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey } 1312c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey 1313c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey return new AssetFileDescriptor(pfd, 0, AssetFileDescriptor.UNKNOWN_LENGTH, extras); 1314c1c8f3f97d344a24bfddcb56a8be05e7e2fabe9eJeff Sharkey } 13159ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey} 1316