How create directory using URI (Android)? - java

In my application i want to create subdirectories in choosen directory. Im using SAF (Storage Access Framework): choose directory and create one subdirectory works fine.
Choose directory:
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, REQUEST_CODE_PATH_TO_DATA);
Create subdirectory:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != Activity.RESULT_OK) {
return;
}
if (requestCode == REQUEST_CODE_PATH_TO_DATA) {
if (data == null) {
return;
}
DocumentFile pickedDir = DocumentFile.fromTreeUri(getActivity(), data.getData());
getActivity().grantUriPermission(getActivity().getPackageName(), data.getData(), Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
getActivity().getContentResolver().takePersistableUriPermission(data.getData(), Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
pickedDir.createDirectory("Portfolio");
String pathToPickedDir = "";
for (DocumentFile file : pickedDir.listFiles()) {
if (file.isDirectory() && file.getName().endsWith("Portfolio")) {
pathToPickedDir = file.getUri().toString();
}
}
}
}
URI from pickedDir is:
content://com.android.externalstorage.documents/tree/314E-7741%3ADCIM
And URI from created subdirectory "Portfolio" is:
content://com.android.externalstorage.documents/tree/314E-7741%3ADCIM/document/314E-7741%3ADCIM%2FPortfolio
And then when im trying to create subdirectory in "Portfolio" i can't do that, because the directory is created in the folder that was initially selected, not in the "Portfolio" folder.
DocumentFile pickedDir = DocumentFile.fromTreeUri(getActivity(), pathToPickedDir);
pickedDir.createDirectory("Patient");
What am I doing wrong? Thank you for your help.

Only way that i found is using "for" cycle:
for (DocumentFile file : pickedDir.listFiles()) {
if (file.isDirectory() && file.getName().equals("Portfolio")) {
file.createDirectory("Subdirectory");
}
}

The following should work in your case:
DocumentFile portfolioDir = pickedDir.createDirectory("Portfolio");
portfolioDir.createDirectory("Patient");
In your code, you are not using the directory object returned by DocumentFile.createDirectory(), which is the object of the newly created directory, in which you want to create a sub-directory.

Related

How to get full path from Intent.ACTION_GET_CONTENT?

I am trying to put selected files(not exclusive to images, it can be any file) from file chooser intent to a zip file. I need full file path to do this, but intent only gives uri paths.
I have tried .getPath() but that does not give the real path of the file
I have tried getRealPathFromRealURI: android get real path by Uri.getPath()
I have tried File file = new File(), file.getPath()
This is my code:
public void onActivityResult(int requestCode, int resultCode, Intent result){
if(requestCode == 111) {
if(null != result) { // checking empty selection
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
if(null != result.getClipData()) { // checking multiple selection or not
for(int i = 0; i < result.getClipData().getItemCount(); i++) {
String uri = result.getClipData().getItemAt(i).getUri().getPath();
uriList.add(uri);
Log.d("PATH: ",uri);
}
confirmationDialog();
} else {
String uri = result.getData().getPath();
uriList.add(uri);
Log.d("PATH: ",uri);
confirmationDialog();
}
}else{Toast.makeText(getApplicationContext(),
"An error has occured: API level requirements not met",Toast.LENGTH_SHORT).show();};
}
}
}
It should give the real path for example: "/sdcard/filename.example"
Instead, it gives me: "/document/9016-4ef8:filename.example"
Uri selectedImage = data.getData();
String[] filePathColumn = { MediaStore.Images.Media.DATA };
Cursor cursor = getContentResolver().query(selectedImage,filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String picturePath = cursor.getString(columnIndex);
cursor.close();
System.out.println("picturePath +"+ picturePath ); //path of sdcard
Found here: Get Real Path For Uri Android
Pick / Get the file's actual path:
val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.type = "*/*"
startActivityForResult(intent, 1)
onActivityResult:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 1 && resultCode == Activity.RESULT_OK) {
val file = data?.data?.let {
getFileFromUri(requireContext().contentResolver, uri, requireContext().cacheDir)
}
}
}
Get File:
private fun getFileFromUri(contentResolver: ContentResolver, uri: Uri, directory: File): File {
val file =
File.createTempFile("suffix", ".prefix", directory)
file.outputStream().use {
contentResolver.openInputStream(uri)?.copyTo(it)
}
return file
}
Once we get the file, We can get the actual path of the file.
Okay, I fixed it by using another file explorer aside from the built-in file explorer, in my case I used Cx File Explorer, different file explorers return different values.

Get real path of a file from URI? [duplicate]

