/**
* ****************************************************************************
* Copyright 2013 Kumar Bibek
* <p/>
* 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
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* 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.kbeanie.imagechooser.threads;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.provider.MediaStore.MediaColumns;
import android.provider.OpenableColumns;
import android.text.TextUtils;
import android.util.Log;
import com.kbeanie.imagechooser.BuildConfig;
import com.kbeanie.imagechooser.api.ChosenImage;
import com.kbeanie.imagechooser.api.ChosenVideo;
import com.kbeanie.imagechooser.api.FileUtils;
import com.kbeanie.imagechooser.exceptions.ChooserException;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Calendar;
import java.util.Locale;
import static com.kbeanie.imagechooser.helpers.StreamHelper.close;
import static com.kbeanie.imagechooser.helpers.StreamHelper.flush;
import static com.kbeanie.imagechooser.helpers.StreamHelper.verifyStream;
public abstract class MediaProcessorThread extends Thread {
private final static String TAG = MediaProcessorThread.class.getSimpleName();
// 500 MB Cache size
protected final static int MAX_DIRECTORY_SIZE = 500 * 1024 * 1024;
// Number of days to preserve 10 days
protected final static int MAX_THRESHOLD_DAYS = (int) (10 * 24 * 60 * 60 * 1000);
private final static int THUMBNAIL_BIG = 1;
private final static int THUMBNAIL_SMALL = 2;
protected String[] filePaths = new String[0];
protected String filePath;
protected Context context;
protected String foldername;
protected boolean shouldCreateThumnails;
protected String mediaExtension;
protected boolean clearOldFiles = false;
public MediaProcessorThread(String filePath, String foldername,
boolean shouldCreateThumbnails) {
this.filePath = filePath;
this.foldername = foldername;
this.shouldCreateThumnails = shouldCreateThumbnails;
}
public MediaProcessorThread(String[] filePaths, String foldername, boolean shouldCreateThumnails) {
this.filePaths = filePaths;
this.foldername = foldername;
this.shouldCreateThumnails = shouldCreateThumnails;
}
public void setContext(Context context) {
this.context = context;
}
public void setMediaExtension(String extension) {
this.mediaExtension = extension;
}
public void clearOldFiles(boolean clearOldFiles) {
this.clearOldFiles = clearOldFiles;
}
protected void downloadAndProcess(String url) throws ChooserException {
filePath = downloadFile(url);
process();
}
protected ChosenVideo downloadAndProcessVideo(String url) throws ChooserException {
String localFile = downloadFile(url);
ChosenVideo video = processVideo(localFile);
return video;
}
protected ChosenImage downloadAndProcessNew(String url) throws ChooserException {
String downloadedFilePath = downloadFile(url);
ChosenImage image = processImage(downloadedFilePath);
return image;
}
protected void process() throws ChooserException {
if (!filePath.contains(foldername)) {
copyFileToDir();
}
}
protected ChosenVideo processVideo(String filePath) throws ChooserException {
ChosenVideo video = new ChosenVideo();
if (!filePath.contains(foldername)) {
String localFilePath = copyFileToDir(filePath);
video.setVideoFilePath(localFilePath);
} else {
video.setVideoFilePath(filePath);
}
return video;
}
protected ChosenImage processImage(String filePath) throws ChooserException {
ChosenImage image = new ChosenImage();
if (!filePath.contains(foldername)) {
String localFilePath = copyFileToDir(filePath);
image.setFilePathOriginal(localFilePath);
} else {
image.setFilePathOriginal(filePath);
}
return image;
}
protected String[] createThumbnails(String image) throws ChooserException {
String[] images = new String[2];
images[0] = getThumbnailPath(image);
images[1] = getThumbnailSmallPath(image);
return images;
}
private String getThumbnailPath(String file) throws ChooserException {
if (BuildConfig.DEBUG) {
Log.i(TAG, "Compressing ... THUMBNAIL");
}
return compressAndSaveImage(file, THUMBNAIL_BIG);
}
private String getThumbnailSmallPath(String file) throws ChooserException {
if (BuildConfig.DEBUG) {
Log.i(TAG, "Compressing ... THUMBNAIL SMALL");
}
return compressAndSaveImage(file, THUMBNAIL_SMALL);
}
private String compressAndSaveImage(String fileImage, int scale) throws ChooserException {
FileOutputStream stream = null;
BufferedInputStream bstream = null;
Bitmap bitmap = null;
try {
Options optionsForGettingDimensions = new Options();
optionsForGettingDimensions.inJustDecodeBounds = true;
BufferedInputStream boundsOnlyStream = new BufferedInputStream(new FileInputStream(fileImage));
bitmap = BitmapFactory.decodeStream(boundsOnlyStream, null, optionsForGettingDimensions);
if (bitmap != null) {
bitmap.recycle();
}
if (boundsOnlyStream != null) {
boundsOnlyStream.close();
}
int w, l;
w = optionsForGettingDimensions.outWidth;
l = optionsForGettingDimensions.outHeight;
ExifInterface exif = new ExifInterface(fileImage);
int orientation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
int rotate = 0;
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_270:
rotate = -90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotate = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_90:
rotate = 90;
break;
}
int what = w > l ? w : l;
Options options = new Options();
if (what > 3000) {
options.inSampleSize = scale * 6;
} else if (what > 2000 && what <= 3000) {
options.inSampleSize = scale * 5;
} else if (what > 1500 && what <= 2000) {
options.inSampleSize = scale * 4;
} else if (what > 1000 && what <= 1500) {
options.inSampleSize = scale * 3;
} else if (what > 400 && what <= 1000) {
options.inSampleSize = scale * 2;
} else {
options.inSampleSize = scale;
}
options.inJustDecodeBounds = false;
if (BuildConfig.DEBUG) {
Log.i(TAG, "Scale: " + (what / options.inSampleSize));
Log.i(TAG, "Rotate: " + rotate);
}
// TODO: Sometime the decode File Returns null for some images
// For such cases, thumbnails can't be created.
// Thumbnails will link to the original file
BufferedInputStream scaledInputStream = new BufferedInputStream(new FileInputStream(fileImage));
bitmap = BitmapFactory.decodeStream(scaledInputStream, null, options);
// verifyBitmap(fileImage, bitmap);
scaledInputStream.close();
if (bitmap == null) {
return fileImage;
}
File original = new File(fileImage);
File file = new File(
(original.getParent() + File.separator + original.getName()
.replace(".", "_fact_" + scale + ".")));
stream = new FileOutputStream(file);
if (rotate != 0) {
Matrix matrix = new Matrix();
matrix.setRotate(rotate);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
bitmap.getHeight(), matrix, false);
}
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
return file.getAbsolutePath();
} catch (IOException e) {
return fileImage;
// throw new ChooserException(e);
} catch (Exception e) {
return fileImage;
} finally {
close(bstream);
flush(stream);
close(stream);
}
}
private String copyFileToDir(String filePath) throws ChooserException {
BufferedOutputStream outStream = null;
BufferedInputStream bStream = null;
try {
File file;
file = new File(Uri.parse(filePath).getPath());
File copyTo = new File(FileUtils.getDirectory(foldername) + File.separator + file.getName());
bStream = new BufferedInputStream(new FileInputStream(file));
outStream = new BufferedOutputStream(new FileOutputStream(copyTo));
byte[] buf = new byte[2048];
int len;
while ((len = bStream.read(buf)) > 0) {
outStream.write(buf, 0, len);
}
filePath = copyTo.getAbsolutePath();
return filePath;
} catch (IOException e) {
throw new ChooserException(e);
} finally {
flush(outStream);
close(bStream);
close(outStream);
}
}
private void copyFileToDir() throws ChooserException {
BufferedOutputStream outStream = null;
BufferedInputStream bStream = null;
try {
File file;
file = new File(Uri.parse(filePath).getPath());
File copyTo = new File(FileUtils.getDirectory(foldername) + File.separator + file.getName());
bStream = new BufferedInputStream(new FileInputStream(file));
outStream = new BufferedOutputStream(new FileOutputStream(copyTo));
byte[] buf = new byte[2048];
int len;
while ((len = bStream.read(buf)) > 0) {
outStream.write(buf, 0, len);
}
filePath = copyTo.getAbsolutePath();
} catch (IOException e) {
throw new ChooserException(e);
} finally {
flush(outStream);
close(bStream);
close(outStream);
}
}
protected String downloadFile(String url) {
String localFilePath = "";
try {
URL u = new URL(url);
HttpURLConnection urlConnection = (HttpURLConnection) u.openConnection();
InputStream stream = new BufferedInputStream(urlConnection.getInputStream());
BufferedInputStream bStream = new BufferedInputStream(stream);
localFilePath = FileUtils.getDirectory(foldername) + File.separator
+ Calendar.getInstance().getTimeInMillis() + "."
+ mediaExtension;
File localFile = new File(localFilePath);
FileOutputStream fileOutputStream = new FileOutputStream(localFile);
byte[] buffer = new byte[1024];
int len;
while ((len = bStream.read(buffer)) > 0)
fileOutputStream.write(buffer, 0, len);
fileOutputStream.flush();
fileOutputStream.close();
bStream.close();
if (BuildConfig.DEBUG) {
Log.i(TAG, "Image saved: " + localFilePath.toString());
}
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return localFilePath;
}
protected void manageDirectoryCache(final String extension) {
if (!clearOldFiles) {
return;
}
File directory;
directory = new File(FileUtils.getDirectory(foldername));
File[] files = directory.listFiles();
long count = 0;
if (files == null) {
return;
}
for (File file : files) {
count = count + file.length();
}
if (BuildConfig.DEBUG) {
Log.i(TAG, "Directory size: " + count);
}
if (count > MAX_DIRECTORY_SIZE) {
final long today = Calendar.getInstance().getTimeInMillis();
FileFilter filter = new FileFilter() {
@Override
public boolean accept(File pathname) {
if (today - pathname.lastModified() > MAX_THRESHOLD_DAYS
&& pathname
.getAbsolutePath()
.toUpperCase(Locale.ENGLISH)
.endsWith(
extension
.toUpperCase(Locale.ENGLISH))) {
return true;
} else {
return false;
}
}
};
File[] filterFiles = directory.listFiles(filter);
int deletedFileCount = 0;
for (File file : filterFiles) {
deletedFileCount++;
file.delete();
}
Log.i(TAG, "Deleted " + deletedFileCount + " files");
}
}
protected abstract void processingDone(String file, String thumbnail,
String thumbnailSmall);
protected void processPicasaMedia(String path, String extension) throws ChooserException {
if (BuildConfig.DEBUG) {
Log.i(TAG, "Picasa Started");
}
BufferedOutputStream outStream = null;
BufferedInputStream bStream = null;
try {
InputStream inputStream = context.getContentResolver()
.openInputStream(Uri.parse(path));
bStream = new BufferedInputStream(inputStream);
verifyStream(path, bStream);
filePath = FileUtils.getDirectory(foldername) + File.separator
+ Calendar.getInstance().getTimeInMillis() + extension;
outStream = new BufferedOutputStream(new FileOutputStream(filePath));
byte[] buf = new byte[2048];
int len;
while ((len = bStream.read(buf)) > 0) {
outStream.write(buf, 0, len);
}
flush(outStream);
process();
} catch (IOException e) {
throw new ChooserException(e);
} finally {
close(bStream);
close(outStream);
}
if (BuildConfig.DEBUG) {
Log.i(TAG, "Picasa Done");
}
}
protected ChosenVideo processPicasaMediaNewVideo(String path, String extension) throws ChooserException {
if (BuildConfig.DEBUG) {
Log.i(TAG, "Picasa Started");
}
ChosenVideo video = null;
BufferedOutputStream outStream = null;
BufferedInputStream bStream = null;
String outFile;
try {
InputStream inputStream = context.getContentResolver()
.openInputStream(Uri.parse(path));
bStream = new BufferedInputStream(inputStream);
verifyStream(path, bStream);
outFile = FileUtils.getDirectory(foldername) + File.separator
+ Calendar.getInstance().getTimeInMillis() + extension;
outStream = new BufferedOutputStream(new FileOutputStream(outFile));
byte[] buf = new byte[2048];
int len;
while ((len = bStream.read(buf)) > 0) {
outStream.write(buf, 0, len);
}
flush(outStream);
video = processVideo(outFile);
} catch (IOException e) {
throw new ChooserException(e);
} finally {
close(bStream);
close(outStream);
}
if (BuildConfig.DEBUG) {
Log.i(TAG, "Picasa Done");
}
return video;
}
protected ChosenImage processPicasaMediaNew(String path, String extension) throws ChooserException {
if (BuildConfig.DEBUG) {
Log.i(TAG, "Picasa Started");
}
String outFile;
ChosenImage image;
BufferedOutputStream outStream = null;
BufferedInputStream bStream = null;
try {
InputStream inputStream = context.getContentResolver()
.openInputStream(Uri.parse(path));
bStream = new BufferedInputStream(inputStream);
verifyStream(path, bStream);
outFile = FileUtils.getDirectory(foldername) + File.separator
+ Calendar.getInstance().getTimeInMillis() + extension;
outStream = new BufferedOutputStream(new FileOutputStream(outFile));
byte[] buf = new byte[2048];
int len;
while ((len = bStream.read(buf)) > 0) {
outStream.write(buf, 0, len);
}
flush(outStream);
image = processImage(path);
} catch (IOException e) {
throw new ChooserException(e);
} finally {
close(bStream);
close(outStream);
}
if (BuildConfig.DEBUG) {
Log.i(TAG, "Picasa Done");
}
return image;
}
protected void processGooglePhotosMedia(String path, String extension)
throws ChooserException {
if (BuildConfig.DEBUG) {
Log.i(TAG, "Google photos Started");
Log.i(TAG, "URI: " + path);
Log.i(TAG, "Extension: " + extension);
}
String retrievedExtension = checkExtension(Uri.parse(path));
if (retrievedExtension != null
&& !TextUtils.isEmpty(retrievedExtension)) {
extension = "." + retrievedExtension;
}
BufferedInputStream inputStream = null;
BufferedOutputStream outStream = null;
try {
filePath = FileUtils.getDirectory(foldername) + File.separator
+ Calendar.getInstance().getTimeInMillis() + extension;
ParcelFileDescriptor parcelFileDescriptor = context
.getContentResolver().openFileDescriptor(Uri.parse(path),
"r");
verifyStream(path, parcelFileDescriptor);
FileDescriptor fileDescriptor = parcelFileDescriptor
.getFileDescriptor();
inputStream = new BufferedInputStream(new FileInputStream(fileDescriptor));
BufferedInputStream reader = new BufferedInputStream(inputStream);
outStream = new BufferedOutputStream(
new FileOutputStream(filePath));
byte[] buf = new byte[2048];
int len;
while ((len = reader.read(buf)) > 0) {
outStream.write(buf, 0, len);
}
flush(outStream);
process();
} catch (IOException e) {
throw new ChooserException(e);
} finally {
flush(outStream);
close(outStream);
close(inputStream);
}
if (BuildConfig.DEBUG) {
Log.i(TAG, "Picasa Done");
}
}
protected ChosenVideo processGooglePhotosMediaNewVideo(String path, String extension)
throws ChooserException {
ChosenVideo video;
if (BuildConfig.DEBUG) {
Log.i(TAG, "Google photos Started");
Log.i(TAG, "URI: " + path);
Log.i(TAG, "Extension: " + extension);
}
String retrievedExtension = checkExtension(Uri.parse(path));
if (retrievedExtension != null
&& !TextUtils.isEmpty(retrievedExtension)) {
extension = "." + retrievedExtension;
}
BufferedInputStream inputStream = null;
BufferedOutputStream outStream = null;
String localPath;
try {
localPath = FileUtils.getDirectory(foldername) + File.separator
+ Calendar.getInstance().getTimeInMillis() + extension;
ParcelFileDescriptor parcelFileDescriptor = context
.getContentResolver().openFileDescriptor(Uri.parse(path),
"r");
verifyStream(path, parcelFileDescriptor);
FileDescriptor fileDescriptor = parcelFileDescriptor
.getFileDescriptor();
inputStream = new BufferedInputStream(new FileInputStream(fileDescriptor));
BufferedInputStream reader = new BufferedInputStream(inputStream);
outStream = new BufferedOutputStream(
new FileOutputStream(localPath));
byte[] buf = new byte[2048];
int len;
while ((len = reader.read(buf)) > 0) {
outStream.write(buf, 0, len);
}
flush(outStream);
video = processVideo(localPath);
} catch (IOException e) {
throw new ChooserException(e);
} finally {
flush(outStream);
close(outStream);
close(inputStream);
}
if (BuildConfig.DEBUG) {
Log.i(TAG, "Picasa Done");
}
return video;
}
protected ChosenImage processGooglePhotosMediaNew(String path, String extension)
throws ChooserException {
String outFile;
ChosenImage image;
if (BuildConfig.DEBUG) {
Log.i(TAG, "Google photos Started");
Log.i(TAG, "URI: " + path);
Log.i(TAG, "Extension: " + extension);
}
String retrievedExtension = checkExtension(Uri.parse(path));
if (retrievedExtension != null
&& !TextUtils.isEmpty(retrievedExtension)) {
extension = "." + retrievedExtension;
}
BufferedInputStream inputStream = null;
BufferedOutputStream outStream = null;
try {
outFile = FileUtils.getDirectory(foldername) + File.separator
+ Calendar.getInstance().getTimeInMillis() + extension;
ParcelFileDescriptor parcelFileDescriptor = context
.getContentResolver().openFileDescriptor(Uri.parse(path),
"r");
verifyStream(path, parcelFileDescriptor);
FileDescriptor fileDescriptor = parcelFileDescriptor
.getFileDescriptor();
inputStream = new BufferedInputStream(new FileInputStream(fileDescriptor));
BufferedInputStream reader = new BufferedInputStream(inputStream);
outStream = new BufferedOutputStream(
new FileOutputStream(outFile));
byte[] buf = new byte[2048];
int len;
while ((len = reader.read(buf)) > 0) {
outStream.write(buf, 0, len);
}
flush(outStream);
image = processImage(outFile);
} catch (IOException e) {
throw new ChooserException(e);
} finally {
flush(outStream);
close(outStream);
close(inputStream);
}
if (BuildConfig.DEBUG) {
Log.i(TAG, "Picasa Done");
}
return image;
}
public String checkExtension(Uri uri) {
String extension = "";
// The query, since it only applies to a single document, will only
// return
// one row. There's no need to filter, sort, or select fields, since we
// want
// all fields for one document.
Cursor cursor = context.getContentResolver().query(uri, null, null,
null, null);
try {
// moveToFirst() returns false if the cursor has 0 rows. Very handy
// for
// "if there's anything to look at, look at it" conditionals.
if (cursor != null && cursor.moveToFirst()) {
// Note it's called "Display Name". This is
// provider-specific, and might not necessarily be the file
// name.
String displayName = cursor.getString(cursor
.getColumnIndex(OpenableColumns.DISPLAY_NAME));
int position = displayName.indexOf(".");
extension = displayName.substring(position + 1);
Log.i(TAG, "Display Name: " + displayName);
int sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE);
// If the size is unknown, the value stored is null. But since
// an
// int can't be null in Java, the behavior is
// implementation-specific,
// which is just a fancy term for "unpredictable". So as
// a rule, check if it's null before assigning to an int. This
// will
// happen often: The storage API allows for remote files, whose
// size might not be locally known.
String size = null;
if (!cursor.isNull(sizeIndex)) {
// Technically the column stores an int, but
// cursor.getString()
// will do the conversion automatically.
size = cursor.getString(sizeIndex);
} else {
size = "Unknown";
}
Log.i(TAG, "Size: " + size);
}
} finally {
cursor.close();
}
return extension;
}
protected void processContentProviderMedia(String path, String extension)
throws ChooserException {
checkExtension(Uri.parse(path));
InputStream inputStream = null;
BufferedOutputStream outStream = null;
BufferedInputStream bStream = null;
try {
inputStream = context.getContentResolver()
.openInputStream(Uri.parse(path));
bStream = new BufferedInputStream(inputStream);
verifyStream(path, bStream);
filePath = FileUtils.getDirectory(foldername) + File.separator
+ Calendar.getInstance().getTimeInMillis() + extension;
outStream = new BufferedOutputStream(new FileOutputStream(filePath));
byte[] buf = new byte[2048];
int len;
while ((len = bStream.read(buf)) > 0) {
outStream.write(buf, 0, len);
}
process();
} catch (IOException e) {
Log.e(TAG, e.getMessage(), e);
throw new ChooserException(e);
} finally {
close(bStream);
close(outStream);
}
}
protected ChosenVideo processContentProviderMediaNewVideo(String path, String extension)
throws ChooserException {
checkExtension(Uri.parse(path));
ChosenVideo video = null;
InputStream inputStream = null;
BufferedOutputStream outStream = null;
BufferedInputStream bStream = null;
String outFile;
try {
inputStream = context.getContentResolver()
.openInputStream(Uri.parse(path));
bStream = new BufferedInputStream(inputStream);
verifyStream(path, bStream);
outFile = FileUtils.getDirectory(foldername) + File.separator
+ Calendar.getInstance().getTimeInMillis() + extension;
outStream = new BufferedOutputStream(new FileOutputStream(outFile));
byte[] buf = new byte[2048];
int len;
while ((len = bStream.read(buf)) > 0) {
outStream.write(buf, 0, len);
}
video = processVideo(path);
} catch (IOException e) {
Log.e(TAG, e.getMessage(), e);
throw new ChooserException(e);
} finally {
close(bStream);
close(outStream);
}
return video;
}
@SuppressLint("NewApi")
protected String getAbsoluteImagePathFromUri(Uri imageUri) {
String[] proj = {MediaColumns.DATA, MediaColumns.DISPLAY_NAME};
if (BuildConfig.DEBUG) {
Log.i(TAG, "Image Uri: " + imageUri.toString());
}
if (imageUri.toString().startsWith(
"content://com.android.gallery3d.provider")) {
imageUri = Uri.parse(imageUri.toString().replace(
"com.android.gallery3d", "com.google.android.gallery3d"));
}
String filePath = "";
String imageUriString = imageUri.toString();
if (imageUriString.startsWith("content://com.google.android.gallery3d")
|| imageUriString
.startsWith("content://com.google.android.apps.photos.content")
|| imageUriString
.startsWith("content://com.android.providers.media.documents")
|| imageUriString
.startsWith("content://com.google.android.apps.docs.storage")
|| imageUriString
.startsWith("content://com.microsoft.skydrive.content.external")
|| imageUriString
.startsWith("content://com.android.externalstorage.documents")
|| imageUriString
.startsWith("content://com.android.internalstorage.documents") ||
imageUriString.startsWith("content://")) {
filePath = imageUri.toString();
} else {
Cursor cursor = context.getContentResolver().query(imageUri, proj,
null, null, null);
cursor.moveToFirst();
filePath = cursor.getString(cursor
.getColumnIndexOrThrow(MediaColumns.DATA));
cursor.close();
}
if (filePath == null && isDownloadsDocument(imageUri)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
filePath = getPath(context, imageUri);
}
return filePath;
}
@TargetApi(Build.VERSION_CODES.KITKAT)
public static String getPath(final Context context, final Uri uri) {
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
// DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
// ExternalStorageProvider
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 getDataColumn(context, uri, null, null);
}
// File
else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return null;
}
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()) {
final int column_index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(column_index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
public static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
public static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
public static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
}