From: Stephen Bird Date: Thu, 2 Jul 2015 21:01:49 +0000 (-0700) Subject: Editor: Handle content uri's in the editor X-Git-Tag: android-x86-6.0-r1~73 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=e09d8433144ac84045e1fbd7bb4723c7cfb66c65;p=android-x86%2Fpackages-apps-CMFileManager.git 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 --- diff --git a/src/com/cyanogenmod/filemanager/activities/EditorActivity.java b/src/com/cyanogenmod/filemanager/activities/EditorActivity.java index 7866102..dfd90b9 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 mReadTask = + new AsyncTask() { + + 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); } /**