I am trying to fetch a file this way:
final Intent chooseFileIntent = new Intent(Intent.ACTION_GET_CONTENT);
String[] mimetypes = {"application/pdf"};
chooseFileIntent.setType("*/*");
chooseFileIntent.addCategory(Intent.CATEGORY_OPENABLE);
if (chooseFileIntent.resolveActivity(activity
.getApplicationContext().getPackageManager()) != null) {
chooseFileIntent.putExtra(Intent.EXTRA_MIME_TYPES, mimetypes);
activity.startActivityForResult(chooseFileIntent, Uploader.PDF);
}
Then in onActivityResult :
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
According to many threads I'm supposed to fetch the file name from the intent with data.getData().getPath(), the file name I'm expecting is my_file.pdf, but instead I'm getting this :
/document/acc=1;doc=28
So what to do? Thanks for your help.
I am trying to fetch a file
Not with that code. That code is asking the user to pick a piece of content. This may or may not be a file.
According to many threads I'm supposed to fetch the file name from the intent with data.getData().getPath()
That was never correct, though it tended to work on older versions of Android.
So what to do?
Well, that depends.
If you wish to only accept files, integrate a file chooser library instead of using ACTION_GET_CONTENT. (UPDATE 2019-04-06: since Android Q is banning most filesystem access, this solution is no longer practical)
If you are willing to allow the user to pick a piece of content using ACTION_GET_CONTENT, please understand that it does not have to be a file and it does not have to have something that resembles a filename. The closest that you will get:
If getScheme() of the Uri returns file, your original algorithm will work
If getScheme() of the Uri returns content, use DocumentFile.fromSingleUri() to create a DocumentFile, then call getName() on that DocumentFile — this should return a "display name" which should be recognizable to the user
To get the real name and to avoid getting a name that looks like "image: 4431" or even just a number, you can write code as recommended by CommonsWare.
The following is an example of a code that selects a single pdf file, prints its name and path to the log, and then sends the file by email using its uri.
private static final int FILEPICKER_RESULT_CODE = 1;
private static final int SEND_EMAIL_RESULT_CODE = 2;
private Uri fileUri;
private void chooseFile() {
Intent fileChooser = new Intent(Intent.ACTION_GET_CONTENT);
fileChooser.setType("application/pdf");
startActivityForResult(Intent.createChooser(fileChooser, "Choose one pdf file"), FILEPICKER_RESULT_CODE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == FILEPICKER_RESULT_CODE) {
if (resultCode == RESULT_OK) {
fileUri = data != null ? data.getData() : null;
if (fileUri != null) {
DocumentFile d = DocumentFile.fromSingleUri(this, fileUri);
if (d != null) {
Log.d("TAG", "file name: " + d.getName());
Log.d("TAG", "file path: " + d.getUri().getPath());
sendEmail(fileUri);
}
}
}
}
}
private void sendEmail(Uri path) {
String email = "example#gmail.com";
Intent intent = new Intent(android.content.Intent.ACTION_SEND);
intent.setType("application/octet-stream");
intent.putExtra(android.content.Intent.EXTRA_SUBJECT, "PDF file");
String[] to = { email };
intent.putExtra(Intent.EXTRA_EMAIL, to);
intent.putExtra(Intent.EXTRA_TEXT, "This is the pdf file...");
intent.putExtra(Intent.EXTRA_STREAM, path);
startActivityForResult(Intent.createChooser(intent, "Send mail..."), SEND_EMAIL_RESULT_CODE);
}
hope it helps.

can we copy and move images to another folder using startactivityforresult

