import android.content.res.Configuration;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
+import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import com.cyanogenmod.filemanager.util.ExceptionUtil;
import com.cyanogenmod.filemanager.util.ExceptionUtil.OnRelaunchCommandResult;
import com.cyanogenmod.filemanager.util.FileHelper;
+import com.cyanogenmod.filemanager.util.MediaHelper;
import com.cyanogenmod.filemanager.util.ResourcesHelper;
import java.io.ByteArrayInputStream;
this.mReadOnly = false;
// Read the intent and check that is has a valid request
- String path = getIntent().getData().getPath();
+ String path = uriToPath(this, getIntent().getData());
if (path == null || path.length() == 0) {
DialogHelper.showToast(
this, R.string.editor_invalid_file_msg, Toast.LENGTH_SHORT);
theme.setTextColor(this, editor, "text_color"); //$NON-NLS-1$
}
+ /**
+ * Method that resolves the content uri to a valid system path
+ *
+ * @param ctx The current context
+ * @param uri The content uri
+ * @return String The system path
+ */
+ private static String uriToPath(Context ctx, Uri uri) {
+ File file = MediaHelper.contentUriToFile(ctx.getContentResolver(), uri);
+ if (file == null) {
+ file = new File(uri.getPath());
+ }
+ return file.getAbsolutePath();
+ }
}
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import com.cyanogenmod.filemanager.util.DialogHelper;
import com.cyanogenmod.filemanager.util.ExceptionUtil;
import com.cyanogenmod.filemanager.util.FileHelper;
+import com.cyanogenmod.filemanager.util.MediaHelper;
import com.cyanogenmod.filemanager.util.MimeTypeHelper;
import com.cyanogenmod.filemanager.util.StorageHelper;
// Return the picked file, as expected (this activity should fill the intent data
// and return RESULT_OK result)
Intent result = new Intent();
- result.setData(getResultUriForFileFromIntent(src, getIntent()));
+ result.setData(getResultUriForFileFromIntent(getContentResolver(), src, getIntent()));
setResult(Activity.RESULT_OK, result);
finish();
return file.getParentFile();
}
- private static Uri getResultUriForFileFromIntent(File src, Intent intent) {
- Uri result = Uri.fromFile(src);
+ private static Uri getResultUriForFileFromIntent(ContentResolver cr, File src, Intent intent) {
+ // Try to find the preferred uri scheme
+ Uri result = MediaHelper.fileToContentUri(cr, src);
+ if (result == null) {
+ result = Uri.fromFile(src);
+ }
if (Intent.ACTION_PICK.equals(intent.getAction()) && intent.getData() != null) {
String scheme = intent.getData().getScheme();
package com.cyanogenmod.filemanager.ui.policy;
import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface.OnCancelListener;
import android.content.DialogInterface.OnDismissListener;
import com.cyanogenmod.filemanager.util.DialogHelper;
import com.cyanogenmod.filemanager.util.ExceptionUtil;
import com.cyanogenmod.filemanager.util.FileHelper;
+import com.cyanogenmod.filemanager.util.MediaHelper;
import com.cyanogenmod.filemanager.util.MimeTypeHelper;
import com.cyanogenmod.filemanager.util.MimeTypeHelper.MimeTypeCategory;
import com.cyanogenmod.filemanager.util.ResourcesHelper;
String mime = MimeTypeHelper.getMimeType(ctx, fso);
File file = new File(fso.getFullPath());
if (mime != null) {
- intent.setDataAndType(Uri.fromFile(file), mime);
+ intent.setDataAndType(getUriFromFile(ctx, file), mime);
} else {
- intent.setData(Uri.fromFile(file));
+ intent.setData(getUriFromFile(ctx, file));
}
// Resolve the intent
intent.setAction(android.content.Intent.ACTION_SEND);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setType(MimeTypeHelper.getMimeType(ctx, fso));
- Uri uri = Uri.fromFile(new File(fso.getFullPath()));
+ Uri uri = getUriFromFile(ctx, new File(fso.getFullPath()));
intent.putExtra(Intent.EXTRA_STREAM, uri);
// Resolve the intent
lastMimeType = mimeType;
// Add the uri
- uris.add(Uri.fromFile(new File(fso.getFullPath())));
+ uris.add(getUriFromFile(ctx, new File(fso.getFullPath())));
}
if (sameMimeType) {
intent.setType(lastMimeType);
});
return pref.get(0);
}
+
+ /**
+ * Method that returns the best Uri for the file (content uri, file uri, ...)
+ *
+ * @param ctx The current context
+ * @param file The file to resolve
+ */
+ private static Uri getUriFromFile(Context ctx, File file) {
+ ContentResolver cr = ctx.getContentResolver();
+ Uri uri = MediaHelper.fileToContentUri(cr, file);
+ if (uri == null) {
+ uri = Uri.fromFile(file);
+ }
+ return uri;
+ }
}
import android.os.UserHandle;
import android.provider.BaseColumns;
import android.provider.MediaStore;
+import android.provider.MediaStore.MediaColumns;
import android.text.TextUtils;
import java.io.File;
*/
public final class MediaHelper {
+ private static final String EMULATED_STORAGE_SOURCE = System.getenv("EMULATED_STORAGE_SOURCE");
+ private static final String EMULATED_STORAGE_TARGET = System.getenv("EMULATED_STORAGE_TARGET");
+ private static final String EXTERNAL_STORAGE = System.getenv("EXTERNAL_STORAGE");
+
+ private static final String INTERNAL_VOLUME = "internal";
+ private static final String EXTERNAL_VOLUME = "external";
+
/**
* URIs that are relevant for determining album art;
* useful for content observer registration
return null;
}
- private static final String EMULATED_STORAGE_SOURCE = System.getenv("EMULATED_STORAGE_SOURCE");
- private static final String EMULATED_STORAGE_TARGET = System.getenv("EMULATED_STORAGE_TARGET");
- private static final String EXTERNAL_STORAGE = System.getenv("EXTERNAL_STORAGE");
+ /**
+ * Method that converts a file reference to a content uri reference
+ *
+ * @param cr A content resolver
+ * @param file The file reference
+ * @return Uri The content uri or null if file not exists in the media database
+ */
+ public static Uri fileToContentUri(ContentResolver cr, File file) {
+ // Normalize the path to ensure media search
+ final String normalizedPath = normalizeMediaPath(file.getAbsolutePath());
+
+ // Check in external and internal storages
+ Uri uri = fileToContentUri(cr, normalizedPath, EXTERNAL_VOLUME);
+ if (uri != null) {
+ return uri;
+ }
+ uri = fileToContentUri(cr, normalizedPath, INTERNAL_VOLUME);
+ if (uri != null) {
+ return uri;
+ }
+ return null;
+ }
+
+ /**
+ * Method that converts a file reference to a content uri reference
+ *
+ * @param cr A content resolver
+ * @param path The path to search
+ * @param volume The volume
+ * @return Uri The content uri or null if file not exists in the media database
+ */
+ private static Uri fileToContentUri(ContentResolver cr, String path, String volume) {
+ final String[] projection = {BaseColumns._ID, MediaStore.Files.FileColumns.MEDIA_TYPE};
+ final String where = MediaColumns.DATA + " = ?";
+ Uri baseUri = MediaStore.Files.getContentUri(volume);
+ Cursor c = cr.query(baseUri, projection, where, new String[]{path}, null);
+ try {
+ if (c != null && c.moveToNext()) {
+ int type = c.getInt(c.getColumnIndexOrThrow(
+ MediaStore.Files.FileColumns.MEDIA_TYPE));
+ if (type != 0) {
+ // Do not force to use content uri for no media files
+ long id = c.getLong(c.getColumnIndexOrThrow(BaseColumns._ID));
+ return Uri.withAppendedPath(baseUri, String.valueOf(id));
+ }
+ }
+ } finally {
+ if (c != null) {
+ c.close();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Method that converts a content uri to a file system path
+ *
+ * @param cr The content resolver
+ * @param uri The content uri
+ * @return File The file reference
+ */
+ public static File contentUriToFile(ContentResolver cr, Uri uri) {
+ // Sanity checks
+ if (uri == null || uri.getScheme() == null || uri.getScheme().compareTo("content") != 0) {
+ return null;
+ }
+
+ // Retrieve the request id
+ long id = 0;
+ try {
+ id = Long.parseLong(new File(uri.getPath()).getName());
+ } catch (NumberFormatException nfex) {
+ return null;
+ }
+
+ // Check in external and internal storages
+ File file = mediaIdToFile(cr, id, EXTERNAL_VOLUME);
+ if (file != null) {
+ return file;
+ }
+ file = mediaIdToFile(cr, id, INTERNAL_VOLUME);
+ if (file != null) {
+ return file;
+ }
+ return null;
+ }
+
+ /**
+ * Method that converts a content uri to a file system path
+ *
+ * @param cr The content resolver
+ * @param id The media database id
+ * @param volume The volume
+ * @return File The file reference
+ */
+ private static File mediaIdToFile(ContentResolver cr, long id, String volume) {
+ final String[] projection = {MediaColumns.DATA};
+ final String where = MediaColumns._ID + " = ?";
+ Uri baseUri = MediaStore.Files.getContentUri(volume);
+ Cursor c = cr.query(baseUri, projection, where, new String[]{String.valueOf(id)}, null);
+ try {
+ if (c != null && c.moveToNext()) {
+ return new File(c.getString(c.getColumnIndexOrThrow(MediaColumns.DATA)));
+ }
+ } finally {
+ if (c != null) {
+ c.close();
+ }
+ }
+ return null;
+ }
/**
* Method that converts a not standard media mount path to a standard media path