Created
March 12, 2019 11:22
-
-
Save abhinav272/925397d26ea86c23e62e79ab96ba1f50 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright (C) 2007-2008 OpenIntents.org | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
package com.ipaulpro.afilechooser.utils; | |
import android.content.ContentResolver; | |
import android.content.ContentUris; | |
import android.content.Context; | |
import android.content.Intent; | |
import android.database.Cursor; | |
import android.database.DatabaseUtils; | |
import android.graphics.Bitmap; | |
import android.net.Uri; | |
import android.os.Build; | |
import android.os.Environment; | |
import android.provider.DocumentsContract; | |
import android.provider.MediaStore; | |
import android.util.Log; | |
import android.webkit.MimeTypeMap; | |
import com.ianhanniballake.localstorage.LocalStorageProvider; | |
import java.io.File; | |
import java.io.FileFilter; | |
import java.text.DecimalFormat; | |
import java.util.Comparator; | |
/** | |
* @version 2009-07-03 | |
* @author Peli | |
* @version 2013-12-11 | |
* @author paulburke (ipaulpro) | |
*/ | |
public class FileUtils { | |
private FileUtils() {} //private constructor to enforce Singleton pattern | |
/** TAG for log messages. */ | |
static final String TAG = "FileUtils"; | |
private static final boolean DEBUG = false; // Set to true to enable logging | |
public static final String MIME_TYPE_AUDIO = "audio/*"; | |
public static final String MIME_TYPE_TEXT = "text/*"; | |
public static final String MIME_TYPE_IMAGE = "image/*"; | |
public static final String MIME_TYPE_VIDEO = "video/*"; | |
public static final String MIME_TYPE_APP = "application/*"; | |
public static final String HIDDEN_PREFIX = "."; | |
/** | |
* Gets the extension of a file name, like ".png" or ".jpg". | |
* | |
* @param uri | |
* @return Extension including the dot("."); "" if there is no extension; | |
* null if uri was null. | |
*/ | |
public static String getExtension(String uri) { | |
if (uri == null) { | |
return null; | |
} | |
int dot = uri.lastIndexOf("."); | |
if (dot >= 0) { | |
return uri.substring(dot); | |
} else { | |
// No extension. | |
return ""; | |
} | |
} | |
/** | |
* @return Whether the URI is a local one. | |
*/ | |
public static boolean isLocal(String url) { | |
if (url != null && !url.startsWith("http://") && !url.startsWith("https://")) { | |
return true; | |
} | |
return false; | |
} | |
/** | |
* @return True if Uri is a MediaStore Uri. | |
* @author paulburke | |
*/ | |
public static boolean isMediaUri(Uri uri) { | |
return "media".equalsIgnoreCase(uri.getAuthority()); | |
} | |
/** | |
* Convert File into Uri. | |
* | |
* @param file | |
* @return uri | |
*/ | |
public static Uri getUri(File file) { | |
if (file != null) { | |
return Uri.fromFile(file); | |
} | |
return null; | |
} | |
/** | |
* Returns the path only (without file name). | |
* | |
* @param file | |
* @return | |
*/ | |
public static File getPathWithoutFilename(File file) { | |
if (file != null) { | |
if (file.isDirectory()) { | |
// no file to be split off. Return everything | |
return file; | |
} else { | |
String filename = file.getName(); | |
String filepath = file.getAbsolutePath(); | |
// Construct path without file name. | |
String pathwithoutname = filepath.substring(0, | |
filepath.length() - filename.length()); | |
if (pathwithoutname.endsWith("/")) { | |
pathwithoutname = pathwithoutname.substring(0, pathwithoutname.length() - 1); | |
} | |
return new File(pathwithoutname); | |
} | |
} | |
return null; | |
} | |
/** | |
* @return The MIME type for the given file. | |
*/ | |
public static String getMimeType(File file) { | |
String extension = getExtension(file.getName()); | |
if (extension.length() > 0) | |
return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.substring(1)); | |
return "application/octet-stream"; | |
} | |
/** | |
* @return The MIME type for the give Uri. | |
*/ | |
public static String getMimeType(Context context, Uri uri) { | |
File file = new File(getPath(context, uri)); | |
return getMimeType(file); | |
} | |
/** | |
* @param uri The Uri to check. | |
* @return Whether the Uri authority is {@link LocalStorageProvider}. | |
* @author paulburke | |
*/ | |
public static boolean isLocalStorageDocument(Uri uri) { | |
return LocalStorageProvider.AUTHORITY.equals(uri.getAuthority()); | |
} | |
/** | |
* @param uri The Uri to check. | |
* @return Whether the Uri authority is ExternalStorageProvider. | |
* @author paulburke | |
*/ | |
public static boolean isExternalStorageDocument(Uri uri) { | |
return "com.android.externalstorage.documents".equals(uri.getAuthority()); | |
} | |
/** | |
* @param uri The Uri to check. | |
* @return Whether the Uri authority is DownloadsProvider. | |
* @author paulburke | |
*/ | |
public static boolean isDownloadsDocument(Uri uri) { | |
return "com.android.providers.downloads.documents".equals(uri.getAuthority()); | |
} | |
/** | |
* @param uri The Uri to check. | |
* @return Whether the Uri authority is MediaProvider. | |
* @author paulburke | |
*/ | |
public static boolean isMediaDocument(Uri uri) { | |
return "com.android.providers.media.documents".equals(uri.getAuthority()); | |
} | |
/** | |
* @param uri The Uri to check. | |
* @return Whether the Uri authority is Google Photos. | |
*/ | |
public static boolean isGooglePhotosUri(Uri uri) { | |
return "com.google.android.apps.photos.content".equals(uri.getAuthority()); | |
} | |
/** | |
* Get the value of the data column for this Uri. This is useful for | |
* MediaStore Uris, and other file-based ContentProviders. | |
* | |
* @param context The context. | |
* @param uri The Uri to query. | |
* @param selection (Optional) Filter used in the query. | |
* @param selectionArgs (Optional) Selection arguments used in the query. | |
* @return The value of the _data column, which is typically a file path. | |
* @author paulburke | |
*/ | |
public static String getDataColumn(Context context, Uri uri, String selection, | |
String[] selectionArgs) { | |
Cursor cursor = null; | |
final String column = "_data"; | |
final String[] projection = { | |
column | |
}; | |
try { | |
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, | |
null); | |
if (cursor != null && cursor.moveToFirst()) { | |
if (DEBUG) | |
DatabaseUtils.dumpCursor(cursor); | |
final int column_index = cursor.getColumnIndexOrThrow(column); | |
return cursor.getString(column_index); | |
} | |
} finally { | |
if (cursor != null) | |
cursor.close(); | |
} | |
return null; | |
} | |
/** | |
* Get a file path from a Uri. This will get the the path for Storage Access | |
* Framework Documents, as well as the _data field for the MediaStore and | |
* other file-based ContentProviders.<br> | |
* <br> | |
* Callers should check whether the path is local before assuming it | |
* represents a local file. | |
* | |
* @param context The context. | |
* @param uri The Uri to query. | |
* @see #isLocal(String) | |
* @see #getFile(Context, Uri) | |
* @author paulburke | |
*/ | |
public static String getPath(final Context context, final Uri uri) { | |
if (DEBUG) | |
Log.d(TAG + " File -", | |
"Authority: " + uri.getAuthority() + | |
", Fragment: " + uri.getFragment() + | |
", Port: " + uri.getPort() + | |
", Query: " + uri.getQuery() + | |
", Scheme: " + uri.getScheme() + | |
", Host: " + uri.getHost() + | |
", Segments: " + uri.getPathSegments().toString() | |
); | |
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; | |
// DocumentProvider | |
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { | |
// LocalStorageProvider | |
if (isLocalStorageDocument(uri)) { | |
// The path is the id | |
return DocumentsContract.getDocumentId(uri); | |
} | |
// ExternalStorageProvider | |
else if (isExternalStorageDocument(uri)) { | |
final String docId = DocumentsContract.getDocumentId(uri); | |
final String[] split = docId.split(":"); | |
final String type = split[0]; | |
if ("primary".equalsIgnoreCase(type)) { | |
return Environment.getExternalStorageDirectory() + "/" + split[1]; | |
} | |
// TODO handle non-primary volumes | |
} | |
// DownloadsProvider | |
else if (isDownloadsDocument(uri)) { | |
final String id = DocumentsContract.getDocumentId(uri); | |
final Uri contentUri = ContentUris.withAppendedId( | |
Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); | |
return getDataColumn(context, contentUri, null, null); | |
} | |
// MediaProvider | |
else if (isMediaDocument(uri)) { | |
final String docId = DocumentsContract.getDocumentId(uri); | |
final String[] split = docId.split(":"); | |
final String type = split[0]; | |
Uri contentUri = null; | |
if ("image".equals(type)) { | |
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; | |
} else if ("video".equals(type)) { | |
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; | |
} else if ("audio".equals(type)) { | |
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; | |
} | |
final String selection = "_id=?"; | |
final String[] selectionArgs = new String[] { | |
split[1] | |
}; | |
return getDataColumn(context, contentUri, selection, selectionArgs); | |
} | |
} | |
// MediaStore (and general) | |
else if ("content".equalsIgnoreCase(uri.getScheme())) { | |
// Return the remote address | |
if (isGooglePhotosUri(uri)) | |
return uri.getLastPathSegment(); | |
return getDataColumn(context, uri, null, null); | |
} | |
// File | |
else if ("file".equalsIgnoreCase(uri.getScheme())) { | |
return uri.getPath(); | |
} | |
return null; | |
} | |
/** | |
* Convert Uri into File, if possible. | |
* | |
* @return file A local file that the Uri was pointing to, or null if the | |
* Uri is unsupported or pointed to a remote resource. | |
* @see #getPath(Context, Uri) | |
* @author paulburke | |
*/ | |
public static File getFile(Context context, Uri uri) { | |
if (uri != null) { | |
String path = getPath(context, uri); | |
if (path != null && isLocal(path)) { | |
return new File(path); | |
} | |
} | |
return null; | |
} | |
/** | |
* Get the file size in a human-readable string. | |
* | |
* @param size | |
* @return | |
* @author paulburke | |
*/ | |
public static String getReadableFileSize(int size) { | |
final int BYTES_IN_KILOBYTES = 1024; | |
final DecimalFormat dec = new DecimalFormat("###.#"); | |
final String KILOBYTES = " KB"; | |
final String MEGABYTES = " MB"; | |
final String GIGABYTES = " GB"; | |
float fileSize = 0; | |
String suffix = KILOBYTES; | |
if (size > BYTES_IN_KILOBYTES) { | |
fileSize = size / BYTES_IN_KILOBYTES; | |
if (fileSize > BYTES_IN_KILOBYTES) { | |
fileSize = fileSize / BYTES_IN_KILOBYTES; | |
if (fileSize > BYTES_IN_KILOBYTES) { | |
fileSize = fileSize / BYTES_IN_KILOBYTES; | |
suffix = GIGABYTES; | |
} else { | |
suffix = MEGABYTES; | |
} | |
} | |
} | |
return String.valueOf(dec.format(fileSize) + suffix); | |
} | |
/** | |
* Attempt to retrieve the thumbnail of given File from the MediaStore. This | |
* should not be called on the UI thread. | |
* | |
* @param context | |
* @param file | |
* @return | |
* @author paulburke | |
*/ | |
public static Bitmap getThumbnail(Context context, File file) { | |
return getThumbnail(context, getUri(file), getMimeType(file)); | |
} | |
/** | |
* Attempt to retrieve the thumbnail of given Uri from the MediaStore. This | |
* should not be called on the UI thread. | |
* | |
* @param context | |
* @param uri | |
* @return | |
* @author paulburke | |
*/ | |
public static Bitmap getThumbnail(Context context, Uri uri) { | |
return getThumbnail(context, uri, getMimeType(context, uri)); | |
} | |
/** | |
* Attempt to retrieve the thumbnail of given Uri from the MediaStore. This | |
* should not be called on the UI thread. | |
* | |
* @param context | |
* @param uri | |
* @param mimeType | |
* @return | |
* @author paulburke | |
*/ | |
public static Bitmap getThumbnail(Context context, Uri uri, String mimeType) { | |
if (DEBUG) | |
Log.d(TAG, "Attempting to get thumbnail"); | |
if (!isMediaUri(uri)) { | |
Log.e(TAG, "You can only retrieve thumbnails for images and videos."); | |
return null; | |
} | |
Bitmap bm = null; | |
if (uri != null) { | |
final ContentResolver resolver = context.getContentResolver(); | |
Cursor cursor = null; | |
try { | |
cursor = resolver.query(uri, null, null, null, null); | |
if (cursor.moveToFirst()) { | |
final int id = cursor.getInt(0); | |
if (DEBUG) | |
Log.d(TAG, "Got thumb ID: " + id); | |
if (mimeType.contains("video")) { | |
bm = MediaStore.Video.Thumbnails.getThumbnail( | |
resolver, | |
id, | |
MediaStore.Video.Thumbnails.MINI_KIND, | |
null); | |
} | |
else if (mimeType.contains(FileUtils.MIME_TYPE_IMAGE)) { | |
bm = MediaStore.Images.Thumbnails.getThumbnail( | |
resolver, | |
id, | |
MediaStore.Images.Thumbnails.MINI_KIND, | |
null); | |
} | |
} | |
} catch (Exception e) { | |
if (DEBUG) | |
Log.e(TAG, "getThumbnail", e); | |
} finally { | |
if (cursor != null) | |
cursor.close(); | |
} | |
} | |
return bm; | |
} | |
/** | |
* File and folder comparator. TODO Expose sorting option method | |
* | |
* @author paulburke | |
*/ | |
public static Comparator<File> sComparator = new Comparator<File>() { | |
@Override | |
public int compare(File f1, File f2) { | |
// Sort alphabetically by lower case, which is much cleaner | |
return f1.getName().toLowerCase().compareTo( | |
f2.getName().toLowerCase()); | |
} | |
}; | |
/** | |
* File (not directories) filter. | |
* | |
* @author paulburke | |
*/ | |
public static FileFilter sFileFilter = new FileFilter() { | |
@Override | |
public boolean accept(File file) { | |
final String fileName = file.getName(); | |
// Return files only (not directories) and skip hidden files | |
return file.isFile() && !fileName.startsWith(HIDDEN_PREFIX); | |
} | |
}; | |
/** | |
* Folder (directories) filter. | |
* | |
* @author paulburke | |
*/ | |
public static FileFilter sDirFilter = new FileFilter() { | |
@Override | |
public boolean accept(File file) { | |
final String fileName = file.getName(); | |
// Return directories only and skip hidden directories | |
return file.isDirectory() && !fileName.startsWith(HIDDEN_PREFIX); | |
} | |
}; | |
/** | |
* Get the Intent for selecting content to be used in an Intent Chooser. | |
* | |
* @return The intent for opening a file with Intent.createChooser() | |
* @author paulburke | |
*/ | |
public static Intent createGetContentIntent() { | |
// Implicitly allow the user to select a particular kind of data | |
final Intent intent = new Intent(Intent.ACTION_GET_CONTENT); | |
// The MIME data type filter | |
intent.setType("*/*"); | |
// Only return URIs that can be opened with ContentResolver | |
intent.addCategory(Intent.CATEGORY_OPENABLE); | |
return intent; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment