Kamis, 12 September 2019

Class FileUtils Untuk Mendapatkan File Real Path Pada Pemrograman Android

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