Android didn't have a standard file browsing UI, so it had to be implemented individually. The new storage access framework made it easy to implement reading and writing files, so I'll remind you. You can access Google Drive, SD card, and internal shared storage. I created a sample application that loads, edits, and saves a text file.
"Basic Activity" was selected as the Activity, and all the code was written in the Main Activity. The project name is "FileSample". The description related to FloatingButton was deleted.
MainActivity.java
package xx.xx.xx.xx.filesample;
import android.content.ClipData;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.DocumentsContract;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.Toast;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.OutputStream;
public class MainActivity extends AppCompatActivity implements View.OnTouchListener {
static final int REQUEST_OPEN_FILE = 1001;
static final int REQUEST_CREATE_FILE = 1002;
static final int REQUEST_DELETE_FILE = 1003;
enum Mode {OPEN, CREATE, DELETE};
EditText editText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
editText = findViewById(R.id.edit_text);
editText.setOnTouchListener(this);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
switch (id) {
case R.id.action_load:
startFileBrowser(Mode.OPEN);
return true;
case R.id.action_save:
startFileBrowser(Mode.CREATE);
return true;
case R.id.action_delete:
startFileBrowser(Mode.DELETE);
return true;
}
return super.onOptionsItemSelected(item);
}
private void startFileBrowser(Mode mode) {
Intent intent = null;
try {
switch (mode) {
case OPEN:
intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.setType("text/plain"); //TEXT file only
intent.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(Intent.createChooser(intent, "Open a file"), REQUEST_OPEN_FILE);
break;
case CREATE:
intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
intent.setType("text/plain"); //TEXT file only
intent.putExtra(Intent.EXTRA_TITLE, "newfile.txt");
intent.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(Intent.createChooser(intent, "Create a file"), REQUEST_CREATE_FILE);
break;
case DELETE:
intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.setType("text/plain"); //TEXT file only
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
startActivityForResult(Intent.createChooser(intent, "Delete a file"), REQUEST_DELETE_FILE);
break;
default:
}
} catch (android.content.ActivityNotFoundException ex) {
// Potentially direct the user to the Market with a Dialog
Toast.makeText(this, "Please install a File Browser/Manager", Toast.LENGTH_LONG).show();
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// File load
if (requestCode == REQUEST_OPEN_FILE) {
if (resultCode == RESULT_OK && data != null) {
Uri uri = data.getData();
if (uri != null) {
editText.setText(loadStrFromUri(uri));
}
}
}
// File save
else if (requestCode == REQUEST_CREATE_FILE) {
if (resultCode == RESULT_OK && data != null) {
Uri uri = data.getData();
if (uri != null) {
saveStrToUri(uri, editText.getText().toString());
}
}
}
// File delete
else if (requestCode == REQUEST_DELETE_FILE) {
if (resultCode == RESULT_OK && data != null) {
ClipData clipData = data.getClipData();
if(clipData==null){ // single selection
Uri uri = data.getData();
deleteUri(uri);
}else { // multiple selection
for (int i = 0; i < clipData.getItemCount(); i++) {
Uri uri = clipData.getItemAt(i).getUri();
deleteUri(uri);
}
}
}
}
}
String loadStrFromUri(Uri uri) {
String str = "";
Boolean loop=true;
try {
if (uri.getScheme().equals("content")) {
InputStream iStream = getContentResolver().openInputStream(uri);
if(iStream==null) loop=false;
ByteArrayOutputStream bout = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
while (loop) {
int len = iStream.read(buffer);
if (len < 0) break;
bout.write(buffer, 0, len);
}
str = bout.toString();
} else {
Toast.makeText(this, "Unknown scheme", Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
Toast.makeText(this, "Cannot read the file:" + e.toString(), Toast.LENGTH_LONG).show();
}
return str;
}
void saveStrToUri(Uri uri, String str) {
try {
if (uri.getScheme().equals("content")) {
OutputStream oStream = getContentResolver().openOutputStream(uri);
if(oStream!=null) oStream.write(str.getBytes());
} else {
Toast.makeText(this, "Unknown scheme", Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
Toast.makeText(this, "Cannot write the file:" + e.toString(), Toast.LENGTH_LONG).show();
}
}
void deleteUri(Uri uri) {
try {
DocumentsContract.deleteDocument(getContentResolver(), uri);
} catch(FileNotFoundException e){
Toast.makeText(this, "Cannot find the file:" + e.toString(), Toast.LENGTH_LONG).show();
}
}
//Below is the code to redisplay the virtual keyboard with touch.
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
view.performClick();
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
if(view == editText) showKeyboard();
break;
}
return false;
}
void showKeyboard() {
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
if(inputMethodManager != null) inputMethodManager.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT);
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
}
}
Calling Intent.ACTION_OPEN_DOCUMENT or Intent.ACTION_CREATE_DOCUMENT brings up the file browsing UI. When the user selects a text file in the UI, the corresponding URI is returned, which is used to read and write the file.
In "Basic Activity", two layout files "activity_main.xml" and "content_main.xml" are created corresponding to MainActivity.java. Among them, describe content_main.xml as follows and display the text display / edit UI in full screen.
content_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context=".MainActivity"
tools:showIn="@layout/activity_main">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="@+id/edit_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:inputType="textMultiLine"
android:textIsSelectable="true" />
</ScrollView>
</android.support.constraint.ConstraintLayout>
You can select READ and WRITE for files in the main menu. Select READ to read the text from the file and display it on the screen. Select WRITE to write the text displayed on the screen to a file.
menu_main.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="me.osdn.users.watanaby.filesample.MainActivity">
<item
android:id="@+id/action_load"
android:orderInCategory="100"
android:title="Load"
app:showAsAction="never" />
<item
android:id="@+id/action_save"
android:orderInCategory="100"
android:title="Save"
app:showAsAction="never" />
<item
android:id="@+id/action_delete"
android:orderInCategory="100"
android:title="Delete"
app:showAsAction="never" />
</menu>
1 2 3
4 5 6
When you start the app, the edit screen is displayed. Call Load, Save, and Delete from the menu icon at the top right of the screen (Screenshot 1). On the file browse screen, you can select storage from the menu at the top left (screenshots 2 and 3). In Save, you can either key in the file name to create a new one, or touch the existing file name to rewrite it (Screenshot 4). With Load and Delete, the key input field does not appear (Screenshot 5). With Delete, you can select multiple files by long-pressing (Screenshot 6). If you touch "Open" at the top of the screen after selecting, the deletion will be executed.
Recommended Posts