Ketika membuat aplikasi pada OS Android, kadang kala kita membutuhkan operasi baca dan tulis suatu berkas (file) di Androd. Penulis pernah menghadapi masalah ini, ketika mengambil suatu berkas, eh ternyata Android memberikan alamat path (alamat yang langsung menunjukkan letaknya) berkas tersebut dalam bentuk URI, bukan path langsung.
Setelah berselancar diinternet, akhirnya penulis mendapatkan fungsi FileUtils yang di-posting oleh Satyawan Hajare di alamat https://stackoverflow.com/questions/17546101/get-real-path-for-uri-android. Di forum Stack Overflow ini dijelaskan dengan detail cara penggunaan serta kode sumbernya. Tetapi tidak ada salahnya penulis juga reposting kode sumber tersebut disini, berikut ini kode sumber FileUtils.java :
1: import android.annotation.SuppressLint;
2: import android.content.ContentUris;
3: import android.content.Context;
4: import android.database.Cursor;
5: import android.net.Uri;
6: import android.os.Build;
7: import android.os.Environment;
8: import android.provider.DocumentsContract;
9: import android.provider.MediaStore;
10: import android.provider.OpenableColumns;
11: import android.text.TextUtils;
12: import android.util.Log;
13: import java.io.File;
14: import java.io.FileOutputStream;
15: import java.io.InputStream;
16: import java.util.List;
17: public class FileUtils {
18: private static Uri contentUri = null;
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.<br>
23: * <br>
24: * Callers should check whether the path is local before assuming it
25: * represents a local file.
26: *
27: * @param context The context.
28: * @param uri The Uri to query.
29: */
30: @SuppressLint("NewApi")
31: public static String getPath(final Context context, final Uri uri) {
32: // check here to KITKAT or new version
33: final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
34: String selection = null;
35: String[] selectionArgs = null;
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: String fullPath = getPathFromExtSD(split);
44: if (fullPath != "") {
45: return fullPath;
46: } else {
47: return null;
48: }
49: }
50: // DownloadsProvider
51: else if (isDownloadsDocument(uri)) {
52: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
53: final String id;
54: Cursor cursor = null;
55: try {
56: cursor = context.getContentResolver().query(uri, new String[]{MediaStore.MediaColumns.DISPLAY_NAME}, null, null, null);
57: if (cursor != null && cursor.moveToFirst()) {
58: String fileName = cursor.getString(0);
59: String path = Environment.getExternalStorageDirectory().toString() + "/Download/" + fileName;
60: if (!TextUtils.isEmpty(path)) {
61: return path;
62: }
63: }
64: } finally {
65: if (cursor != null)
66: cursor.close();
67: }
68: id = DocumentsContract.getDocumentId(uri);
69: if (!TextUtils.isEmpty(id)) {
70: if (id.startsWith("raw:")) {
71: return id.replaceFirst("raw:", "");
72: }
73: String[] contentUriPrefixesToTry = new String[]{
74: "content://downloads/public_downloads",
75: "content://downloads/my_downloads"
76: };
77: for (String contentUriPrefix : contentUriPrefixesToTry) {
78: try {
79: final Uri contentUri = ContentUris.withAppendedId(Uri.parse(contentUriPrefix), Long.valueOf(id));
80: return getDataColumn(context, contentUri, null, null);
81: } catch (NumberFormatException e) {
82: //In Android 8 and Android P the id is not a number
83: return uri.getPath().replaceFirst("^/document/raw:", "").replaceFirst("^raw:", "");
84: }
85: }
86: }
87: } else {
88: final String id = DocumentsContract.getDocumentId(uri);
89: //final boolean isOreo = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
90: if (id.startsWith("raw:")) {
91: return id.replaceFirst("raw:", "");
92: }
93: try {
94: contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
95: } catch (NumberFormatException e) {
96: e.printStackTrace();
97: }
98: if (contentUri != null) {
99: return getDataColumn(context, contentUri, null, null);
100: }
101: }
102: }
103: // MediaProvider
104: else if (isMediaDocument(uri)) {
105: final String docId = DocumentsContract.getDocumentId(uri);
106: final String[] split = docId.split(":");
107: final String type = split[0];
108: Uri contentUri = null;
109: if ("image".equals(type)) {
110: contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
111: } else if ("video".equals(type)) {
112: contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
113: } else if ("audio".equals(type)) {
114: contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
115: }
116: selection = "_id=?";
117: selectionArgs = new String[]{split[1]};
118: return getDataColumn(context, contentUri, selection, selectionArgs);
119: } else if (isGoogleDriveUri(uri)) {
120: return getDriveFilePath(uri, context);
121: }
122: }
123: // MediaStore (and general)
124: else if ("content".equalsIgnoreCase(uri.getScheme())) {
125: if (isGooglePhotosUri(uri)) {
126: return uri.getLastPathSegment();
127: }
128: if (isGoogleDriveUri(uri)) {
129: return getDriveFilePath(uri, context);
130: }
131: if (Build.VERSION.SDK_INT == Build.VERSION_CODES.N) {
132: // return getFilePathFromURI(context,uri);
133: return getMediaFilePathForN(uri, context);
134: // return getRealPathFromURI(context,uri);
135: } else {
136: return getDataColumn(context, uri, null, null);
137: }
138: }
139: // File
140: else if ("file".equalsIgnoreCase(uri.getScheme())) {
141: return uri.getPath();
142: }
143: return null;
144: }
145: /**
146: * Check if a file exists on device
147: *
148: * @param filePath The absolute file path
149: */
150: private static boolean fileExists(String filePath) {
151: File file = new File(filePath);
152: return file.exists();
153: }
154: /**
155: * Get full file path from external storage
156: *
157: * @param pathData The storage type and the relative path
158: */
159: private static String getPathFromExtSD(String[] pathData) {
160: final String type = pathData[0];
161: final String relativePath = "/" + pathData[1];
162: String fullPath = "";
163: // on my Sony devices (4.4.4 & 5.1.1), `type` is a dynamic string
164: // something like "71F8-2C0A", some kind of unique id per storage
165: // don't know any API that can get the root path of that storage based on its id.
166: //
167: // so no "primary" type, but let the check here for other devices
168: if ("primary".equalsIgnoreCase(type)) {
169: fullPath = Environment.getExternalStorageDirectory() + relativePath;
170: if (fileExists(fullPath)) {
171: return fullPath;
172: }
173: }
174: // Environment.isExternalStorageRemovable() is `true` for external and internal storage
175: // so we cannot relay on it.
176: //
177: // instead, for each possible path, check if file exists
178: // we'll start with secondary storage as this could be our (physically) removable sd card
179: fullPath = System.getenv("SECONDARY_STORAGE") + relativePath;
180: if (fileExists(fullPath)) {
181: return fullPath;
182: }
183: fullPath = System.getenv("EXTERNAL_STORAGE") + relativePath;
184: if (fileExists(fullPath)) {
185: return fullPath;
186: }
187: return fullPath;
188: }
189: private static String getDriveFilePath(Uri uri, Context context) {
190: Uri returnUri = uri;
191: Cursor returnCursor = context.getContentResolver().query(returnUri, null, null, null, null);
192: /*
193: * Get the column indexes of the data in the Cursor,
194: * * move to the first row in the Cursor, get the data,
195: * * and display it.
196: * */
197: int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
198: int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
199: returnCursor.moveToFirst();
200: String name = (returnCursor.getString(nameIndex));
201: String size = (Long.toString(returnCursor.getLong(sizeIndex)));
202: File file = new File(context.getCacheDir(), name);
203: try {
204: InputStream inputStream = context.getContentResolver().openInputStream(uri);
205: FileOutputStream outputStream = new FileOutputStream(file);
206: int read = 0;
207: int maxBufferSize = 1 * 1024 * 1024;
208: int bytesAvailable = inputStream.available();
209: //int bufferSize = 1024;
210: int bufferSize = Math.min(bytesAvailable, maxBufferSize);
211: final byte[] buffers = new byte[bufferSize];
212: while ((read = inputStream.read(buffers)) != -1) {
213: outputStream.write(buffers, 0, read);
214: }
215: Log.e("File Size", "Size " + file.length());
216: inputStream.close();
217: outputStream.close();
218: Log.e("File Path", "Path " + file.getPath());
219: Log.e("File Size", "Size " + file.length());
220: } catch (Exception e) {
221: Log.e("Exception", e.getMessage());
222: }
223: return file.getPath();
224: }
225: private static String getMediaFilePathForN(Uri uri, Context context) {
226: Uri returnUri = uri;
227: Cursor returnCursor = context.getContentResolver().query(returnUri, null, null, null, null);
228: /*
229: * Get the column indexes of the data in the Cursor,
230: * * move to the first row in the Cursor, get the data,
231: * * and display it.
232: * */
233: int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
234: int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
235: returnCursor.moveToFirst();
236: String name = (returnCursor.getString(nameIndex));
237: String size = (Long.toString(returnCursor.getLong(sizeIndex)));
238: File file = new File(context.getFilesDir(), name);
239: try {
240: InputStream inputStream = context.getContentResolver().openInputStream(uri);
241: FileOutputStream outputStream = new FileOutputStream(file);
242: int read = 0;
243: int maxBufferSize = 1 * 1024 * 1024;
244: int bytesAvailable = inputStream.available();
245: //int bufferSize = 1024;
246: int bufferSize = Math.min(bytesAvailable, maxBufferSize);
247: final byte[] buffers = new byte[bufferSize];
248: while ((read = inputStream.read(buffers)) != -1) {
249: outputStream.write(buffers, 0, read);
250: }
251: Log.e("File Size", "Size " + file.length());
252: inputStream.close();
253: outputStream.close();
254: Log.e("File Path", "Path " + file.getPath());
255: Log.e("File Size", "Size " + file.length());
256: } catch (Exception e) {
257: Log.e("Exception", e.getMessage());
258: }
259: return file.getPath();
260: }
261: private static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
262: Cursor cursor = null;
263: final String column = "_data";
264: final String[] projection = {column};
265: try {
266: cursor = context.getContentResolver().query(uri, projection,
267: selection, selectionArgs, null);
268: if (cursor != null && cursor.moveToFirst()) {
269: final int index = cursor.getColumnIndexOrThrow(column);
270: return cursor.getString(index);
271: }
272: } finally {
273: if (cursor != null)
274: cursor.close();
275: }
276: return null;
277: }
278: /**
279: * @param uri - The Uri to check.
280: * @return - Whether the Uri authority is ExternalStorageProvider.
281: */
282: private static boolean isExternalStorageDocument(Uri uri) {
283: return "com.android.externalstorage.documents".equals(uri.getAuthority());
284: }
285: /**
286: * @param uri - The Uri to check.
287: * @return - Whether the Uri authority is DownloadsProvider.
288: */
289: private static boolean isDownloadsDocument(Uri uri) {
290: return "com.android.providers.downloads.documents".equals(uri.getAuthority());
291: }
292: /**
293: * @param uri - The Uri to check.
294: * @return - Whether the Uri authority is MediaProvider.
295: */
296: private static boolean isMediaDocument(Uri uri) {
297: return "com.android.providers.media.documents".equals(uri.getAuthority());
298: }
299: /**
300: * @param uri - The Uri to check.
301: * @return - Whether the Uri authority is Google Photos.
302: */
303: private static boolean isGooglePhotosUri(Uri uri) {
304: return "com.google.android.apps.photos.content".equals(uri.getAuthority());
305: }
306: /**
307: * @param uri The Uri to check.
308: * @return Whether the Uri authority is Google Drive.
309: */
310: private static boolean isGoogleDriveUri(Uri uri) {
311: return "com.google.android.apps.docs.storage".equals(uri.getAuthority()) || "com.google.android.apps.docs.storage.legacy".equals(uri.getAuthority());
312: }
313: }
Cara penggunaan class FileUtils sebagai berikut:
/* Untuk menyimpan lokasi file yang dipilih */
Uri pilihFile=null;
/* Untuk menyimpan nama file dan path nya */
String pathFile;
// Ambil Uri file
pilihFile = data.getData();
// Cek, apakah isi pilihFile berisi Uri?
if (pilihFile != null) {
// Jika keduanya YA , kerjakan perintah berikut ini:
/* Panggil class FileUtils untuk mendapatkan path dari berkas yang akan digunakan dan
simpan hasilnya di variabel pathFile */
pathFile = FileUtils.getPath(getActivity(),pilihFile);
}
Selamat menggunakan class FileUtil ini diprogram Android buatan anda sendiri...
Tidak ada komentar:
Posting Komentar