Create/copy File In Android Q Using Mediastore
Solution 1:
1. Create and Write File
createAndWriteButton.setOnClickListener(newView.OnClickListener() {
@OverridepublicvoidonClick(View view) {
try {
ContentValuesvalues=newContentValues();
values.put(MediaStore.MediaColumns.DISPLAY_NAME, "menuCategory"); //file name
values.put(MediaStore.MediaColumns.MIME_TYPE, "text/plain"); //file extension, will automatically add to file
values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOCUMENTS + "/Kamen Rider Decade/"); //end "/" is not mandatoryUriuri= getContentResolver().insert(MediaStore.Files.getContentUri("external"), values); //important!OutputStreamoutputStream= getContentResolver().openOutputStream(uri);
outputStream.write("This is menu category data.".getBytes());
outputStream.close();
Toast.makeText(view.getContext(), "File created successfully", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
Toast.makeText(view.getContext(), "Fail to create file", Toast.LENGTH_SHORT).show();
}
}
});
2. Find and Read File
findAndReadButton.setOnClickListener(newView.OnClickListener() {
@OverridepublicvoidonClick(View view) {
UricontentUri= MediaStore.Files.getContentUri("external");
Stringselection= MediaStore.MediaColumns.RELATIVE_PATH + "=?";
String[] selectionArgs = newString[]{Environment.DIRECTORY_DOCUMENTS + "/Kamen Rider Decade/"};
Cursorcursor= getContentResolver().query(contentUri, null, selection, selectionArgs, null);
Uriuri=null;
if (cursor.getCount() == 0) {
Toast.makeText(view.getContext(), "No file found in \"" + Environment.DIRECTORY_DOCUMENTS + "/Kamen Rider Decade/\"", Toast.LENGTH_LONG).show();
} else {
while (cursor.moveToNext()) {
StringfileName= cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME));
if (fileName.equals("menuCategory.txt")) {
longid= cursor.getLong(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
uri = ContentUris.withAppendedId(contentUri, id);
break;
}
}
if (uri == null) {
Toast.makeText(view.getContext(), "\"menuCategory.txt\" not found", Toast.LENGTH_SHORT).show();
} else {
try {
InputStreaminputStream= getContentResolver().openInputStream(uri);
intsize= inputStream.available();
byte[] bytes = newbyte[size];
inputStream.read(bytes);
inputStream.close();
StringjsonString=newString(bytes, StandardCharsets.UTF_8);
AlertDialog.Builderbuilder=newAlertDialog.Builder(view.getContext());
builder.setTitle("File Content");
builder.setMessage(jsonString);
builder.setPositiveButton("OK", null);
builder.create().show();
} catch (IOException e) {
Toast.makeText(view.getContext(), "Fail to read file", Toast.LENGTH_SHORT).show();
}
}
}
}
});
3. Find and Overwrite File
findAndWriteButton.setOnClickListener(newView.OnClickListener() {
@OverridepublicvoidonClick(View view) {
UricontentUri= MediaStore.Files.getContentUri("external");
Stringselection= MediaStore.MediaColumns.RELATIVE_PATH + "=?";
String[] selectionArgs = newString[]{Environment.DIRECTORY_DOCUMENTS + "/Kamen Rider Decade/"}; //must include "/" in front and endCursorcursor= getContentResolver().query(contentUri, null, selection, selectionArgs, null);
Uriuri=null;
if (cursor.getCount() == 0) {
Toast.makeText(view.getContext(), "No file found in \"" + Environment.DIRECTORY_DOCUMENTS + "/Kamen Rider Decade/\"", Toast.LENGTH_LONG).show();
} else {
while (cursor.moveToNext()) {
StringfileName= cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME));
if (fileName.equals("menuCategory.txt")) { //must include extensionlongid= cursor.getLong(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
uri = ContentUris.withAppendedId(contentUri, id);
break;
}
}
if (uri == null) {
Toast.makeText(view.getContext(), "\"menuCategory.txt\" not found", Toast.LENGTH_SHORT).show();
} else {
try {
OutputStreamoutputStream= getContentResolver().openOutputStream(uri, "rwt"); //overwrite mode, see below
outputStream.write("This is overwritten data。\n你就不要想起我。".getBytes());
outputStream.close();
Toast.makeText(view.getContext(), "File written successfully", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
Toast.makeText(view.getContext(), "Fail to write file", Toast.LENGTH_SHORT).show();
}
}
}
}
});
- Read/Write mode: https://developer.android.com/training/data-storage/shared/media#open-file-descriptor
Demo: https://www.youtube.com/watch?v=idsUMiWjfnM
Hope this may help you.
Solution 2:
As you mentioned Environment.getExternalStoragePublicDirectory
is marked deprecated. So there is no regular way to get the path to Downloads directory to save your file there. Alternatively you can use ACTION_CREATE_DOCUMENT
to show path picker and then use returned uri to write file to selected location.
This is how to show picker:
// Request code for creating a document.constval CREATE_FILE = 1privatefuncreateFile(pickerInitialUri: Uri) {
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "text/plain"
putExtra(Intent.EXTRA_TITLE, "sam.txt")
// Optionally, specify a URI for the directory that should be opened in// the system file picker before your app creates the document.
putExtra(DocumentsContract.EXTRA_INITIAL_URI, pickerInitialUri)
}
startActivityForResult(intent, CREATE_FILE)
}
And this is how to get selected uri and write file:
overridefunonActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
if (requestCode == CREATE_FILE && resultCode == Activity.RESULT_OK) {
// The result data contains a URI for the document or directory that// the user selected.
resultData?.data?.also { outputUri ->
// Perform operations on the document using its URI.
FileInputStream(inputFile).use { inputStream ->
context.contentResolver.openFileDescriptor(outputUri, "w")?.use {
FileOutputStream(it.fileDescriptor).use { outputStream ->
FileUtils.copy(inputStream, outputStream)
}
}
}
}
}
}
More information can be found here.
EDIT:
To pick a directory to persist files ACTION_OPEN_DOCUMENT_TREE
can be used. Then use takePersistableUriPermission
method to take granted persistable permission to be able to use it after device restart. And then use DocumentFile
to execute file operations.
Open directory request:
privatestaticfinalintOPEN_DIRECTORY_REQUEST_CODE=1;
voidopenDirectory() {
Intentintent=newIntent(Intent.ACTION_OPEN_DOCUMENT_TREE);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
startActivityForResult(intent, OPEN_DIRECTORY_REQUEST_CODE);
}
Receive picked directory and take persistable permission:
@OverridepublicvoidonActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == OPEN_DIRECTORY_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
UridirectoryUri= data.getData();
if (directoryUri == null)
return;
requireContext()
.getContentResolver()
.takePersistableUriPermission(directoryUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
// persist picked uri to be able to reuse it later
} elsesuper.onActivityResult(requestCode, resultCode, data);
}
And at last persist the file:
privatevoidpersistFile(@NonNull Uri directoryUri,
@NonNull File fileToPersist,
@NonNull String mimeType,
@NonNull String displayName) {
DocumentFiledirFile= DocumentFile.fromSingleUri(requireContext(), directoryUri);
if (dirFile != null) {
DocumentFilefile= dirFile.createFile(mimeType, displayName);
if (file != null) {
UrioutputUri= file.getUri();
try (ParcelFileDescriptorfd= requireContext().getContentResolver().openFileDescriptor(outputUri, "w")) {
if (fd != null) {
try (FileInputStreaminputStream=newFileInputStream(fileToPersist)) {
try (FileOutputStreamoutputStream=newFileOutputStream(fd.getFileDescriptor())) {
FileUtils.copy(inputStream, outputStream);
}
}
}
} catch (Throwable th) {
th.printStackTrace();
}
}
}
}
Review this repo for an example of ACTION_CREATE_DOCUMENT
usage.
Post a Comment for "Create/copy File In Android Q Using Mediastore"