Save files to external storage
This commit is contained in:
parent
9a493fb536
commit
74a6f930a5
5 changed files with 111 additions and 37 deletions
|
@ -6,8 +6,10 @@ import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.Environment;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.support.v4.app.FragmentActivity;
|
||||||
import android.support.v4.content.FileProvider;
|
import android.support.v4.content.FileProvider;
|
||||||
import android.support.v4.content.LocalBroadcastManager;
|
import android.support.v4.content.LocalBroadcastManager;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
|
@ -18,6 +20,7 @@ import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -34,11 +37,12 @@ public class EditFragment extends Fragment {
|
||||||
public static final String SAVE_ACTION = "com.wbrawner.simplemarkdown.ACTION_SAVE";
|
public static final String SAVE_ACTION = "com.wbrawner.simplemarkdown.ACTION_SAVE";
|
||||||
public static final String LOAD_ACTION = "com.wbrawner.simplemarkdown.ACTION_LOAD";
|
public static final String LOAD_ACTION = "com.wbrawner.simplemarkdown.ACTION_LOAD";
|
||||||
private static EditText mMarkdownEditor;
|
private static EditText mMarkdownEditor;
|
||||||
|
private FileUtils mFileUtils;
|
||||||
|
|
||||||
@BindView(R.id.markdown_edit)
|
@BindView(R.id.markdown_edit)
|
||||||
EditText markdownEditor;
|
EditText markdownEditor;
|
||||||
|
|
||||||
private Context mContext;
|
private FragmentActivity mContext;
|
||||||
|
|
||||||
private File mTmpFile;
|
private File mTmpFile;
|
||||||
private boolean loadTmpFile = true;
|
private boolean loadTmpFile = true;
|
||||||
|
@ -58,6 +62,7 @@ public class EditFragment extends Fragment {
|
||||||
filter
|
filter
|
||||||
);
|
);
|
||||||
mContext = getActivity();
|
mContext = getActivity();
|
||||||
|
mFileUtils = new FileUtils(mContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -111,10 +116,16 @@ public class EditFragment extends Fragment {
|
||||||
|
|
||||||
public void save(String data, String filePath) {
|
public void save(String data, String filePath) {
|
||||||
// TODO: move this to AsyncTask
|
// TODO: move this to AsyncTask
|
||||||
if (filePath == null)
|
if (!mFileUtils.isExternalStorageWriteable()) {
|
||||||
|
mFileUtils.requestWritePermissions();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (filePath == null) {
|
||||||
filePath = MainActivity.getFilePath() + MainActivity.getFileName();
|
filePath = MainActivity.getFilePath() + MainActivity.getFileName();
|
||||||
|
}
|
||||||
FileOutputStream out = null;
|
FileOutputStream out = null;
|
||||||
try {
|
try {
|
||||||
|
Log.d(TAG, "File path: " + filePath);
|
||||||
File tmpFile = new File(filePath);
|
File tmpFile = new File(filePath);
|
||||||
out = new FileOutputStream(tmpFile);
|
out = new FileOutputStream(tmpFile);
|
||||||
out.write(data.getBytes());
|
out.write(data.getBytes());
|
||||||
|
@ -122,8 +133,11 @@ public class EditFragment extends Fragment {
|
||||||
Log.e(TAG, "Error saving temp file:", e);
|
Log.e(TAG, "Error saving temp file:", e);
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
if (out != null)
|
if (out != null) {
|
||||||
out.close();
|
out.close();
|
||||||
|
Toast.makeText(mContext, getString(R.string.file_saved, filePath), Toast.LENGTH_SHORT)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e(TAG, "Error closing write stream", e);
|
Log.e(TAG, "Error closing write stream", e);
|
||||||
}
|
}
|
||||||
|
@ -134,8 +148,8 @@ public class EditFragment extends Fragment {
|
||||||
save(data, null);
|
save(data, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void save(Editable data) {
|
public void save() {
|
||||||
save(data.toString(), null);
|
save(mMarkdownEditor.getText().toString(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -157,6 +171,11 @@ public class EditFragment extends Fragment {
|
||||||
case SAVE_ACTION:
|
case SAVE_ACTION:
|
||||||
if (intent.hasExtra("fileName")) {
|
if (intent.hasExtra("fileName")) {
|
||||||
String fileName = intent.getStringExtra("fileName");
|
String fileName = intent.getStringExtra("fileName");
|
||||||
|
if (!fileName.contains("/")) {
|
||||||
|
fileName = MainActivity.getFilePath() + "/" + fileName;
|
||||||
|
}
|
||||||
|
if (!fileName.endsWith(".md"))
|
||||||
|
fileName += ".md";
|
||||||
save(mMarkdownEditor.getText().toString(), fileName);
|
save(mMarkdownEditor.getText().toString(), fileName);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
64
app/src/main/java/com/wbrawner/simplemarkdown/FileUtils.java
Normal file
64
app/src/main/java/com/wbrawner/simplemarkdown/FileUtils.java
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
package com.wbrawner.simplemarkdown;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.support.v4.app.ActivityCompat;
|
||||||
|
import android.support.v4.content.ContextCompat;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by billy on 7/27/2017.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class FileUtils {
|
||||||
|
|
||||||
|
public static final int WRITE_PERMISSION_REQUEST = 0;
|
||||||
|
|
||||||
|
private Activity mContext;
|
||||||
|
|
||||||
|
public FileUtils(Activity context) {
|
||||||
|
mContext = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isExternalStorageWritable() {
|
||||||
|
String state = Environment.getExternalStorageState();
|
||||||
|
if (Environment.MEDIA_MOUNTED.equals(state)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isExternalStorageReadable() {
|
||||||
|
String state = Environment.getExternalStorageState();
|
||||||
|
if (Environment.MEDIA_MOUNTED.equals(state) ||
|
||||||
|
Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isExternalStorageWriteable() {
|
||||||
|
String state = Environment.getExternalStorageState();
|
||||||
|
if (Environment.MEDIA_MOUNTED.equals(state) && checkWritePermission()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean checkWritePermission() {
|
||||||
|
return (ContextCompat.checkSelfPermission(
|
||||||
|
mContext,
|
||||||
|
Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||||
|
) == PackageManager.PERMISSION_GRANTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void requestWritePermissions() {
|
||||||
|
ActivityCompat.requestPermissions(
|
||||||
|
mContext,
|
||||||
|
new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE},
|
||||||
|
WRITE_PERMISSION_REQUEST
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,6 +8,8 @@ import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.support.design.widget.TabLayout;
|
import android.support.design.widget.TabLayout;
|
||||||
import android.support.v4.app.ActivityCompat;
|
import android.support.v4.app.ActivityCompat;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
|
@ -16,14 +18,17 @@ import android.support.v4.app.FragmentPagerAdapter;
|
||||||
import android.support.v4.content.ContextCompat;
|
import android.support.v4.content.ContextCompat;
|
||||||
import android.support.v4.content.FileProvider;
|
import android.support.v4.content.FileProvider;
|
||||||
import android.support.v4.content.LocalBroadcastManager;
|
import android.support.v4.content.LocalBroadcastManager;
|
||||||
|
import android.support.v4.os.EnvironmentCompat;
|
||||||
import android.support.v4.view.ViewPager;
|
import android.support.v4.view.ViewPager;
|
||||||
import android.support.v7.app.AlertDialog;
|
import android.support.v7.app.AlertDialog;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.text.Editable;
|
||||||
import android.text.InputType;
|
import android.text.InputType;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
import android.view.SearchEvent;
|
||||||
import android.webkit.MimeTypeMap;
|
import android.webkit.MimeTypeMap;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
@ -33,7 +38,8 @@ import java.io.File;
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
|
|
||||||
public class MainActivity extends AppCompatActivity {
|
public class MainActivity extends AppCompatActivity
|
||||||
|
implements ActivityCompat.OnRequestPermissionsResultCallback {
|
||||||
|
|
||||||
public static final String AUTHORITY = "com.wbrawner.simplemarkdown.fileprovider";
|
public static final String AUTHORITY = "com.wbrawner.simplemarkdown.fileprovider";
|
||||||
private static final int REQUEST_WRITE_STORAGE = 0;
|
private static final int REQUEST_WRITE_STORAGE = 0;
|
||||||
|
@ -43,6 +49,7 @@ public class MainActivity extends AppCompatActivity {
|
||||||
|
|
||||||
private static final String TAG = MainActivity.class.getSimpleName();
|
private static final String TAG = MainActivity.class.getSimpleName();
|
||||||
private static String fileName;
|
private static String fileName;
|
||||||
|
public static FileUtils mFileUtils;
|
||||||
|
|
||||||
public static String getTempFileName() {
|
public static String getTempFileName() {
|
||||||
return "tmp_" + getFileName();
|
return "tmp_" + getFileName();
|
||||||
|
@ -62,7 +69,7 @@ public class MainActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getFilePath() {
|
public static String getFilePath() {
|
||||||
return mFilesDir + "/saved_files/";
|
return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS) + "/";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setFileName(String fileName) {
|
public static void setFileName(String fileName) {
|
||||||
|
@ -123,10 +130,7 @@ public class MainActivity extends AppCompatActivity {
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
if (input.getText().length() > 0) {
|
if (input.getText().length() > 0) {
|
||||||
setFileName(input.getText().toString());
|
setFileName(input.getText().toString());
|
||||||
Intent saveIntent = new Intent(EditFragment.SAVE_ACTION);
|
requestSave(input.getText().toString());
|
||||||
saveIntent.putExtra("fileName", input.getText());
|
|
||||||
LocalBroadcastManager.getInstance(getApplicationContext())
|
|
||||||
.sendBroadcast(saveIntent);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -148,11 +152,8 @@ public class MainActivity extends AppCompatActivity {
|
||||||
LocalBroadcastManager.getInstance(getApplicationContext())
|
LocalBroadcastManager.getInstance(getApplicationContext())
|
||||||
.sendBroadcast(saveIntent);
|
.sendBroadcast(saveIntent);
|
||||||
}
|
}
|
||||||
Log.d(TAG, "Temp file size: " + tmpFile.length());
|
|
||||||
Uri fileUri = FileProvider.getUriForFile(MainActivity.this, AUTHORITY, tmpFile);
|
Uri fileUri = FileProvider.getUriForFile(MainActivity.this, AUTHORITY, tmpFile);
|
||||||
// Uri fileUri = Uri.fromFile(tmpFile);
|
|
||||||
if (fileUri != null) {
|
if (fileUri != null) {
|
||||||
Log.d(TAG, "MIME type: " + getContentResolver().getType(fileUri));
|
|
||||||
try {
|
try {
|
||||||
Intent shareIntent = new Intent(Intent.ACTION_SEND);
|
Intent shareIntent = new Intent(Intent.ACTION_SEND);
|
||||||
shareIntent.setDataAndType(
|
shareIntent.setDataAndType(
|
||||||
|
@ -177,33 +178,31 @@ public class MainActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
// case R.id.action_export:
|
|
||||||
// //TODO: Implement export functionality
|
|
||||||
// if (ContextCompat.checkSelfPermission(MainActivity.this,
|
|
||||||
// Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
|
||||||
// != PackageManager.PERMISSION_GRANTED){
|
|
||||||
// ActivityCompat.requestPermissions(MainActivity.this,
|
|
||||||
// new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
|
|
||||||
// REQUEST_WRITE_STORAGE);
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void requestSave(String text) {
|
||||||
|
Intent saveIntent = new Intent(EditFragment.SAVE_ACTION);
|
||||||
|
saveIntent.putExtra("fileName", text);
|
||||||
|
LocalBroadcastManager.getInstance(getApplicationContext())
|
||||||
|
.sendBroadcast(saveIntent);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRequestPermissionsResult(int requestCode,
|
public void onRequestPermissionsResult(int requestCode,
|
||||||
String permissions[], int[] grantResults) {
|
String permissions[], int[] grantResults) {
|
||||||
//TODO: Implement export functionality
|
|
||||||
switch (requestCode) {
|
switch (requestCode) {
|
||||||
case REQUEST_WRITE_STORAGE: {
|
case FileUtils.WRITE_PERMISSION_REQUEST: {
|
||||||
// If request is cancelled, the result arrays are empty.
|
// If request is cancelled, the result arrays are empty.
|
||||||
if (grantResults.length > 0
|
if (grantResults.length > 0
|
||||||
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||||
// Permission granted, open file chooser dialog
|
// Permission granted, open file chooser dialog
|
||||||
|
requestSave(getFileName());
|
||||||
} else {
|
} else {
|
||||||
// Permission denied, do nothing
|
// Permission denied, do nothing
|
||||||
|
Toast.makeText(MainActivity.this, R.string.no_permissions, Toast.LENGTH_SHORT)
|
||||||
|
.show();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,16 +11,6 @@
|
||||||
android:id="@+id/action_share"
|
android:id="@+id/action_share"
|
||||||
android:icon="@android:drawable/ic_menu_share"
|
android:icon="@android:drawable/ic_menu_share"
|
||||||
app:showAsAction="always" />
|
app:showAsAction="always" />
|
||||||
<!--<item-->
|
|
||||||
<!--android:id="@+id/action_export"-->
|
|
||||||
<!--android:orderInCategory="100"-->
|
|
||||||
<!--android:title="@string/action_export"-->
|
|
||||||
<!--app:showAsAction="never" />-->
|
|
||||||
<!--<item-->
|
|
||||||
<!--android:id="@+id/action_settings"-->
|
|
||||||
<!--android:orderInCategory="100"-->
|
|
||||||
<!--android:title="@string/action_settings"-->
|
|
||||||
<!--app:showAsAction="never" />-->
|
|
||||||
<!--<item-->
|
<!--<item-->
|
||||||
<!--android:id="@+id/action_help"-->
|
<!--android:id="@+id/action_help"-->
|
||||||
<!--android:orderInCategory="100"-->
|
<!--android:orderInCategory="100"-->
|
||||||
|
|
|
@ -14,4 +14,6 @@
|
||||||
<string name="action_export">Export</string>
|
<string name="action_export">Export</string>
|
||||||
<string name="no_shareable_apps">Unable to share file - no capable apps installed</string>
|
<string name="no_shareable_apps">Unable to share file - no capable apps installed</string>
|
||||||
<string name="share_file">Share file to...</string>
|
<string name="share_file">Share file to...</string>
|
||||||
|
<string name="no_permissions">Unable to save file without permissions</string>
|
||||||
|
<string name="file_saved">File saved to %1$s</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Reference in a new issue