aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Bird <sbird@cyngn.com>2015-07-02 14:01:49 -0700
committerNBruderman <nbruderman@gmail.com>2015-07-16 20:06:44 +0300
commite09d8433144ac84045e1fbd7bb4723c7cfb66c65 (patch)
treed7a16b715d41da48abd0d09cf9cd914a74a3b514
parent7310a29aea20505951d36e0584befef0398f10ec (diff)
downloadandroid_packages_apps_CMFileManager-e09d8433144ac84045e1fbd7bb4723c7cfb66c65.tar.gz
android_packages_apps_CMFileManager-e09d8433144ac84045e1fbd7bb4723c7cfb66c65.tar.bz2
android_packages_apps_CMFileManager-e09d8433144ac84045e1fbd7bb4723c7cfb66c65.zip
Editor: Handle content uri's in the editor
Previously, files opened that were not contained inside the /data/media partition were considered invalid. Repo steps: - Open email with .txt attachment - Open attachment with Editor This also fixes similar issues all across the system where content uri's would not open in editor. Previously they would report that the user needed to gain root access. Change-Id: I15aa3fd81ae261f66920d253d6adebe28cf28e66
-rw-r--r--src/com/cyanogenmod/filemanager/activities/EditorActivity.java269
1 files changed, 211 insertions, 58 deletions
diff --git a/src/com/cyanogenmod/filemanager/activities/EditorActivity.java b/src/com/cyanogenmod/filemanager/activities/EditorActivity.java
index 7866102e..dfd90b97 100644
--- a/src/com/cyanogenmod/filemanager/activities/EditorActivity.java
+++ b/src/com/cyanogenmod/filemanager/activities/EditorActivity.java
@@ -97,6 +97,7 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
+import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringReader;
import java.util.ArrayList;
@@ -1000,77 +1001,229 @@ public class EditorActivity extends Activity implements TextWatcher {
this.mReadOnly = false;
// Read the intent and check that is has a valid request
- String path = uriToPath(this, getIntent().getData());
- if (path == null || path.length() == 0) {
- DialogHelper.showToast(
- this, R.string.editor_invalid_file_msg, Toast.LENGTH_SHORT);
- return;
- }
+ Intent fileIntent = getIntent();
+ if (fileIntent.getData().getScheme().equals("content")) {
+ asyncReadContentURI(fileIntent.getData());
+ } else {
+ // File Scheme URI's
+ String path = uriToPath(this, getIntent().getData());
+ if (path == null || path.length() == 0) {
+ DialogHelper.showToast(
+ this, R.string.editor_invalid_file_msg, Toast.LENGTH_SHORT);
+ return;
+ }
- // Set the title of the dialog
- File f = new File(path);
- this.mTitle.setText(f.getName());
+ // Set the title of the dialog
+ File f = new File(path);
+ this.mTitle.setText(f.getName());
- // Check that the file exists (the real file, not the symlink)
- try {
- this.mFso = CommandHelper.getFileInfo(this, path, true, null);
- if (this.mFso == null) {
+ // Check that the file exists (the real file, not the symlink)
+ try {
+ this.mFso = CommandHelper.getFileInfo(this, path, true, null);
+ if (this.mFso == null) {
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to get file reference", e); //$NON-NLS-1$
+ }
+
+ // Check that we can handle the length of the file (by device)
+ if (this.mMaxFileSize < this.mFso.getSize()) {
DialogHelper.showToast(
- this, R.string.editor_file_not_found_msg, Toast.LENGTH_SHORT);
+ this, R.string.editor_file_exceed_size_msg, Toast.LENGTH_SHORT);
return;
}
- } catch (Exception e) {
- Log.e(TAG, "Failed to get file reference", e); //$NON-NLS-1$
- DialogHelper.showToast(
- this, R.string.editor_file_not_found_msg, Toast.LENGTH_SHORT);
- return;
- }
- // Check that we can handle the length of the file (by device)
- if (this.mMaxFileSize < this.mFso.getSize()) {
- DialogHelper.showToast(
- this, R.string.editor_file_exceed_size_msg, Toast.LENGTH_SHORT);
- return;
- }
+ // Get the syntax highlight processor
+ SyntaxHighlightFactory shpFactory =
+ SyntaxHighlightFactory.getDefaultFactory(new ResourcesResolver());
+ this.mSyntaxHighlightProcessor = shpFactory.getSyntaxHighlightProcessor(f);
+ if (this.mSyntaxHighlightProcessor != null) {
+ this.mSyntaxHighlightProcessor.initialize();
+ }
- // Get the syntax highlight processor
- SyntaxHighlightFactory shpFactory =
- SyntaxHighlightFactory.getDefaultFactory(new ResourcesResolver());
- this.mSyntaxHighlightProcessor = shpFactory.getSyntaxHighlightProcessor(f);
- if (this.mSyntaxHighlightProcessor != null) {
- this.mSyntaxHighlightProcessor.initialize();
+ // Check that we have read access
+ try {
+ FileHelper.ensureReadAccess(
+ ConsoleBuilder.getConsole(this),
+ this.mFso,
+ null);
+
+ // Read the file in background
+ asyncRead();
+
+ } catch (Exception ex) {
+ ExceptionUtil.translateException(
+ this, ex, false, true, new OnRelaunchCommandResult() {
+ @Override
+ public void onSuccess() {
+ // Read the file in background
+ asyncRead();
+ }
+
+ @Override
+ public void onFailed(Throwable cause) {
+ finish();
+ }
+
+ @Override
+ public void onCancelled() {
+ finish();
+ }
+ });
+ }
}
+ }
- // Check that we have read access
- try {
- FileHelper.ensureReadAccess(
- ConsoleBuilder.getConsole(this),
- this.mFso,
- null);
+ /**
+ * Method that does the read of a content uri in the background
+ * @hide
+ */
+ void asyncReadContentURI(Uri uri) {
+ // Do the load of the file
+ AsyncTask<Uri, Integer, Boolean> mReadTask =
+ new AsyncTask<Uri, Integer, Boolean>() {
+
+ private Exception mCause;
+ private boolean changeToBinaryMode;
+ private boolean changeToDisplaying;
+ private String tempText;
+
+ @Override
+ protected void onPreExecute() {
+ // Show the progress
+ this.changeToBinaryMode = false;
+ this.changeToDisplaying = false;
+ doProgress(true, 0);
+ }
- // Read the file in background
- asyncRead();
+ @Override
+ protected Boolean doInBackground(Uri... params) {
- } catch (Exception ex) {
- ExceptionUtil.translateException(
- this, ex, false, true, new OnRelaunchCommandResult() {
- @Override
- public void onSuccess() {
- // Read the file in background
- asyncRead();
- }
+ // Only one argument (the file to open)
+ Uri fso = params[0];
+ this.mCause = null;
- @Override
- public void onFailed(Throwable cause) {
- finish();
- }
+ // Read the file in an async listener
+ try {
- @Override
- public void onCancelled() {
- finish();
- }
- });
- }
+ publishProgress(Integer.valueOf(0));
+
+ InputStream is = getContentResolver().openInputStream(fso);
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ int readBytes;
+ byte[] buffer = new byte[1024];
+ try {
+ while ((readBytes = is.read(buffer, 0, buffer.length)) != -1) {
+ baos.write(buffer, 0, readBytes);
+ publishProgress(
+ Integer.valueOf((readBytes * 100) / buffer.length));
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ return Boolean.FALSE;
+ }
+
+ // 100%
+ publishProgress(new Integer(100));
+ tempText = new String(baos.toByteArray(), "UTF-8");
+ Log.i(TAG, "Bytes read: " + baos.toByteArray().length); //$NON-NLS-1$
+
+ // 100%
+ this.changeToDisplaying = true;
+ publishProgress(new Integer(0));
+
+ } catch (Exception e) {
+ this.mCause = e;
+ return Boolean.FALSE;
+ }
+
+ return Boolean.TRUE;
+
+ }
+
+ @Override
+ protected void onProgressUpdate(Integer... values) {
+ // Do progress
+ doProgress(true, values[0].intValue());
+ }
+
+ @Override
+ protected void onPostExecute(Boolean result) {
+ final EditorActivity activity = EditorActivity.this;
+ // Is error?
+ if (!result.booleanValue()) {
+ if (this.mCause != null) {
+ ExceptionUtil.translateException(activity, this.mCause);
+ activity.mEditor.setEnabled(false);
+ }
+ } else {
+ // Now we have the buffer, set the text of the editor
+ activity.mEditor.setText(
+ tempText, BufferType.EDITABLE);
+
+ // Highlight editor text syntax
+ if (activity.mSyntaxHighlight &&
+ activity.mSyntaxHighlightProcessor != null) {
+ try {
+ activity.mSyntaxHighlightProcessor.process(
+ activity.mEditor.getText());
+ } catch (Exception ex) {
+ // An error in a syntax library, should not break down app.
+ Log.e(TAG, "Syntax highlight failed.", ex); //$NON-NLS-1$
+ }
+ }
+
+ setDirty(false);
+ activity.mEditor.setEnabled(!activity.mReadOnly);
+
+ // Notify read-only mode
+ if (activity.mReadOnly) {
+ DialogHelper.showToast(
+ activity,
+ R.string.editor_read_only_mode,
+ Toast.LENGTH_SHORT);
+ }
+ }
+
+ doProgress(false, 0);
+ }
+
+ @Override
+ protected void onCancelled() {
+ // Hide the progress
+ doProgress(false, 0);
+ }
+
+ /**
+ * Method that update the progress status
+ *
+ * @param visible If the progress bar need to be hidden
+ * @param progress The progress
+ */
+ private void doProgress(boolean visible, int progress) {
+ final EditorActivity activity = EditorActivity.this;
+
+ // Show the progress bar
+ activity.mProgressBar.setProgress(progress);
+ activity.mProgress.setVisibility(visible ? View.VISIBLE : View.GONE);
+
+ if (this.changeToBinaryMode) {
+ mWordWrapView.setVisibility(View.GONE);
+ mNoWordWrapView.setVisibility(View.GONE);
+ mBinaryEditor.setVisibility(View.VISIBLE);
+
+ // Show hex dumping text
+ activity.mProgressBarMsg.setText(R.string.dumping_message);
+ this.changeToBinaryMode = false;
+ }
+ else if (this.changeToDisplaying) {
+ activity.mProgressBarMsg.setText(R.string.displaying_message);
+ this.changeToDisplaying = false;
+ }
+ }
+ };
+ mReadTask.execute(uri);
}
/**