What is the best way to create temporary files on Android? - java

Well, this is not exactly a question, as I'm not really "stuck" on my code, but I've found some strange behavior for Android API regarding accessing the external storage and the File.createTempFile() method, and I'd like to understand what's happening...
Please note that my manifest does not include the <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE">.
Part 1 :
I have the following code which does work as a charm :
File tempFile = new File(Environment.getExternalStorageDirectory(),
"my_temp_file.png");
it creates a temporary file for me, and I can write datas in it without any trouble.
Question 1 : Why does it work, as I'm not supposed to have writing rights on my SDCard ?
Part 2 :
I've tried to change my code to use the createTempFile which is the official method to create temporary file. So I've tried :
File tempFile = File.createTempFile("my_temp", "png",
Environment.getExternalStorageDirectory());
and added the WRITE_EXTERNAL_STORAGE in my manifest.xml. Guess what ? This does not work, and I get a java.io.IOException :
09-07 14:07:29.061: E/_CLOG(19982): java.io.IOException: Permission denied
09-07 14:07:29.061: E/_CLOG(19982): at java.io.File.createNewFileImpl(Native Method)
09-07 14:07:29.061: E/_CLOG(19982): at java.io.File.createNewFile(File.java:1257)
09-07 14:07:29.061: E/_CLOG(19982): at java.io.File.createTempFile(File.java:1322)
09-07 14:07:29.061: E/_CLOG(19982): at com.(...).onClick(ProfileImageUpdater.java:58)
Question 2 : Why this doesn't work, whereas imho it should ?

try like this...
File outputDir = context.getCacheDir(); // context being the Activity pointer
File outputFile = File.createTempFile("prefix", "extension", outputDir);
Edit :
for Question 2
It may be issue as below link...
Environment.getExternalStorageDirectory does not return the path to the removable storage

you're getting this error because you declare on the manifest.xml permission to write to the external storage. you need to add this permission.
also,
do never ever ever ever write files (specially temporary ones) directly on the getExternalStorage().
This will put directly on the SD-card and will create a mess.
For temporary files that is only to be seen by your own application you should use:
getExternalStorage() + "/Android/data/<package_name>/cache/"
replacing by your app packaged, e.g. com. Orabig.myFirstApp
that special folder is automatically deleted from the system if the user uninstall the application, keeping the system free from temporary files.
edit:
Please note that my manifest does not include the
you have to!
edit:
also, if you creating temporary media files (PNG for example) is good practice to create an empty file named .nomedia on that folder. That way you avoid the Media Scanner scanning it and showing it on the gallery.
last edit:
and before creating files you must create the folder by calling mkdirs() on the File object.

I finally figured out what was hapenning...
Question 1 : In fact, the file that was created was meant to be used by the system application to retrieve and crop an image from the user's gallery. So my app didn't have to own the WRITE_EXTERNAL_STORAGE permission, as the file was written by the system itself.
Question 2 : I'm not sure. I guess that the Android do not allow to create a temporary file where I was trying to (as it's not the right place for it)

Related

Is it possible to access a document created using the intent with its path?

While working to upgrade to API 33 from API 28 I can no longer access the files that I have created with ACTION_CREATE_DOCUMENT intent without using its URI.
I have tried making sure to ensure READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE permissions were taken before attempting to access the file. I manage to create the file but when creating its path and trying to access it at that path the app suddenly fails to open it even though it should be the owner of that file if I'm not wrong?
I absolutely cannot use MANAGE_EXTERNAL_STORAGE permission because that doesn't fit the usecase that I have.
Is there a way to use the path instead of the URI returned to write to the file? the file extension is csv.
I have created a sample to write and read the file.
Create the File:
Intent intent = new Intent(Intent.ActionCreateDocument);
intent.AddCategory(Intent.CategoryOpenable);
intent.SetType("application/txt");
intent.PutExtra(Intent.ExtraTitle, "anew.txt");
StartActivity(intent);
Then I saved the file into the Download Folder by the system file manager and write the file.
File.WriteAllText("/storage/emulated/0/Download/anew.txt", "this is file content");
Every thing worked well after I granted the storage permission to my app. But when I saved the file in the Documents Folder, I will get the error about accessing path /storage/emulated/0/Documents/anew.txt is denied.
The read and write storage permission cann't access the Documentss Folder with a path.

Android Studio cannot read from file, does not exist