I am a newbie in android app development. I have a simple question. I googled about it but couldn't find any satisfactory answer. My question is :
Can we copy and move images to another folder using startactivityforresult() method. If yes, then how can we pass the position of the selected images we want to move or copy ?
Thanks
In your main activity:
Create new ArrayList to hold selected images:
ArrayList<Model_images> selectedImages = new ArrayList<Model_Images>();
Add all selected images to selectedImages in your adapter's
onClick using:
selectedImages.add(al_images.get(position));
Then once you have the list of selected images, Build the intent and
call the activity:
Intent moveIntent = new Intent(this, MoveActivity.class);
moveIntent.putExtra("selected_images", selectedImages);
startActivityForResult(moveIntent, REQUEST_CODE); // REQUEST_CODE is a unique int value within your app for this intent.
Override onActivityResult to receive the response:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// check if the request code is same as what is passed(REQUEST_CODE)
if(requestCode==REQUEST_CODE)
{
if (resultCode == RESULT_OK){
//The called activity completed successfully.
String message=data.getStringExtra("MESSAGE"); //The message passed along with result
}
}
}
In your MoveActivity activity:
Get the passed ArrayList:
ArrayList<model_Images> selectedImages = new ArrayList<Model_Images>();
if(getIntent().getSerializableExtra("selected_images") != null)
selectedImages = getIntent().getSerializableExtra("selected_images");
Move the images to destination folder:
//Move each selected file to destination
for (Model_Images image : selectedImages{
File sourceImage = image.getFile(); //returns the image File from model class to be moved.
File destinationImage = new File("path/to/destination", "filename.extension");
moveFile(sourceImage, destinationImage);
}
//Method to move the file
private void moveFile(File sourceFile, File destFile) throws IOException {
if (!sourceFile.exists()) {
return;
}
FileChannel source = null;
FileChannel destination = null;
source = new FileInputStream(sourceFile).getChannel();
destination = new FileOutputStream(destFile).getChannel();
if (destination != null && source != null) {
destination.transferFrom(source, 0, source.size());
}
if (source != null) {
source.close();
}
if (destination != null) {
destination.close();
}
source.delete();
}
Set the result to calling activity once done:
// Set result back to the calling activity
Intent intent=new Intent();
intent.putExtra("MESSAGE",message); // Set a message for the calling activity
setResult(RESULT_OK,intent); //RESULT_OK represents success result
finish();//finishing activity
P.S: handling storage permission is not discussed and is required to read/write.

File path is empty for google drive files

I am developing a file uploading android application. My objective is to upload the user selected file from file manager to a remote server. But when a google drive file is selected , file uploading fails because of empty path . Can somebody help me ?
My code is :
private void showFileChooser() {
Intent intent = new Intent();
intent.setType("*/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
startActivityForResult(Intent.createChooser(intent, "Choose File to Upload.."), PICK_FILE_REQUEST);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
if (requestCode == PICK_FILE_REQUEST) {
if (data == null) {
//no data present
return;
}
Uri selectedFileUri = data.getData();
selectedFilePath = FilePath.getPath(mActivity, selectedFileUri);
if (selectedFilePath != null && !selectedFilePath.equals("")) {
callUploadDocumentAPI();
} else {
Toast.makeText(mActivity, StringConstants.CANT_UPLOAD_TO_SERVER, Toast.LENGTH_SHORT).show();
}
}
}
But when a google drive file is selected , file uploading fails because of empty path .
FilePath.getPath(mActivity, selectedFileUri) cannot work. A Uri is not a file.
Use a ContentResolver and openInputStream() to get an InputStream on the content identified by the Uri. Either use that InputStream directly, or use it to make your own copy of the content in some file that you control, then use that copy.

Copy file from the directory to another , having the path's of file and directory

in my android application I want to copy file from one directory to another , I have the path of file filePath , and have the path of directory dirPath in what I must copy the file. I tried many ways , but nothing helped , some ways only make some empty(0 kb) file with strange name different from the name of my file. SO help please :)
here is some part of code, if it help's you, I have two buttons for Gallery and for Camera , and I must pick images from there
Button btnCam = (Button) dialog.findViewById(R.id.btncamera);
btnCam.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
dialog.cancel();
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, 2500);
}
});
//end of camera button
Button btnGal = (Button) dialog.findViewById(R.id.btngalary);
btnGal.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
dialog.cancel();
Intent i = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(i, RESULT_LOAD_IMAGE);
}
});
and Activity Result
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RESULT_LOAD_IMAGE && resultCode == RESULT_OK && null != data)
{
Uri selectedImage = data.getData();
url = new String(selectedImage.toString());
//here I must copy file with path `selectedImage` and replace it in
// directory with path `currentDir.hetPath()`
}
if (requestCode == 2500)
{
Bitmap photo = (Bitmap) data.getExtras().get("data");
imageView.setImageBitmap(photo);
//here I must do the same thing above
}
}
I found some way , in my Activity result I must call copyFile(String, String) function , here is the body
public static boolean copyFile(String from, String to) {
try {
File sd = Environment.getExternalStorageDirectory();
if (sd.canWrite()) {
int end = from.toString().lastIndexOf("/");
String str1 = from.toString().substring(0, end);
String str2 = from.toString().substring(end+1, from.length());
File source = new File(str1, str2);
File destination= new File(to, str2);
if (source.exists()) {
FileChannel src = new FileInputStream(source).getChannel();
FileChannel dst = new FileOutputStream(destination).getChannel();
dst.transferFrom(src, 0, src.size());
src.close();
dst.close();
}
}
return true;
} catch (Exception e) {
return false;
}
}
If you feel up to it, you can include Apache Commons I/O in your app. I don't know how big it is. See Standard concise way to copy a file in Java?
Or maybe you could download the source, and cherry-pick the source to FileUtils.copyFile()

Categories