I have read so many theories about saving a file to the internal storage and external storage that I don't know exactly any more what to do.
I created a PDF file with droidtext that I want to e-mail as an attachment in the chosen e-mail app.
This is no problem. I succeeded in this, however... I only can do it with the external storage.
So, I create a PDF, put it in the external storage with Environment.getExternalStorageDirectory().getAbsolutePath().
However, if no external storage is available I want to save the PDF on the internal storage.
I did it like this so far:
External (working perfectly):
pdf = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + java.io.File.separator + fileName);
PdfWriter.getInstance(document, new FileOutputStream(pdf));
Internal storage:
pdf = new File(fileName);
PdfWriter.getInstance(document, openFileOutput(fileName, MODE_PRIVATE));
With both having Document document = new Document();.
The Internal memory method delivers no error whatsoever, but I am not sure if the file is saved internally.
Also, I think that because it is saved internally, the mail app will not be able to select it as an attachment.
I can't test this because my emulator has no mail app. Nor can I go through the content on the device. Nor do I own a device that has no external storage...
What is the best way to solve this? Force users to have external storage or are there other ways to solve this?
"What is the best way to solve this? Force users to have external storage or are there other ways to solve this?"...I'm not certain, but I think you have no choice but to force users to have external storage to be able to email an attachment.
You can't use MODE_PRIVATE to save to internal storage or the email app won't be able to access the file. You'll have to use MODE_WORLD_READABLE.
To get the directory of where the file is stored use Context.getFilesDir() (http://developer.android.com/reference/android/content/Context.html#getFilesDir%28%29)
You can also just install an email app on the emulator to test this. Just download an apk and install it via adb.
Related
I have created an android app that gets input from user through EditText and writes them to name.txt file in phone's internal storage. Is it possible to open the text file in phone's file manager? I tried to get the file path using getFilesDir().getAbsolutePath()+"/"+FILE_NAME. But couldn't locate the file in file manager.
You need to use External storage if you want another app like File Manager to access the file. Internal storage is only readable by your app.
In the comments you ask a valid question - "What if the phone doesnt have external storage...?". That is not really a concern today. See https://developer.android.com/training/data-storage/files:
Many devices now divide the permanent storage space into separate
"internal" and "external" partitions. So even without a removable
storage medium, these two storage spaces always exist...
==========
So change your above code to this:
getExternalFilesDir().getAbsolutePath()+"/"+FILE_NAME
getExternalFilesDir is a method from the android.content.Context class. So this call will work from your activity class which is a Context.
=============
Further supporting the choice of external storage is the following, also from https://developer.android.com/training/data-storage/files.
Internal storage is best when you want to be sure that neither the
user nor other apps can access your files.
External storage is the best place for files that don't require access
restrictions and for files that you want to share with other apps or
allow the user to access with a computer.
there is private storage for each app that can be accessed from the app itself and then public storage /sdcard/... that other app can access too (it needs to get Storage Permission from system)
this method will save a content in a file in private storage of app
public void saveFile(String fileName, String content) {
try {
FileOutputStream fOut = context.openFileOutput(fileName, Context.MODE_PRIVATE);
fOut.write((content).getBytes());
fOut.flush();
fOut.close();
} catch (Exception e) {
e.printStackTrace();
}
}
From here I know a way to write a file and be accessible to other app and other intent, but now that the Context.MODE_WORLD_READABLE is deprecated how can I safely accomplish this?
FileOutputStream out = myActivity.openFileOutput(fileTo, Context.MODE_WORLD_READABLE);
Okay more info:
I'm using this:
intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(uri, "video/*");
And the uri will be the one that I will write to a sdcard location. And the video will come from the application so problem is, if this is now not allowed, how can I write the file and view it.
And the uri will be the one that I will write to a sdcard location.
That is already MODE_WORLD_WRITABLE by default. Also note that the code you have listed (openFileOutput()) does not write to external storage (what you incorrectly call "sdcard"). openFileOutput() is for internal storage.
And the video will come from the application so problem is, if this is now not allowed, how can I write the file and view it.
If you are really writing the file to external storage, just use a Uri pointing to that file.
If you are writing the file to internal storage, create a ContentProvider to serve that file, and use a Uri pointing to that ContentProvider. Here is a sample application with a ContentProvider that extracts a PDF file from assets/ on first run, then serves up that file via openFile() so it can be viewed by a PDF viewer.
Save your video in your internal memory using:
openFileOutput("test.mp4", "MODE_PRIVATE");
Then do this:
String path = context.getFilesDir().getAbsolutePath() + "/test.mp4"; // path to the root of internal memory.
File f = new File(path);
f.setReadable(true, false);
Intent playIntent ....
playIntent.setType("video/*");
playIntent.setData(Uri.fromFile(f));
Good Luck.
It seems to look like the docs are clear about it.
This constant was deprecated in API level 17.
Creating world-readable files is very dangerous, and likely to cause
security holes in applications. It is strongly discouraged; instead,
applications should use more formal mechanism for interactions such as
ContentProvider, BroadcastReceiver, and Service. There are no
guarantees that this access mode will remain on a file, such as when
it goes through a backup and restore. File creation mode: allow all
other applications to have read access to the created file.
I want to save a file and then fire an intent to an other application to open that file. How do I accomplish this?
If tried : openFileOutput("file.pdf", Context.MODE_WORLD_READABLE) but doesn't seem to work. Should I save the file outside the applications folder? If so how do I pass it the correct permissions?
You can use something like this:
String extPath = Environment.getExternalStorageDirectory().getAbsolutePath();
String pathPrefix = extPath + "/Android/data/" + APP_PACKAGE_ID + "/cache/";
to save the file to sd card, which is accessible by all other applications. the Mode Context.MODE_WORLD_READABLE is sufficient for this. The code is for use with android 2.1 and uses the suggested path for storing app related data on the sd card. Starting with Android 2.2 this directory automatically gets deleted if the app is uninstalled.
Your app needs the right to install to sd card:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Using openFileOutput(...) with world readable rights is a bit useless as this files are stored into a folder only accessible by the application itself.
More information is described in the data storage documentation.
Please note that the external memory may be unavailable if the user has connected the device via USB for file storage access. You should always check for this conditions first via String state = Environment.getExternalStorageState();.
i have to make an application in which first i have to create a text file from the data user has entered in the UI and then send the text file as an attachment in an email. For this i will have to write data to the external directory and then pass the URI to the Intent so that the email client in the phone can read it.
i am not sure how would i:
write data to the external storage.
2.Pass the URI of the file created to the Intent so that i can attach it to the email.
I have seen several examples of how to send email attachments.. but none fit my requirements hence as a last resort i am posting this question.
thank you in advance.
Both questions have been answered here many times.
External storage:
How can i Use External Storage in android
How should I refer to "external storage" in the UI on Android?
Attach a file to an email:
Trying to attach a file from SD Card to email
Android:Attach file with email from device memory
I honestly cannot figure out what is so specific about your requirements. It looks like a pretty standard task to me...
I am creating a file into Internal storage (/data/data/package_name/myfile_name), I want to send that file with attachment but I am getting a blank file in attachment(although I checked that file from file explorer, that file is present and not empty at same location).
And same code running well when I used external storage( I am getting my actual file in attachment). Is there any restrictions that we can not send file which are present in internal storage? Or other steps I am missing?
I'm assuming you are trying to send the file as an email attachment using intents.
The reason why the file is empty is that the email app does not have access to the file in /data/data/package_name/myfile_name, due to Androids security model (the /data/data/package_name directory is private to your app).
In order to add the file as an attachment, you need to write it to public storage (such as the SD card) so the email app can access it.
How do you know the file exists at the path you're interested in? Can you view it with DDMS or ADB after your application saved it there? What code are you using to save/read the file? I may be able to provide more specific assistance with that information.
The method used to obtain the internal storage directory on any given device is Context.getFilesDir(). To create a reference to a file named "myfile.dat", for instance:
File myFile = new File(getFilesDir(),"myfile.dat");
Assuming you call the code from inside an Activity or other Context. In order to attach this file to an email, you would be passing a Uri to that location as an extra, so let's add the creation of that to the example:
File myFile = new File(getFilesDir(),"myfile.dat");
Uri fileUri = Uri.fromFile(myFile);
This is all assuming the file was properly saved into Internal Storage in the first place.
Hope that Helps!