aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJorge Ruesga <jorge@ruesga.com>2013-11-15 01:41:32 +0100
committerJorge Ruesga <jorge@ruesga.com>2013-11-15 01:41:32 +0100
commitf0ff624a4fe2fd5651ad6b79e02050e0c01acdac (patch)
treedc7267578bf7652637818a982fd976641ec1e675
parentd60e42f5aaf303449ce7ae6b15bcb1484a4b68cf (diff)
downloadandroid_packages_apps_CMFileManager-f0ff624a4fe2fd5651ad6b79e02050e0c01acdac.tar.gz
android_packages_apps_CMFileManager-f0ff624a4fe2fd5651ad6b79e02050e0c01acdac.tar.bz2
android_packages_apps_CMFileManager-f0ff624a4fe2fd5651ad6b79e02050e0c01acdac.zip
Select content uris vs file uris when open or send files
Change-Id: I1e576ccc3d14f9e02bd0148f530133065bfc20bf JIRA: CYAN-2649 Issue: https://jira.cyanogenmod.org/browse/CYAN-2649 Signed-off-by: Jorge Ruesga <jorge@ruesga.com>
-rw-r--r--src/com/cyanogenmod/filemanager/activities/EditorActivity.java18
-rw-r--r--src/com/cyanogenmod/filemanager/activities/PickerActivity.java12
-rw-r--r--src/com/cyanogenmod/filemanager/ui/policy/IntentsActionPolicy.java25
-rw-r--r--src/com/cyanogenmod/filemanager/util/MediaHelper.java122
4 files changed, 166 insertions, 11 deletions
diff --git a/src/com/cyanogenmod/filemanager/activities/EditorActivity.java b/src/com/cyanogenmod/filemanager/activities/EditorActivity.java
index 2a6b9d87..68f91f31 100644
--- a/src/com/cyanogenmod/filemanager/activities/EditorActivity.java
+++ b/src/com/cyanogenmod/filemanager/activities/EditorActivity.java
@@ -28,6 +28,7 @@ import android.content.IntentFilter;
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;
@@ -78,6 +79,7 @@ import com.cyanogenmod.filemanager.util.DialogHelper;
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;
@@ -907,7 +909,7 @@ public class EditorActivity extends Activity implements TextWatcher {
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);
@@ -1509,4 +1511,18 @@ public class EditorActivity extends Activity implements TextWatcher {
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();
+ }
}
diff --git a/src/com/cyanogenmod/filemanager/activities/PickerActivity.java b/src/com/cyanogenmod/filemanager/activities/PickerActivity.java
index f548b413..fdf50993 100644
--- a/src/com/cyanogenmod/filemanager/activities/PickerActivity.java
+++ b/src/com/cyanogenmod/filemanager/activities/PickerActivity.java
@@ -21,6 +21,7 @@ import android.app.AlertDialog;
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;
@@ -60,6 +61,7 @@ import com.cyanogenmod.filemanager.ui.widgets.NavigationView.OnFilePickedListene
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;
@@ -428,7 +430,7 @@ public class PickerActivity extends Activity
// 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();
@@ -490,8 +492,12 @@ public class PickerActivity extends Activity
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();
diff --git a/src/com/cyanogenmod/filemanager/ui/policy/IntentsActionPolicy.java b/src/com/cyanogenmod/filemanager/ui/policy/IntentsActionPolicy.java
index c0711c50..852d2984 100644
--- a/src/com/cyanogenmod/filemanager/ui/policy/IntentsActionPolicy.java
+++ b/src/com/cyanogenmod/filemanager/ui/policy/IntentsActionPolicy.java
@@ -17,6 +17,7 @@
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;
@@ -37,6 +38,7 @@ import com.cyanogenmod.filemanager.ui.dialogs.AssociationsDialog;
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;
@@ -99,9 +101,9 @@ public final class IntentsActionPolicy extends ActionsPolicy {
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
@@ -138,7 +140,7 @@ public final class IntentsActionPolicy extends ActionsPolicy {
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
@@ -199,7 +201,7 @@ public final class IntentsActionPolicy extends ActionsPolicy {
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);
@@ -580,4 +582,19 @@ public final class IntentsActionPolicy extends ActionsPolicy {
});
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;
+ }
}
diff --git a/src/com/cyanogenmod/filemanager/util/MediaHelper.java b/src/com/cyanogenmod/filemanager/util/MediaHelper.java
index db818db3..bb6a9c6b 100644
--- a/src/com/cyanogenmod/filemanager/util/MediaHelper.java
+++ b/src/com/cyanogenmod/filemanager/util/MediaHelper.java
@@ -22,6 +22,7 @@ import android.net.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;
@@ -33,6 +34,13 @@ import java.util.Map;
*/
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
@@ -98,9 +106,117 @@ public final class MediaHelper {
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