package com.vaguehope.onosendai.images;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.provider.BaseColumns;
import android.provider.MediaStore.MediaColumns;
import android.provider.OpenableColumns;
import android.support.v4.content.FileProvider;
import android.webkit.MimeTypeMap;
import com.vaguehope.onosendai.util.FileHelper;
import com.vaguehope.onosendai.util.LogWrapper;
import com.vaguehope.onosendai.util.StringHelper;
public class CachedImageFileProvider extends FileProvider {
private static final LogWrapper LOG = new LogWrapper("CIFP");
public CachedImageFileProvider () {}
public static List<File> addFileExtensions (final List<File> input) {
final List<File> ret = new ArrayList<File>();
for (final File file : input) {
final String extension = identifyFileExtension(file);
if (!StringHelper.isEmpty(extension)) {
ret.add(new File(String.format("%s.%s", file.getAbsolutePath(), extension)));
}
else {
ret.add(file);
}
}
return ret;
}
protected static String identifyFileExtension (final File file) {
return MimeTypeMap.getSingleton().getExtensionFromMimeType(identifyFileMimeType(file));
}
protected static String identifyFileMimeType (final File file) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(file.getAbsolutePath(), options);
return options.outMimeType;
}
protected static Uri removeExtension (final Uri uri) {
return uri.buildUpon().path(removeExtension(uri.getPath())).build();
}
protected static String baseName (final Uri uri) {
final List<String> segs = uri.getPathSegments();
return segs.get(segs.size() - 1);
}
private static String removeExtension (final String path) {
final int dot = path.lastIndexOf(".");
final int slash = path.lastIndexOf("/");
if (dot > slash && dot < path.length() - 1) return path.substring(0, dot);
return path;
}
private static String getExtension (final String path) {
final int dot = path.lastIndexOf(".");
final int slash = path.lastIndexOf("/");
if (dot > slash && dot < path.length() - 1) return path.substring(dot + 1);
return "";
}
protected static long tryReadId (final Uri uri) {
String baseName = baseName(uri);
if (baseName.length() > 14) baseName = baseName.substring(baseName.length() - 14);
try {
return Long.valueOf(baseName, 16);
}
catch (final NumberFormatException e) {
LOG.w("Failed to read ID from uri=%s baseName=%s.", uri, baseName);
return -1;
}
}
@Override
public Cursor query (final Uri uri, final String[] projection, final String selection, final String[] selectionArgs, final String sortOrder) {
LOG.i("query: %s, %s, %s, %s, %s", uri, Arrays.toString(projection), selection, selectionArgs, sortOrder);
final Uri uriMinusExtension = removeExtension(uri);
final MatrixCursor inputCursor = (MatrixCursor) super.query(uriMinusExtension, projection, selection, selectionArgs, sortOrder);
// This mess to clone the single entry cursor and append file extensions to display name.
final List<String> cols = new ArrayList<String>();
final List<Object> values = new ArrayList<Object>();
inputCursor.moveToFirst();
for (final String colName : projection) {
final int colIndex = inputCursor.getColumnIndex(colName);
if (OpenableColumns.DISPLAY_NAME.equals(colName)) {
if (colIndex >= 0) {
cols.add(OpenableColumns.DISPLAY_NAME);
values.add(makeDisplayName(inputCursor.getString(colIndex), uri));
}
}
else if (OpenableColumns.SIZE.equals(colName)) {
if (colIndex >= 0) {
cols.add(OpenableColumns.SIZE);
values.add(inputCursor.getLong(colIndex));
}
}
else if (MediaColumns.MIME_TYPE.equals(colName)) {
cols.add(MediaColumns.MIME_TYPE);
values.add(getType(uri));
}
else if (BaseColumns._ID.equals(colName)) {
final long id = tryReadId(uriMinusExtension);
if (id > 0) {
cols.add(BaseColumns._ID);
values.add(id);
}
}
}
final String[] colsArr = cols.toArray(new String[cols.size()]);
LOG.i("result: %s, %s", Arrays.toString(colsArr), values);
final MatrixCursor updatedCursor = new MatrixCursor(colsArr, 1);
updatedCursor.addRow(values);
return updatedCursor;
}
private String makeDisplayName (final String baseName, final Uri uri) {
final String extension = getExtension(uri.getPath());
final String key = HybridBitmapCache.readKeyFromMetaFileName(getContext(), baseName(removeExtension(uri)));
if (!StringHelper.isEmpty(key)) {
final String nameFromKey = FileHelper.nameFromPath(key);
if (!StringHelper.isEmpty(nameFromKey)) {
return StringHelper.addSuffexIfCaseInsensitiveMissing(nameFromKey, "." + extension);
}
}
return String.format("%s.%s", baseName, extension);
}
@Override
public String getType (final Uri uri) {
// Cheat as file does not have to exist for super class to identify by extension.
final String type = super.getType(uri);
LOG.i("getType(%s)=%s", uri, type);
return type;
}
@Override
public ParcelFileDescriptor openFile (final Uri uri, final String mode) throws FileNotFoundException {
LOG.i("openFile: %s", uri);
return super.openFile(removeExtension(uri), mode);
}
}