Is it possible for android application to create several directories in internal storage for storing there different kinds of files? I need this capability, because I'll need to delete a kind of files at definite time moment in my application.
When I try to use standard Context method openFileOutput() and send to it filename with "/" symbol I get IllegalArgumentException.
Tell me please what classes and methods could allow me such functionality?
Use Context.getDir(String name, int mode) method to create or access directories in internal storage. Quote from docs:
Retrieve, creating if needed, a new directory in which the application can place its own custom data files. You can use the returned File object to create and access files in this directory. Note that files created through a File object will only be accessible by your own application; you can only set the mode of the entire directory, not of individual files.
UPD Example:
File mydir = context.getDir("mydir", Context.MODE_PRIVATE); //Creating an internal dir;
File fileWithinMyDir = new File(mydir, "myfile"); //Getting a file within the dir.
FileOutputStream out = new FileOutputStream(fileWithinMyDir); //Use the stream as usual to write into the file.
Related
As Google is trying to enforcing apps to use SAF for storage access, I am trying to adapt my app to use SAF replacing java file io apis.
I have spent many hours study the SAF APIs (mainly DocumentFile and DocumentContract classes) but still have some difficulties.
First one is how to move a file to another directory? DocumentFile does have a method to rename a file, but it is just the display name of the file. How can I move a file to another folder, if it is a huge file which I don't want to copy it. Assume src and dst are on the same partition.
Second question is how to list child files efficiently. I checked the source code and found that DocumentFile.listFiles() impl only queries the child files with single projection [ID]. And later when I want to display the files in a list view with their names, the call to DocumentFile.getName() will trigger another query via content resolver for each file again. This is a huge impact on the performance of the code. Especially when I try to sort an array of DocumentFile by their names, 30+ files will cost 600+ms, which is far beyond the acceptable. I doubt whether I am using the correct API set. Could anyone point out a better way to list files with names (and other properties)?
Simple Storage is a library that simplify SAF across API levels. Suppose that you want to move a MP4 file from directory Video in external storage into directory Others in SD card. Let's assume that AAAA-BBBB as SD card's storage ID:
val source = DocumentFileCompat.fromSimplePath(context, basePath = "Video/Infinity War.mp4")
val targetFolder = DocumentFileCompat.fromSimplePath(context, storageId = "AAAA-BBBB", basePath = "Others")
// To move file:
source.moveFileTo(context, targetFolder, callback)
// To copy file:
source.copyFileTo(context, targetFolder, callback)
In C# there are Application.StartUpPath or Application.AppDataPath global methods to get a path where I would store Application Settings.
I tried static String fName = System.getProperty("user.dir") + "SatCli.conf";
"/SatCli.conf" - is the resulted fName
then I call
BufferedOutputStream oustream = new BufferedOutputStream(new
FileOutputStream(fName, false));
and I am getting the common exception
"/SatCli.conf: open failed: EROFS (Read-only file system)"
Well, I've been writing apps under Unix and I understand maybe the file name is refering to internal memory.. in other words to the root part of system file system.
Or maybe not.. maybe it refers to the App Folder?
Anyway, what I would like to get is the correct method to get the right folder to store the settings data.
Also, what is important, I need it before any context is built, when static fields are initializing.
Thank you for any relevant hint and help.
what I would like to get is the correct method to get the right folder to store the settings data.
For arbitrary files, call getFilesDir() on a Context (e.g., Activity). This gives you a File object representing a private directory where your app can read and write.
FWIW, Android's standard way of storing settings that you collect from the user is SharedPreferences, so you can take advantage of PreferenceFragment for the UI.
Naturally I thought to delete a file means to remove it from existence. So when I do
File file = new File(absPath);
....//add content
file.delete();
I expect that no further operation can be executed on file or it would throw an exception. But how come I can still add content to the file such as shown here Android saving Bitmap to SD card. So how do I delete a file so that it is completely gone? So that when someone go look through file manager, the file is no longer there? I am not in a position to test this now, so I was hoping for authoritative reference.
how come I can still add content to the file such as shown here Android saving Bitmap to SD card.
That code creates a new file after deleting the old one.
So how do I delete a file so that it is completely gone? So that when someone go look through file manager, the file is no longer there?
Call delete() on a File object that points to the file. Then, do not use that same File object to write to the file again, thereby creating a new file, as the code that you link to does.
I have created a java application using "Simple" that allows me to serialize objects in some configuration xml file.
These files must be redistributed with my android application, but here comes the problem:
Where do I place the files? Is it better to place them in the res/xml folder or create a custom path to the assets folder (assets/myfiles)?
In the examples given with Simple if I want to deserialize an object I need an xml file:
File fl = new File ("string to file path");
but if the file is in the resources of my project, how do I get the file?
Searching the internet I found only examples that use a XmlResourceParser but I don't know how to use it with Simple!
If you are going to include files you can later access from your application you'll need to put them in the assets folder. After your application has been installed and running you can get get that xml file by using the AssetManager class:
AssetManager assets = getAssets();
InputStream stream = asset.open("filename");
That will give you an InputStream for you to do whatever you need.
What's the best way to create a temporary file in Android?
Can File.createTempFile be used? The documentation is very vague about it.
In particular, it's not clear when temporary files created with File.createTempFile are deleted, if ever.
This is what I typically do:
File outputDir = context.getCacheDir(); // context being the Activity pointer
File outputFile = File.createTempFile("prefix", ".extension", outputDir);
As for their deletion, I am not complete sure either. Since I use this in my implementation of a cache, I manually delete the oldest files till the cache directory size comes down to my preset value.
Best practices on internal and external temporary files:
Internal Cache
If you'd like to cache some data, rather than store it persistently,
you should use getCacheDir() to open a File that represents the
internal directory where your application should save temporary cache
files.
When the device is low on internal storage space, Android may delete
these cache files to recover space. However, you should not rely on
the system to clean up these files for you. You should always maintain
the cache files yourself and stay within a reasonable limit of space
consumed, such as 1MB. When the user uninstalls your application,
these files are removed.
External Cache
To open a File that represents the external storage directory where
you should save cache files, call getExternalCacheDir(). If the user
uninstalls your application, these files will be automatically
deleted.
Similar to ContextCompat.getExternalFilesDirs(), mentioned above,
you can also access a cache directory on a secondary external storage
(if available) by calling ContextCompat.getExternalCacheDirs().
Tip: To preserve file space and maintain your app's performance, it's
important that you carefully manage your cache files and remove those
that aren't needed anymore throughout your app's lifecycle.
For temporary internal files their are 2 options
1.
File file;
file = File.createTempFile(filename, null, this.getCacheDir());
2.
File file
file = new File(this.getCacheDir(), filename);
Both options adds files in the applications cache directory and thus can be cleared to make space as required but option 1 will add a random number on the end of the filename to keep files unique. It will also add a file extension which is .tmp by default, but it can be set to anything via the use of the 2nd parameter. The use of the random number means despite specifying a filename it doesn't stay the same as the number is added along with the suffix/file extension (.tmp by default) e.g you specify your filename as internal_file and comes out as internal_file1456345.tmp. Whereas you can specify the extension you can't specify the number that is added. You can however find the filename it generates via file.getName();, but you would need to store it somewhere so you can use it whenever you wanted for example to delete or read the file. Therefore for this reason I prefer the 2nd option as the filename you specify is the filename that is created.
You can use the cache dir using context.getCacheDir().
File temp=File.createTempFile("prefix","suffix",context.getCacheDir());
You can use the File.deleteOnExit() method
https://developer.android.com/reference/java/io/File.html#deleteOnExit()
It is referenced here https://developer.android.com/reference/java/io/File.html#createTempFile(java.lang.String, java.lang.String, java.io.File)
Do it in simple. According to documentation
https://developer.android.com/training/data-storage/files
String imageName = "IMG_" + String.valueOf(System.currentTimeMillis()) +".jpg";
picFile = new File(ProfileActivity.this.getCacheDir(),imageName);
and delete it after usage
picFile.delete()