Android. Delete file after it has been shared - android

I use this code to share a zip file (fzip):
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(fzip));
sendIntent.putExtra("myfilename", fzip.getPath());
sendIntent.setType("application/zip");
startActivityForResult(sendIntent, 1);
After the file is shared (copied, added to Dropbox, ...) I want to delete the original zip file because it is no longer useful.
I try to use this:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// Check which request we're responding to
if (requestCode == 1) {
String myname=data.getStringExtra("myfilename");
Toast.makeText(getApplicationContext(), "created file:" + myname , Toast.LENGTH_SHORT).show();
}
}
so that after I get the file name, and since the file has been shared, I could delete it.
The zip file is copied as it should. but the app crashes. What should I do?

First, ACTION_SEND is not used with startActivityForResult(), as it does not return a result.
Second, your extra is not on the Intent passed into onActivityResult(), because those are separate Intent objects.
Third, just because control returned to you does not mean that the other application is done with your file yet. You have no good way to know when the other app is done with the file. I would recommend waiting 24 hours and deleting it then.

Related

Android open the directory of a uri obtained through ACTION_CREATE_DOCUMENT

I am using Android ACTION_CREATE_DOCUMENT to select a location to save a PDF file.
After getting the uri and writing to the file (as done in the code below), I want to show a Snackbar with the action set to opening the location of the file.
To be clear I don't want to open the file itself, but to help user locate the file using the file explorer app. Is there a "developer.android.com" recommended way to do this? The current code is as follows.
private void getSaveLocation() {
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("application/pdf");
intent.putExtra(Intent.EXTRA_TITLE, "MyFile.pdf");
startActivityForResult(intent, MY_CODE);
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != Activity.RESULT_OK || data == null || data.getData() == null) return;
Uri uri = data.getData();
OutputStream out = getContext().getContentResolver().openOutputStream(uri);
// write the pdf to out
try {
out.close();
showSnackbar(uri);
} catch (IOException e) {
e.printStackTrace();
}
}
void showSnackbar(Uri uri) {
Snackbar snackbar = Snackbar.make(getView(), "Saved to MyFile.pdf", Snackbar.LENGTH_LONG);
snackbar.setAction("Locate file", new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
// NEED TO SETUP THE INTENT CORRECTLY USING uri
activity.startActivity(intent);
}
});
snackbar.show();
}
Is there a "developer.android.com" recommended way to do this?
No.
First, there is no standard "open a file explorer on a particular location" Intent action.
Second, there is no requirement that ACTION_OPEN_DOCUMENT be used to open a document that is part of something that can be explored. The user can use it to access documents in other things (encrypted containers, cloud storage, etc.) that may not necessarily be accessible by a file manager.
ACTION_CREATE_DOCUMENT gives you an uri for a file and read write permissions for this file if you use the uri.
Even if you would manage to decode an uri for the parent directory you would not be able to use that uri as read and write permissions would lack.

Select pdf from storage dont working in android Oreo [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.

Getting one or more files from onActivityResult Intent, and their filenames?

I am using this code to allow the user to select multiple .csv files from their storage:
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.setType("text/comma-separated-values");
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
startActivityForResult(Intent.createChooser(intent, "Get CSV Files"), REQUEST_IMPORT_CSV);
After choosing the files it goes to onActivityResult() and so far I have done:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQUEST_IMPORT_CSV:
if (data != null) {
ClipData clipData = data.getClipData();
ArrayList<Uri> csvUris = new ArrayList<>();
if (clipData != null) {
for (int i = 0; i < clipData.getItemCount(); i++) {
clipData.getItemAt(i).getText()
csvUris.add(clipData.getItemAt(i).getUri());
}
}
else {
csvUris.add(data.getData());
}
}
break;
}
}
Is this the right way to get all the relevant Uris from the result? If seems like if the user picks one file, I get the Uri from data.getData(), and if the user picked multiple files, then it goes straight to this clipData() thing instead.
Assuming (1) is correct, how do I get the filenames of the corresponding files that the user chose? For example "chosen_file.csv" (I am not asking for the path).
Is this the right way to get all the relevant Uris from the result?
AFAIK, yes. Leastways, it has worked for me.
how do I get the filenames of the corresponding files that the user chose?
Strictly speaking, you don't. There is no requirement for the Uri to point to a file, any more than the URL to this Web page has to point to a file.
What you can do is wrap the Uri in a DocumentFile, via fromSingleUri(). Then, call getName() on the DocumentFile to get a "display name" for the content. Depending on where the user got the content from, this may be a filename-like value. It is supposed to be something user-recognizable. However, do not assume that it is a filename, as it could be something else.

