• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.support.v4.provider;
18 
19 import android.content.ContentResolver;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.pm.PackageManager;
23 import android.database.Cursor;
24 import android.net.Uri;
25 import android.provider.DocumentsContract;
26 import android.text.TextUtils;
27 import android.util.Log;
28 
29 class DocumentsContractApi19 {
30     private static final String TAG = "DocumentFile";
31 
isDocumentUri(Context context, Uri self)32     public static boolean isDocumentUri(Context context, Uri self) {
33         return DocumentsContract.isDocumentUri(context, self);
34     }
35 
getName(Context context, Uri self)36     public static String getName(Context context, Uri self) {
37         return queryForString(context, self, DocumentsContract.Document.COLUMN_DISPLAY_NAME, null);
38     }
39 
getRawType(Context context, Uri self)40     private static String getRawType(Context context, Uri self) {
41         return queryForString(context, self, DocumentsContract.Document.COLUMN_MIME_TYPE, null);
42     }
43 
getType(Context context, Uri self)44     public static String getType(Context context, Uri self) {
45         final String rawType = getRawType(context, self);
46         if (DocumentsContract.Document.MIME_TYPE_DIR.equals(rawType)) {
47             return null;
48         } else {
49             return rawType;
50         }
51     }
52 
isDirectory(Context context, Uri self)53     public static boolean isDirectory(Context context, Uri self) {
54         return DocumentsContract.Document.MIME_TYPE_DIR.equals(getRawType(context, self));
55     }
56 
isFile(Context context, Uri self)57     public static boolean isFile(Context context, Uri self) {
58         final String type = getRawType(context, self);
59         if (DocumentsContract.Document.MIME_TYPE_DIR.equals(type) || TextUtils.isEmpty(type)) {
60             return false;
61         } else {
62             return true;
63         }
64     }
65 
lastModified(Context context, Uri self)66     public static long lastModified(Context context, Uri self) {
67         return queryForLong(context, self, DocumentsContract.Document.COLUMN_LAST_MODIFIED, 0);
68     }
69 
length(Context context, Uri self)70     public static long length(Context context, Uri self) {
71         return queryForLong(context, self, DocumentsContract.Document.COLUMN_SIZE, 0);
72     }
73 
canRead(Context context, Uri self)74     public static boolean canRead(Context context, Uri self) {
75         // Ignore if grant doesn't allow read
76         if (context.checkCallingOrSelfUriPermission(self, Intent.FLAG_GRANT_READ_URI_PERMISSION)
77                 != PackageManager.PERMISSION_GRANTED) {
78             return false;
79         }
80 
81         // Ignore documents without MIME
82         if (TextUtils.isEmpty(getRawType(context, self))) {
83             return false;
84         }
85 
86         return true;
87     }
88 
canWrite(Context context, Uri self)89     public static boolean canWrite(Context context, Uri self) {
90         // Ignore if grant doesn't allow write
91         if (context.checkCallingOrSelfUriPermission(self, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
92                 != PackageManager.PERMISSION_GRANTED) {
93             return false;
94         }
95 
96         final String type = getRawType(context, self);
97         final int flags = queryForInt(context, self, DocumentsContract.Document.COLUMN_FLAGS, 0);
98 
99         // Ignore documents without MIME
100         if (TextUtils.isEmpty(type)) {
101             return false;
102         }
103 
104         // Deletable documents considered writable
105         if ((flags & DocumentsContract.Document.FLAG_SUPPORTS_DELETE) != 0) {
106             return true;
107         }
108 
109         if (DocumentsContract.Document.MIME_TYPE_DIR.equals(type)
110                 && (flags & DocumentsContract.Document.FLAG_DIR_SUPPORTS_CREATE) != 0) {
111             // Directories that allow create considered writable
112             return true;
113         } else if (!TextUtils.isEmpty(type)
114                 && (flags & DocumentsContract.Document.FLAG_SUPPORTS_WRITE) != 0) {
115             // Writable normal files considered writable
116             return true;
117         }
118 
119         return false;
120     }
121 
delete(Context context, Uri self)122     public static boolean delete(Context context, Uri self) {
123         return DocumentsContract.deleteDocument(context.getContentResolver(), self);
124     }
125 
exists(Context context, Uri self)126     public static boolean exists(Context context, Uri self) {
127         final ContentResolver resolver = context.getContentResolver();
128 
129         Cursor c = null;
130         try {
131             c = resolver.query(self, new String[] {
132                     DocumentsContract.Document.COLUMN_DOCUMENT_ID }, null, null, null);
133             return c.getCount() > 0;
134         } catch (Exception e) {
135             Log.w(TAG, "Failed query: " + e);
136             return false;
137         } finally {
138             closeQuietly(c);
139         }
140     }
141 
queryForString(Context context, Uri self, String column, String defaultValue)142     private static String queryForString(Context context, Uri self, String column,
143             String defaultValue) {
144         final ContentResolver resolver = context.getContentResolver();
145 
146         Cursor c = null;
147         try {
148             c = resolver.query(self, new String[] { column }, null, null, null);
149             if (c.moveToFirst() && !c.isNull(0)) {
150                 return c.getString(0);
151             } else {
152                 return defaultValue;
153             }
154         } catch (Exception e) {
155             Log.w(TAG, "Failed query: " + e);
156             return defaultValue;
157         } finally {
158             closeQuietly(c);
159         }
160     }
161 
queryForInt(Context context, Uri self, String column, int defaultValue)162     private static int queryForInt(Context context, Uri self, String column,
163             int defaultValue) {
164         return (int) queryForLong(context, self, column, defaultValue);
165     }
166 
queryForLong(Context context, Uri self, String column, long defaultValue)167     private static long queryForLong(Context context, Uri self, String column,
168             long defaultValue) {
169         final ContentResolver resolver = context.getContentResolver();
170 
171         Cursor c = null;
172         try {
173             c = resolver.query(self, new String[] { column }, null, null, null);
174             if (c.moveToFirst() && !c.isNull(0)) {
175                 return c.getLong(0);
176             } else {
177                 return defaultValue;
178             }
179         } catch (Exception e) {
180             Log.w(TAG, "Failed query: " + e);
181             return defaultValue;
182         } finally {
183             closeQuietly(c);
184         }
185     }
186 
closeQuietly(AutoCloseable closeable)187     private static void closeQuietly(AutoCloseable closeable) {
188         if (closeable != null) {
189             try {
190                 closeable.close();
191             } catch (RuntimeException rethrown) {
192                 throw rethrown;
193             } catch (Exception ignored) {
194             }
195         }
196     }
197 }
198