I'm trying to read from a file in Android Studio, in a small Java app. So I'm trying this:
File test = new File("C:\\testing\\testFile.dat");
if (test.exists()) {
System.out.println("test exists");
}
else {
System.out.println("test doesn't exist");
}
The file definitely exists, but it keeps on reporting that the file doesn't exist. I was able to work around this with another file by using the AssetManager and reading it through a stream, but the method I'm calling now requires a File's absolute path, but it's point blank refusing to find the file.
Am I doing something dumb, or misunderstanding something?
UPDATE
Ok, thanks for the input, I've now solved the problem. First I had to upload the file I wanted into the virtual device's storage, then I was able to get the path to it.
File test = new File(this.getFilesDir().getAbsolutePath(), "testFile.dat");
but the method I'm calling now requires a File's absolute path
Assets are files on your development machine. They are not files on the device.
Ideally, you switch to some library that supports InputStream or similar options, rather than requiring a filesystem path. If that is not an option, you can always get the InputStream from AssetManager and use that to make a copy of the data in some file that you control (e.g., in getCacheDir()). You can then pass the path to that file to this method.
You can place this file in your assets/ folder inside the android project and access using the following code.
val inputSteam = assets.open("testFile.dat")
or place it inside the res/raw folder and access it like below.
val inputStream = resources.openRawResource(R.raw.testFile)
We can't access a file on a development machine like this and won't be available on an android device so it will break so it's better if we move this somewhere inside the project and access it as above.

File not found on Android Device

I have an error here:
FileHandle file = Gdx.files.internal("hscore.json");
Showing that it can't be found:
...
com.badlogic.gdx.utils.GdxRuntimeException: File not found: hscore.json (Local)
at com.badlogic.gdx.files.FileHandle.read(FileHandle.java:136)
...
It works on my Desktop, but fails like this on my Android Phone.
I use Android Studio, where I keep the file in the assets folder which is in the android folder.
I have no idea why it can't find it on the android?
Update: I don't know what happened in meantime, but now it highlights this line of code after throwing the same error:
String s = file.readString();
It can read .txt files and other files I'm using just fine, seems the .json file is the problem for android?
Until this is resolved, I'm using Preferences to save data there, rather than the whole class in .json
Thanks to a chat with p.streef This question has come to a closure, sorta.
1) I created a new test.txt file and it worked fine reading that.
Maybe then the .json file itself was a real issue?
2) But then I renamed it to text.json, and afterwards back to hscore.json
It worked fine in both cases when opening and reading the file.
I had no idea why the initial file .json was not readable?
3) I also killed and restarted my android studio in meantime because it froze at a point when building my project.
After all of this the problem of file not being found was resolved by itself.
Anyway then I realized that the file is not writable since internal files are read-only.
I decided to stick then with the Preferences as the final solution.

Can't find folder or file created with Android App with windows file exlorer

I'm creating a directory and a text file on the sdcard in one of my apps because I want to be able to move it to my computer for analysis. But I can't find the folder or the file I'm creating on my sdcard using the file browser on my computer.
I CAN find and read the file using my phones file manager but not using the file browser in windows.
So the file and folder are succesfully created and I can write to the file, I can also find and read the file using the file manager on my phone but I can't find either directory or file using my computer.
I have a uses permission for the application to allow it to write to external storage.
This is the code I use to create the file and directory.
String fileName = "testFil.txt";
String path = Environment.getExternalStorageDirectory().getAbsolutePath()+"/PulsApp";
File appDirectory = new File(path);
appDirectory.mkdirs();
File file = new File(path, fileName);
try {
file.createNewFile();
} catch (IOException e) {
}
Does anyone know what the problem is and how to fix it? I really need to be able to write files to my sdcard so I can transfer them to my computer.
I am completely baffled by this problem since all the research I've done point to that everyone else is doing the same thing.
If your device is running Android 3.0 or higher, you also need to use MediaScannerConnection to index your newly-created file before it will show up on a development PC's file explorer.
More accurately, the newly-created file needs to be indexed by the MediaStore. That will eventually happen for other reasons (e.g., device reboot). However, you are better served using scanFile() on MediaScannerConnection to get it to happen more quickly.
I blogged about this last summer.
Sometimes that the MediaScannerConnection will recognize the folder as a unknown type file, so try to create another folder inside the original one can avoid this problem.
I have met the same problem, and I use the method in the comment
And it works for me.

Storing on the external storage card

I want to store data recorded with the accelerometer on the external storage but I have an error when I try to create the directory in which I want to save the data. My code is as follows :
dataDirectory=Environment.getDataDirectory();
path=DataDirectory.getAbsolutePath();
path+="/"+getResources().getString(R.string.DirectoryName);
myDirectory=new File(path);
myDirectory.createNewFile();
The createNewFile call triggers an IOException.
I can add two things : the path variable is set to "/data" after the call to getAbsolutePath and the getExternalStorageState function returns "mounted".
Can anyone tell me what is wrong in my code?
Thanks in advance for the time you will spend trying to help me.
You can't have permission to write in the /data directory
Use the sdcard directory
Or try working in the /data/data/com.yourapplication/files directory where you do have permission. Use Context.getFilesDir() to get the path of your application's working directory.
try this
path=DataDirectory.getAbsolutePath().toString();
add WRITE_EXTERNAL_STORAGE permission in your manifest file

Categories