Java tutorial
/* * Copyright (C) 2014 Vlad Mihalachi * * This file is part of Turbo Editor. * * Turbo Editor is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Turbo Editor is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.slim.turboeditor.activity; import android.app.ActionBar; import android.app.ProgressDialog; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.res.Configuration; import android.graphics.Typeface; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.support.annotation.NonNull; import android.support.v7.widget.Toolbar; import android.text.TextUtils; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.inputmethod.InputMethodManager; import android.widget.HorizontalScrollView; import android.widget.Toast; import com.getbase.floatingactionbutton.FloatingActionButton; import com.slim.slimfilemanager.R; import com.slim.slimfilemanager.ThemeActivity; import com.slim.slimfilemanager.settings.SettingsProvider; import com.slim.slimfilemanager.utils.FileUtil; import com.slim.slimfilemanager.utils.RootUtils; import com.slim.turboeditor.dialogfragment.FindTextDialog; import com.slim.turboeditor.dialogfragment.NumberPickerDialog; import com.slim.turboeditor.dialogfragment.SaveFileDialog; import com.slim.turboeditor.texteditor.FileUtils; import com.slim.turboeditor.texteditor.LineUtils; import com.slim.turboeditor.texteditor.PageSystem; import com.slim.turboeditor.texteditor.PageSystemButtons; import com.slim.turboeditor.texteditor.SearchResult; import com.slim.turboeditor.views.Editor; import com.slim.turboeditor.views.GoodScrollView; import com.slim.util.Constant; import org.apache.commons.io.FilenameUtils; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.lang.ref.WeakReference; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import butterknife.Bind; import butterknife.ButterKnife; import rx.Observable; import rx.Observer; import rx.Subscriber; import rx.android.schedulers.AndroidSchedulers; import rx.functions.Action1; import rx.schedulers.Schedulers; import trikita.log.Log; import static butterknife.ButterKnife.findById; public class MainActivity extends ThemeActivity implements FindTextDialog.SearchDialogInterface, GoodScrollView.ScrollInterface, PageSystem.PageSystemInterface, PageSystemButtons.PageButtonsInterface, NumberPickerDialog.INumberPickerDialog, SaveFileDialog.ISaveDialog, Observer<Boolean> { //region VARIABLES private static final int READ_REQUEST_CODE = 42, CREATE_REQUEST_CODE = 43, SAVE_AS_REQUEST_CODE = 44, SELECT_FILE_CODE = 121, SYNTAX_DELAY_MILLIS_SHORT = 250, SYNTAX_DELAY_MILLIS_LONG = 1500, ID_UNDO = R.id.im_undo, ID_REDO = R.id.im_redo; private static String currentEncoding = "UTF-16"; private final Handler updateHandler = new Handler(); @Bind(R.id.horizontal_scroll) HorizontalScrollView mHorizontalScroll; @Bind(R.id.vertical_scroll) GoodScrollView verticalScroll; @Bind(R.id.editor) Editor mEditor; private final Runnable colorRunnable_duringEditing = new Runnable() { @Override public void run() { mEditor.replaceTextKeepCursor(null); } }; private final Runnable colorRunnable_duringScroll = new Runnable() { @Override public void run() { mEditor.replaceTextKeepCursor(null); } }; SharedPreferences.OnSharedPreferenceChangeListener mPreferenceListener = new SharedPreferences.OnSharedPreferenceChangeListener() { @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { onPreferencesChanged(key); } }; private File mFile; private boolean fileOpened = false; private Executor mExecutor = Executors.newSingleThreadExecutor(); private NewFileTask mNewFileTask; private ProgressDialog mProgressDialog; private SearchResult searchResult; private PageSystem pageSystem; private PageSystemButtons pageSystemButtons; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_home); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); toolbar.setTitle(R.string.text_editor); ButterKnife.bind(this); mProgressDialog = new ProgressDialog(this); mProgressDialog.setMessage(getString(R.string.please_wait)); setupTextEditor(); hideTextEditor(); parseIntent(getIntent()); SettingsProvider.get(this).registerOnSharedPreferenceChangeListener(mPreferenceListener); } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); parseIntent(intent); } public void showProgressDialog() { mProgressDialog.show(); } public void hideProgressDialog() { mProgressDialog.dismiss(); } @Override public void onPause() { super.onPause(); if (mNewFileTask != null) { mNewFileTask.cancel(true); mNewFileTask = null; } hideProgressDialog(); if (SettingsProvider.getBoolean(this, "auto_save", false) && mEditor.canSaveFile()) { saveTheFile(false); mEditor.fileSaved(); // so it doesn't ask to save in onDetach } } @Override public void onDestroy() { try { closeKeyBoard(); } catch (NullPointerException e) { e.printStackTrace(); } SettingsProvider.get(this).unregisterOnSharedPreferenceChangeListener(mPreferenceListener); super.onDestroy(); } public PageSystem getPageSystem() { return pageSystem; } @Override public final void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); } @Override public boolean onKeyDown(int keyCode, @NonNull KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { onBackPressed(); return true; } else if (keyCode == KeyEvent.KEYCODE_MENU) { return false; } else { if (mEditor == null) mEditor = findById(this, R.id.editor); // this will happen on first key pressed on hard-keyboard only. Once myInputField // gets the focus again, it will automatically receive further key presses. try { if (fileOpened && mEditor != null && !mEditor.hasFocus()) { mEditor.requestFocus(); mEditor.onKeyDown(keyCode, event); return true; } } catch (NullPointerException ex) { // Ignore } } return false; } @Override public void onBackPressed() { if (mEditor.canSaveFile()) { new SaveFileDialog(mFile, pageSystem.getAllText(mEditor.getText().toString()), currentEncoding) .show(getFragmentManager(), "dialog"); } else { super.onBackPressed(); } } @Override protected void onActivityResult(int requestCode, int resultCode, final Intent intent) { super.onActivityResult(requestCode, resultCode, intent); if (resultCode == RESULT_OK) { if (requestCode == SELECT_FILE_CODE) { final Uri data = intent.getData(); File newFile = new File(data.getPath()); newFileToOpen(newFile, ""); } else { final Uri data = intent.getData(); final File newFile = new File(data.getPath()); // grantUriPermission(getPackageName(), // data, Intent.FLAG_GRANT_READ_URI_PERMISSION); // Check for the freshest data. getContentResolver().takePersistableUriPermission(data, (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION)); if (requestCode == READ_REQUEST_CODE || requestCode == CREATE_REQUEST_CODE) { newFileToOpen(newFile, ""); } if (requestCode == SAVE_AS_REQUEST_CODE) { getSaveFileObservable(getApplicationContext(), newFile, pageSystem.getAllText(mEditor.getText().toString()), currentEncoding) .subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()) .subscribe(new Action1<Boolean>() { @Override public void call(Boolean aBoolean) { savedAFile(aBoolean); newFileToOpen(newFile, ""); } }); } } } } @Override public boolean onCreateOptionsMenu(Menu menu) { if (fileOpened && searchResult != null) getMenuInflater().inflate(R.menu.fragment_editor_search, menu); else if (fileOpened) getMenuInflater().inflate(R.menu.fragment_editor, menu); return super.onCreateOptionsMenu(menu); } @Override public boolean onPrepareOptionsMenu(Menu menu) { if (fileOpened && searchResult != null) { MenuItem imReplace = menu.findItem(R.id.im_replace); MenuItem imReplaceAll = menu.findItem(R.id.im_replace_all); MenuItem imPrev = menu.findItem(R.id.im_previous_item); MenuItem imNext = menu.findItem(R.id.im_next_item); if (imReplace != null) imReplace.setVisible(searchResult.canReplaceSomething()); if (imReplaceAll != null) imReplaceAll.setVisible(searchResult.canReplaceSomething()); if (imPrev != null) imPrev.setVisible(searchResult.hasPrevious()); if (imNext != null) imNext.setVisible(searchResult.hasNext()); } else if (fileOpened) { MenuItem imSave = menu.findItem(R.id.im_save); MenuItem imUndo = menu.findItem(R.id.im_undo); MenuItem imRedo = menu.findItem(R.id.im_redo); if (mEditor != null) { if (imSave != null) imSave.setVisible(mEditor.canSaveFile()); if (imUndo != null) imUndo.setVisible(mEditor.getCanUndo()); if (imRedo != null) imRedo.setVisible(mEditor.getCanRedo()); } else { imSave.setVisible(false); imUndo.setVisible(false); imRedo.setVisible(false); } } return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int i = item.getItemId(); if (i == R.id.im_save_normaly) { saveTheFile(false); } else if (i == R.id.im_save_as) { saveTheFile(true); } else if (i == R.id.im_undo) { mEditor.onTextContextMenuItem(ID_UNDO); } else if (i == R.id.im_redo) { mEditor.onTextContextMenuItem(ID_REDO); } else if (i == R.id.im_search) { FindTextDialog.newInstance(mEditor.getText().toString()).show(getFragmentManager().beginTransaction(), "dialog"); } else if (i == R.id.im_cancel) { searchResult = null; invalidateOptionsMenu(); } else if (i == R.id.im_replace) { replaceText(false); } else if (i == R.id.im_replace_all) { replaceText(true); } else if (i == R.id.im_next_item) { nextResult(); } else if (i == R.id.im_previous_item) { previousResult(); } else if (i == R.id.im_goto_line) { int min = mEditor.getLineUtils().firstReadLine(); int max = mEditor.getLineUtils().lastReadLine(); NumberPickerDialog.newInstance(NumberPickerDialog.Actions.GoToLine, min, min, max) .show(getFragmentManager().beginTransaction(), "dialog"); } return super.onOptionsItemSelected(item); } void replaceText(boolean all) { if (all) { mEditor.setText(pageSystem.getAllText(mEditor.getText().toString()) .replaceAll(searchResult.whatToSearch, searchResult.textToReplace)); searchResult = null; invalidateOptionsMenu(); } else { int start = searchResult.foundIndex.get(searchResult.index); int end = start + searchResult.textLength; mEditor.setText(mEditor.getText().replace(start, end, searchResult.textToReplace)); searchResult.doneReplace(); invalidateOptionsMenu(); if (searchResult.hasNext()) nextResult(); else if (searchResult.hasPrevious()) previousResult(); } } void nextResult() { if (searchResult.index == mEditor.getLineCount() - 1) // last result of page { return; } if (searchResult.index < searchResult.numberOfResults() - 1) { // equal zero is not good searchResult.index++; final int line = LineUtils.getLineFromIndex(searchResult.foundIndex.get(searchResult.index), mEditor.getLineCount(), mEditor.getLayout()); verticalScroll.post(new Runnable() { @Override public void run() { int y = mEditor.getLayout().getLineTop(line); if (y > 100) y -= 100; else y = 0; verticalScroll.scrollTo(0, y); } }); mEditor.setFocusable(true); mEditor.requestFocus(); mEditor.setSelection(searchResult.foundIndex.get(searchResult.index), searchResult.foundIndex.get(searchResult.index) + searchResult.textLength); } invalidateOptionsMenu(); } void previousResult() { if (searchResult.index == 0) return; if (searchResult.index > 0) { searchResult.index--; final int line = LineUtils.getLineFromIndex(searchResult.foundIndex.get(searchResult.index), mEditor.getLineCount(), mEditor.getLayout()); verticalScroll.post(new Runnable() { @Override public void run() { int y = mEditor.getLayout().getLineTop(line); if (y > 100) y -= 100; else y = 0; verticalScroll.scrollTo(0, y); } }); mEditor.setFocusable(true); mEditor.requestFocus(); mEditor.setSelection(searchResult.foundIndex.get(searchResult.index), searchResult.foundIndex.get(searchResult.index) + searchResult.textLength); } invalidateOptionsMenu(); } public void saveTheFile(final boolean saveAs) { if (!saveAs && mFile != null && mFile.exists()) { Observable<Boolean> saveFile = getSaveFileObservable(getApplicationContext(), mFile, pageSystem.getAllText(mEditor.getText().toString()), currentEncoding) .subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()).cache(); saveFile.subscribe(new Action1<Boolean>() { @Override public void call(Boolean aBoolean) { Log.d("call(" + aBoolean + ")"); savedAFile(aBoolean); } }); } else { Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT); intent.setType("*/*"); intent.putExtra(Intent.EXTRA_TITLE, mFile.getName()); startActivityForResult(intent, SAVE_AS_REQUEST_CODE); } } private void setupTextEditor() { if (SettingsProvider.getBoolean(this, SettingsProvider.EDITOR_WRAP_CONTENT, false)) { mHorizontalScroll.removeView(mEditor); verticalScroll.removeView(mHorizontalScroll); verticalScroll.addView(mEditor); } verticalScroll.setScrollInterface(this); pageSystem = new PageSystem(this); pageSystemButtons = new PageSystemButtons(this, this, (FloatingActionButton) findById(this, R.id.fabPrev), (FloatingActionButton) findById(this, R.id.fabNext)); mEditor.setupEditor(this, verticalScroll); } private void showTextEditor() { fileOpened = true; findById(this, R.id.text_editor).setVisibility(View.VISIBLE); mEditor.resetVariables(); searchResult = null; invalidateOptionsMenu(); mEditor.disableTextChangedListener(); mEditor.replaceTextKeepCursor(pageSystem.getCurrentPageText()); mEditor.enableTextChangedListener(); } private void hideTextEditor() { fileOpened = false; try { findById(this, R.id.text_editor).setVisibility(View.GONE); mEditor.disableTextChangedListener(); mEditor.replaceTextKeepCursor(""); mEditor.enableTextChangedListener(); } catch (Exception e) { // lol } } /** * Parses the intent */ private void parseIntent(Intent intent) { final String action = intent.getAction(); final String type = intent.getType(); if (Intent.ACTION_VIEW.equals(action) || Intent.ACTION_EDIT.equals(action) || Intent.ACTION_PICK.equals(action) && type != null) { Uri uri = intent.getData(); File newFile = new File(uri.getPath()); newFileToOpen(newFile, ""); } else if (Intent.ACTION_SEND.equals(action) && type != null) { if ("text/plain".equals(type)) { newFileToOpen(null, intent.getStringExtra(Intent.EXTRA_TEXT)); } } } // closes the soft keyboard private void closeKeyBoard() throws NullPointerException { // Central system API to the overall input method framework (IMF) architecture InputMethodManager inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); // Base interface for a remotable object if (getCurrentFocus() != null) { IBinder windowToken = getCurrentFocus().getWindowToken(); // Hide type int hideType = InputMethodManager.HIDE_NOT_ALWAYS; // Hide the KeyBoard inputManager.hideSoftInputFromWindow(windowToken, hideType); } } public void updateTextSyntax() { if (mEditor.hasSelection()) return; updateHandler.removeCallbacks(colorRunnable_duringEditing); updateHandler.removeCallbacks(colorRunnable_duringScroll); updateHandler.postDelayed(colorRunnable_duringEditing, SYNTAX_DELAY_MILLIS_LONG); } void newFileToOpen(final File newFile, final String newFileText) { if (fileOpened && mEditor != null && mEditor.canSaveFile() && mFile != null && pageSystem != null && currentEncoding != null) { new SaveFileDialog(mFile, pageSystem.getAllText(mEditor.getText().toString()), currentEncoding, true) .show(getFragmentManager(), "dialog"); return; } showProgressDialog(); if (mNewFileTask != null && mNewFileTask.getStatus() == AsyncTask.Status.RUNNING) { mNewFileTask.cancel(true); } mFile = newFile; mNewFileTask = new NewFileTask(); mNewFileTask.setMainActivity(this); mNewFileTask.setNewFile(newFile); mNewFileTask.setNewFileText(newFileText); mNewFileTask.executeOnExecutor(mExecutor); } @Override public void onCompleted() { Toast.makeText(this, String.format(getString(R.string.file_saved_with_success), mFile.getName()), Toast.LENGTH_SHORT).show(); } @Override public void onError(Throwable e) { Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT).show(); } @Override public void onNext(Boolean b) { savedAFile(b); } public void savedAFile(boolean success) { mEditor.clearHistory(); mEditor.fileSaved(); invalidateOptionsMenu(); try { closeKeyBoard(); } catch (NullPointerException e) { e.printStackTrace(); } if (success) finish(); } /** * When a file can't be opened * Invoked by the EditorFragment */ void cannotOpenFile() { if (getActionBar() != null) getActionBar().setTitle(getString(R.string.nome_app_turbo_editor)); invalidateOptionsMenu(); // Replace fragment hideTextEditor(); } void onPreferencesChanged(String key) { switch (key) { case SettingsProvider.EDITOR_WRAP_CONTENT: if (SettingsProvider.getBoolean(this, SettingsProvider.EDITOR_WRAP_CONTENT, false)) { mHorizontalScroll.removeView(mEditor); verticalScroll.removeView(mHorizontalScroll); verticalScroll.addView(mEditor); } else { verticalScroll.removeView(mEditor); verticalScroll.addView(mHorizontalScroll); mHorizontalScroll.addView(mEditor); } break; case SettingsProvider.USE_MONOSPACE: if (SettingsProvider.getBoolean(this, SettingsProvider.USE_MONOSPACE, false)) { mEditor.setTypeface(Typeface.MONOSPACE); } else { mEditor.setTypeface(Typeface.DEFAULT); } break; case SettingsProvider.FONT_SIZE: mEditor.updatePadding(); mEditor.setTextSize(SettingsProvider.getInt(this, SettingsProvider.FONT_SIZE, 16)); break; case SettingsProvider.EDITOR_ENCODING: String oldEncoding, newEncoding; oldEncoding = currentEncoding; newEncoding = SettingsProvider.getString(this, SettingsProvider.EDITOR_ENCODING, Constant.DEFAULT_ENCODING); try { final byte[] oldText = mEditor.getText().toString().getBytes(oldEncoding); mEditor.disableTextChangedListener(); mEditor.replaceTextKeepCursor(new String(oldText, newEncoding)); mEditor.enableTextChangedListener(); currentEncoding = newEncoding; } catch (UnsupportedEncodingException ignored) { try { final byte[] oldText = mEditor.getText().toString().getBytes(oldEncoding); mEditor.disableTextChangedListener(); mEditor.replaceTextKeepCursor(new String(oldText, Constant.DEFAULT_ENCODING)); mEditor.enableTextChangedListener(); } catch (UnsupportedEncodingException ignored2) { // Ignored } } break; } } @Override public void nextPageClicked() { pageSystem.savePage(mEditor.getText().toString()); pageSystem.nextPage(); mEditor.disableTextChangedListener(); mEditor.replaceTextKeepCursor(pageSystem.getCurrentPageText()); mEditor.enableTextChangedListener(); verticalScroll.postDelayed(new Runnable() { @Override public void run() { verticalScroll.smoothScrollTo(0, 0); } }, 200); } @Override public void prevPageClicked() { pageSystem.savePage(mEditor.getText().toString()); pageSystem.prevPage(); mEditor.disableTextChangedListener(); mEditor.replaceTextKeepCursor(pageSystem.getCurrentPageText()); mEditor.enableTextChangedListener(); verticalScroll.postDelayed(new Runnable() { @Override public void run() { verticalScroll.smoothScrollTo(0, 0); } }, 200); } @Override public void pageSystemButtonLongClicked() { int maxPages = pageSystem.getMaxPage(); int currentPage = pageSystem.getCurrentPage(); NumberPickerDialog.newInstance(NumberPickerDialog.Actions.SelectPage, 0, currentPage, maxPages) .show(getFragmentManager().beginTransaction(), "dialog"); } @Override public boolean canReadNextPage() { return pageSystem.canReadNextPage(); } @Override public boolean canReadPrevPage() { return pageSystem.canReadPrevPage(); } @Override public void onSearchDone(SearchResult searchResult) { invalidateOptionsMenu(); final int line = LineUtils.getLineFromIndex(searchResult.foundIndex.getFirst(), mEditor.getLineCount(), mEditor.getLayout()); verticalScroll.post(new Runnable() { @Override public void run() { int y = mEditor.getLayout().getLineTop(line); if (y > 100) y -= 100; else y = 0; verticalScroll.scrollTo(0, y); } }); mEditor.setFocusable(true); mEditor.requestFocus(); mEditor.setSelection(searchResult.foundIndex.getFirst(), searchResult.foundIndex.getFirst() + searchResult.textLength); } @Override public void onPageChanged(int page) { pageSystemButtons.updateVisibility(false); searchResult = null; mEditor.clearHistory(); invalidateOptionsMenu(); } @Override public void onScrollChanged(int l, int t, int oldl, int oldt) { pageSystemButtons.updateVisibility(Math.abs(t) > 10); if (mEditor.hasSelection() && searchResult == null) return; updateHandler.removeCallbacks(colorRunnable_duringEditing); updateHandler.removeCallbacks(colorRunnable_duringScroll); updateHandler.postDelayed(colorRunnable_duringScroll, SYNTAX_DELAY_MILLIS_SHORT); } @Override public void onNumberPickerDialogDismissed(NumberPickerDialog.Actions action, int value) { if (action == NumberPickerDialog.Actions.SelectPage) { pageSystem.savePage(mEditor.getText().toString()); pageSystem.goToPage(value); mEditor.disableTextChangedListener(); mEditor.replaceTextKeepCursor(pageSystem.getCurrentPageText()); mEditor.enableTextChangedListener(); verticalScroll.postDelayed(new Runnable() { @Override public void run() { verticalScroll.smoothScrollTo(0, 0); } }, 200); } else if (action == NumberPickerDialog.Actions.GoToLine) { int fakeLine = mEditor.getLineUtils().fakeLineFromRealLine(value); final int y = LineUtils.getYAtLine(verticalScroll, mEditor.getLineCount(), fakeLine); verticalScroll.postDelayed(new Runnable() { @Override public void run() { verticalScroll.smoothScrollTo(0, y); } }, 200); } } @Override public void userDoesntWantToSave(boolean openNewFile, File file) { mEditor.fileSaved(); if (openNewFile) newFileToOpen(file, ""); else cannotOpenFile(); } public Observable<Boolean> getSaveFileObservable(final Context context, final File file, final String newContent, final String encoding) { return Observable.create(new Observable.OnSubscribe<Boolean>() { @Override public void call(Subscriber<? super Boolean> subscriber) { try { String filePath = mFile.getAbsolutePath(); // if the uri has no path if (TextUtils.isEmpty(filePath)) { FileUtil.writeUri(context, Uri.fromFile(file), newContent, encoding); } else { FileUtil.writeFile(context, newContent, file, encoding); } subscriber.onNext(true); subscriber.onCompleted(); } catch (Exception e) { e.printStackTrace(); subscriber.onNext(false); subscriber.onError(e); } } }); } private static class NewFileTask extends AsyncTask<Void, Void, String> { String message = ""; String fileText = ""; String fileName = ""; String encoding = "UTF-16"; boolean isRootRequired = false; File newFile; String newFileText; // reference to the activity private WeakReference<MainActivity> mActivityReference; private void setNewFile(File f) { newFile = f; } private void setNewFileText(String t) { newFileText = t; } private void setMainActivity(MainActivity activity) { mActivityReference = new WeakReference<>(activity); } @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected String doInBackground(Void... params) { try { if (isCancelled()) return ""; // if no new uri if (newFile == null) { fileText = newFileText; return "txt"; } else { String filePath = newFile.getAbsolutePath(); // if the uri has no path if (TextUtils.isEmpty(filePath)) { fileName = newFile.getName(); readUri(newFile, false); return FilenameUtils.getExtension(fileName).toLowerCase(); } else { fileName = FilenameUtils.getName(filePath); isRootRequired = !newFile.canRead(); // if we cannot read the file, root permission required if (isRootRequired) { readUri(newFile, true); } else { readUri(newFile, false); } return FilenameUtils.getExtension(fileName).toLowerCase(); } } } catch (Exception e) { message = e.getMessage(); fileText = ""; } return null; } private void readUri(File file, boolean asRoot) throws IOException { BufferedReader buffer = null; StringBuilder stringBuilder = new StringBuilder(); String line; if (asRoot) { encoding = "UTF-8"; fileText = RootUtils.readFile(file); } else { if (mActivityReference.get() != null) { encoding = FileUtils.getDetectedEncoding( mActivityReference.get().getContentResolver().openInputStream(Uri.fromFile(file))); if (encoding.isEmpty()) { encoding = SettingsProvider.getString(mActivityReference.get(), SettingsProvider.EDITOR_ENCODING, Constant.DEFAULT_ENCODING); } InputStream inputStream = mActivityReference.get().getContentResolver() .openInputStream(Uri.fromFile(file)); if (inputStream != null) { buffer = new BufferedReader(new InputStreamReader(inputStream, encoding)); } } } if (buffer != null) { while ((line = buffer.readLine()) != null) { if (isCancelled()) { break; } stringBuilder.append(line); stringBuilder.append("\n"); } buffer.close(); fileText = stringBuilder.toString(); } } @Override protected void onPostExecute(String result) { super.onPostExecute(result); if (isCancelled()) return; MainActivity activity = mActivityReference.get(); if (activity == null) return; activity.mEditor.setExtension(result); activity.hideProgressDialog(); if (!TextUtils.isEmpty(message)) { Toast.makeText(activity, message, Toast.LENGTH_LONG).show(); activity.cannotOpenFile(); } else { activity.pageSystem.setFileText(fileText); currentEncoding = encoding; activity.showTextEditor(); ActionBar ab = activity.getActionBar(); if (ab != null) { if (fileName.isEmpty()) ab.setTitle(R.string.new_file); else ab.setTitle(fileName); } } } } }