Browse path on SD card via Intent

I'd like to know if there's a way to open a file browser (system or 3rd party like Astro) to a specific path. There's not much else to say here... pretty straight-forward question.
Sounds like ACTION_GET_CONTENT is what you want. See here. The relevant bits would be:
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("file/*");
startActivityForResult(intent,PICKFILE_RESULT_CODE);
On my phone (which has astro already installed), this brings up an astro dialog for /sdcard. I'm not sure what this will do on a phone with no file browser installed. I'm also unsure about whether you are able to actually specify the starting path using this method. The docs make it sound like you can't specify a starting uri for ACTION_GET_CONTENT.
EDIT: I think I understand the question better now. I thought you were wanting a picker style browser to just get a file path from the user. If you want a full blown browser to handle your uri, then this worked for me:
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse("file:///mnt/sdcard/Music"), "*/*");
startActivity(intent);
That will probably give you quite a long list of possible handlers, but I'd bet any file manager on the system would be in the list (astro certainly is).
I don't believe that any of the manufacturer provided File Browsers provide such a thing.
Though I don't see anything glaringly wrong with the theory of doing so. I imagine you are more likely to find a 3rd party file browser with this feature, but I've never come across any of those either.
You might look in to the Open Intents OI File Manager this concept seems right up their ally, if they don't already have this feature, I bet they might consider adding it if you get in contact with them.
Here i am going to show you that how to create a BROWSE button, which when you will click, it will open up the SDCARD, you will select a File and in result you will get the File Name and File path of the selected one:
// A button which you will hit**
browse.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
Intent intent = new Intent();
intent.setAction(Intent.ACTION_PICK);
Uri startDir = Uri.fromFile(new File("/sdcard"));
startActivityForResult(intent, PICK_REQUEST_CODE);
}
});
//The function which will get the Resulted File Name and File Path
protected void onActivityResult(int requestCode, int resultCode, Intent intent)
{
if (requestCode == PICK_REQUEST_CODE)
{
if (resultCode == RESULT_OK)
{
Uri uri = intent.getData();
if (uri.getScheme().toString().compareTo("content")==0)
{
Cursor cursor =getContentResolver().query(uri, null, null, null, null);
if (cursor.moveToFirst())
{
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);//Instead of "MediaStore.Images.Media.DATA" can be used "_data"
Uri filePathUri = Uri.parse(cursor.getString(column_index));
String file_name = filePathUri.getLastPathSegment().toString();
String file_path=filePathUri.getPath();
Toast.makeText(this,"File Name & PATH are:"+file_name+"\n"+file_path, Toast.LENGTH_LONG).show();
}
}
}
}
}

Pick any kind of file via an Intent in Android

