1package eu.siacs.conversations.utils;
2
3import android.annotation.SuppressLint;
4import android.content.ContentUris;
5import android.content.Context;
6import android.database.Cursor;
7import android.net.Uri;
8import android.os.Build;
9import android.os.Environment;
10import android.provider.DocumentsContract;
11import android.provider.MediaStore;
12
13import java.io.File;
14
15public class FileUtils {
16
17 private static final Uri PUBLIC_DOWNLOADS = Uri.parse("content://downloads/public_downloads");
18
19 /**
20 * Get a file path from a Uri. This will get the the path for Storage Access
21 * Framework Documents, as well as the _data field for the MediaStore and
22 * other file-based ContentProviders.
23 *
24 * @param context The context.
25 * @param uri The Uri to query.
26 * @author paulburke
27 */
28 @SuppressLint("NewApi")
29 public static String getPath(final Context context, final Uri uri) {
30 if (uri == null) {
31 return null;
32 }
33
34 final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
35
36 // DocumentProvider
37 if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
38 // ExternalStorageProvider
39 if (isExternalStorageDocument(uri)) {
40 final String docId = DocumentsContract.getDocumentId(uri);
41 final String[] split = docId.split(":");
42 final String type = split[0];
43
44 if ("primary".equalsIgnoreCase(type)) {
45 return Environment.getExternalStorageDirectory() + "/" + split[1];
46 }
47
48 // TODO handle non-primary volumes
49 }
50 // DownloadsProvider
51 else if (isDownloadsDocument(uri)) {
52
53 final String id = DocumentsContract.getDocumentId(uri);
54 try {
55 final Uri contentUri = ContentUris.withAppendedId(PUBLIC_DOWNLOADS, Long.valueOf(id));
56 return getDataColumn(context, contentUri, null, null);
57 } catch (NumberFormatException e) {
58 return null;
59 }
60 }
61 // MediaProvider
62 else if (isMediaDocument(uri)) {
63 final String docId = DocumentsContract.getDocumentId(uri);
64 final String[] split = docId.split(":");
65 final String type = split[0];
66
67 Uri contentUri = null;
68 if ("image".equals(type)) {
69 contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
70 } else if ("video".equals(type)) {
71 contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
72 } else if ("audio".equals(type)) {
73 contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
74 }
75
76 final String selection = "_id=?";
77 final String[] selectionArgs = new String[]{
78 split[1]
79 };
80
81 return getDataColumn(context, contentUri, selection, selectionArgs);
82 }
83 }
84 // MediaStore (and general)
85 else if ("content".equalsIgnoreCase(uri.getScheme())) {
86 String path = getDataColumn(context, uri, null, null);
87 if (path != null) {
88 File file = new File(path);
89 if (!file.canRead()) {
90 return null;
91 }
92 }
93 return path;
94 }
95 // File
96 else if ("file".equalsIgnoreCase(uri.getScheme())) {
97 return uri.getPath();
98 }
99
100 return null;
101 }
102
103 /**
104 * Get the value of the data column for this Uri. This is useful for
105 * MediaStore Uris, and other file-based ContentProviders.
106 *
107 * @param context The context.
108 * @param uri The Uri to query.
109 * @param selection (Optional) Filter used in the query.
110 * @param selectionArgs (Optional) Selection arguments used in the query.
111 * @return The value of the _data column, which is typically a file path.
112 */
113 public static String getDataColumn(Context context, Uri uri, String selection,
114 String[] selectionArgs) {
115
116 Cursor cursor = null;
117 final String column = "_data";
118 final String[] projection = {
119 column
120 };
121
122 try {
123 cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,null);
124 if (cursor != null && cursor.moveToFirst()) {
125 final int column_index = cursor.getColumnIndexOrThrow(column);
126 return cursor.getString(column_index);
127 }
128 } catch(Exception e) {
129 return null;
130 } finally {
131 if (cursor != null) {
132 cursor.close();
133 }
134 }
135 return null;
136 }
137
138
139 /**
140 * @param uri The Uri to check.
141 * @return Whether the Uri authority is ExternalStorageProvider.
142 */
143 public static boolean isExternalStorageDocument(Uri uri) {
144 return "com.android.externalstorage.documents".equals(uri.getAuthority());
145 }
146
147 /**
148 * @param uri The Uri to check.
149 * @return Whether the Uri authority is DownloadsProvider.
150 */
151 public static boolean isDownloadsDocument(Uri uri) {
152 return "com.android.providers.downloads.documents".equals(uri.getAuthority());
153 }
154
155 /**
156 * @param uri The Uri to check.
157 * @return Whether the Uri authority is MediaProvider.
158 */
159 public static boolean isMediaDocument(Uri uri) {
160 return "com.android.providers.media.documents".equals(uri.getAuthority());
161 }
162}