I would like to start an intentchooser for apps which can return any kind of file
Currently I use (which I copied from the Android email source code for file attachment)
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
Intent i = Intent.createChooser(intent, "File");
startActivityForResult(i, CHOOSE_FILE_REQUESTCODE);
But it only shows "Gallery" and "Music player" on my Galaxy S2. There is a file explorer on this device and I would like it to appear in the list. I would also like the camera app to show in the list, so that the user can shoot a picture and send it through my app.
If I install Astro file manager it will respond to that intent, too. My customers are Galaxy SII owners only and I don't want to force them to install Astro file manager given that they already have a basic but sufficient file manager.
Any idea of how I could achieve this ? I am pretty sure that I already saw the default file manager appear in such a menu to pick a file, but I can't remember in which app.
Not for camera but for other files..
In my device I have ES File Explorer installed and This simply thing works in my case..
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("file/*");
startActivityForResult(intent, PICKFILE_REQUEST_CODE);
Samsung file explorer needs not only custom action (com.sec.android.app.myfiles.PICK_DATA),
but also category part (Intent.CATEGORY_DEFAULT) and mime-type should be passed as extra.
Intent intent = new Intent("com.sec.android.app.myfiles.PICK_DATA");
intent.putExtra("CONTENT_TYPE", "*/*");
intent.addCategory(Intent.CATEGORY_DEFAULT);
You can also use this action for opening multiple files: com.sec.android.app.myfiles.PICK_DATA_MULTIPLE
Anyway here is my solution which works on Samsung and other devices:
public void openFile(String mimeType) {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType(mimeType);
intent.addCategory(Intent.CATEGORY_OPENABLE);
// special intent for Samsung file manager
Intent sIntent = new Intent("com.sec.android.app.myfiles.PICK_DATA");
// if you want any file type, you can skip next line
sIntent.putExtra("CONTENT_TYPE", mimeType);
sIntent.addCategory(Intent.CATEGORY_DEFAULT);
Intent chooserIntent;
if (getPackageManager().resolveActivity(sIntent, 0) != null){
// it is device with Samsung file manager
chooserIntent = Intent.createChooser(sIntent, "Open file");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] { intent});
} else {
chooserIntent = Intent.createChooser(intent, "Open file");
}
try {
startActivityForResult(chooserIntent, CHOOSE_FILE_REQUESTCODE);
} catch (android.content.ActivityNotFoundException ex) {
Toast.makeText(getApplicationContext(), "No suitable File Manager was found.", Toast.LENGTH_SHORT).show();
}
}
This solution works well for me, and maybe will be useful for someone else.
this work for me on galaxy note
its show
contacts,
file managers installed on device,
gallery,
music player
private void openFile(Int CODE) {
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.setType("*/*");
startActivityForResult(intent, CODE);
}
here get path in onActivityResult of activity.
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
String Fpath = data.getDataString();
// do somthing...
super.onActivityResult(requestCode, resultCode, data);
}
This gives me the best result:
Intent intent;
if (android.os.Build.MANUFACTURER.equalsIgnoreCase("samsung")) {
intent = new Intent("com.sec.android.app.myfiles.PICK_DATA");
intent.putExtra("CONTENT_TYPE", "*/*");
intent.addCategory(Intent.CATEGORY_DEFAULT);
} else {
String[] mimeTypes =
{"application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", // .doc & .docx
"application/vnd.ms-powerpoint", "application/vnd.openxmlformats-officedocument.presentationml.presentation", // .ppt & .pptx
"application/vnd.ms-excel", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", // .xls & .xlsx
"text/plain",
"application/pdf",
"application/zip", "application/vnd.android.package-archive"};
intent = new Intent(Intent.ACTION_GET_CONTENT); // or ACTION_OPEN_DOCUMENT
intent.setType("*/*");
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
}
Turns out the Samsung file explorer uses a custom action. This is why I could see the Samsung file explorer when looking for a file from the samsung apps, but not from mine.
The action is "com.sec.android.app.myfiles.PICK_DATA"
I created a custom Activity Picker which displays activities filtering both intents.
If you want to know this, it exists an open source library called aFileDialog that it is an small and easy to use which provides a file picker.
The difference with another file chooser's libraries for Android is that aFileDialog gives you the option to open the file chooser as a Dialog and as an Activity.
It also lets you to select folders, create files, filter files using regular expressions and show confirmation dialogs.
The other answers are not incorrect. However, now there are more options for opening files. For example, if you want the app to have long term, permanent acess to a file, you can use ACTION_OPEN_DOCUMENT instead. Refer to the official documentation: Open files using storage access framework. Also refer to this answer.

Categories

Resources