Guidance on Android file storage - java

I need to write an Android app that would download sounds from the internet for further use.
Where should i store these sounds? Is Sqlite an option? And what's the best way to load and play these files?
Thanks in advance.

I would recommend putting the files on the SD Card, if one exists. One thing to note, though, is that you should never hard code a path to the SD card. You would likely want to do something along the lines of:
try {
//Create handle to SD card drectory
exportDirectory = new File(Environment.getExternalStorageDirectory() + "/MyDir");
//Verify export path exists. Create otherwise.
if (exportDirectory.exists() == false) {
if (exportDirectory.mkdirs() == false) {
//Directory structure could not be created.
//Message the user here
return false;
}
}
//Create handle to SD card file.
exportFile = new File(exportDirectory.getAbsolutePath() + "/whatever.mp3");
//Do whatever here
} catch(Exception e) {
//Exception. Message user and bail
return false;
}
From there it is a simple matter of transferring whatever data you want into the file. An SQLite database would likely be overkill for this app, unless you plan on storing a LOT of extra information. There is also no guarantee, unless you store the files directly into the database as BLOBs, that the user won't mess with the file system between application runs. Though, in the case of MP3s and the like, track / artist type information can be stored directly into the file via ID3 tags instead of using a database.
As for playing the files back, consult the Android documentation on their audio APIs. There is a ton of great information out there, definitely more than I can repeat here.

I'd say the best place to store them is as individual files on the sdcard under your own folder i.e. File("/sdcard/com.example.myapp/sound12345.mp3");
EDIT: please see phobos51594's answer which is much more complete than mine.

It's best to save them directly on the file system. Why would you want to store it in a database? are there additional information you need to store together with it? (Like titles, descriptions etc)? If not, I'd write it directly into the filesystem.
Basically you could save it into the data folder of your app (where the shared preferences, and sqlite db are stored too). However, I personally think this should be discouraged, as it reduces the available memonry on the /data partition (which is already tooo small on Android phones. Most phones have less than 50 MB free on data (this means: less than 50 MB for apps, which can't be partly moved to SD card).
You should always safe such fines on SD card if possible, so you don't lower free space on data partition too much. Even with Froyo's A2SD feature, not all data of an installed app is moved on the SD card. The *.dex files (which often ranges between 10-50% of the total size of an app) still remains on /data partition. So does the settings and sqlite databases this apps uses. So even with A2SD the space will become less and less the more apps the user installs

Related

Can I save a text file without giving users ability to modify it?

I'm working on a game and I am at that part that I want to save the game progress into a text file (or maybe a properties file would be good too), but I'd like to save that file to a place that is not reachable for the players. I was thinking about saving it to a source folder inside the program, but I am not able to save or load a text file from there, only images. Could anybody suggest something how/where to save the game stats that players can not just go into the settings file and modify their score or level or something like that?
With the properties file my only problem is the saving, where I need an output stream or a writer to save it, what I', not able to get
Assuming your player's pc has a regular hard drive with regular standards then:
If the game is offline(and maybe later synced with a server) then the answer is NO; if your app can access the file so does the user; even if you encrypt the data written to the save file people can just reverse engineer your app and get the keys and algorithms and modify the file; to put it simply you can only complicate it, their access to save files is inevitable.
If your game is only possible to be played online then you can do sanity check for every action of the players and save the progress in an inaccessible by players manner;
About the read only, been asked before:
create a read-only file
For the second one, keep in mind that as you know the path to the file and the name of it, the user don't. Saving the file using "scary" name, in un-trivial path will protect the file from any changes for a while

Use metadata to uniquely identify files

Hello need to know how to identify the audio file in the storage of a device, the question is as follows:
I am developing a music player and am storing some playback data in the database that are attached to each audio file individually, from time to time the application checks for changes in the user's audio library (on sdcard or internal memory) and inserts the new songs (if any) in the database, the problem is I can not identify if the database already exists because I can not get a common identifier, I tried to use the music path in the storage but in some cases the music name has banned characters that prevent me from using in sqlite so the question is:
How to identify an audio file?
EDIT1:
I think my question was not very clear, what I wanted was a way to individually identify each audio file using for example some metadata of the file that was unique to it and could not be repeated such as the creation date of the file in milliseconds, or any other metadata that is unique to each file, like a fingerprint.
I'm testing a solution that I find not if it is is ideal, I take the path of the file and use the Base64 class to encode it:
String path = "/storage/emulated/0/Download/Disturbed-Ten Thousand Fists.mp3";
Base64.encodeToString(path.getBytes(), Base64.DEFAULT);'
result is: L3N0b3JhZ2UvZW11bGF0ZWQvMC9Eb3dubG9hZC9EaXN0dXJiZWQtVGVuIFRob3VzYW5kIEZpc3Rz
Lm1wMw
The size varies depending on the path but String gets only letters and numbers that are accepted in the database and the result is always the same for each path. What you tink about it?
An audio file can be identified by the extension. A list (not complete) of formats that is used can be found on Wikipedia Audio_file_format
Your best option would probably be to check the file extension and make a list of known extension types related to audio.
This does not, however, cover cases such as an MP4 file with audio and no video.
For the purpose of this, I will assume you already have a variable, either hard coded or in a loop/list, which is the File object you wish to check.
File audioFile;
//this is just for readability, do not write in your code as this should be replaced with the variable you have which is storing the audio file File.
String name = audioFile.getName();
//This is where you can do your logic. The name also returns the extension of the file so you can make sure your music player can handle the file extension, and also check the characters in the name
//Here is an example of detecting the ' character
if(name.contains("'")){
//do something
}
Please let me know if you have further questions!
You must clicked all file format in the file type frame then choose the insert file with audio format such mp3, real, wmp.

Java framework to manage BLOB data outside of database

I want to store my blobs outside of the database in files, however they are just random blobs of data and aren't directly linked to a file.
So for example I have a table called Data with the following columns:
id
name
comments
...
I can't just include a column called fileLink or something like that because the blob is just raw data. I do however want to store it outside of the database. I would love to create a file called 3.dat where 3 is the id number for that row entry. The only thing with this setup is that the main folder will quickly start to have a large number of files as the id is a flat folder structure and there will be OS file issues. And no the data is not grouped or structured, it's one massive list.
Is there a Java framework or library that will allow me to store and manage the blobs so that I can just do something like MyBlobAPI.saveBlob(id, data); and then do MyBlobAPI.getBlob(id) and so on? In other words something where all the File IO is handled for me?
Simply use an appropriate database which implements blobs as you described, and use JDBC. You really are not looking for another API but a specific implementation. It's up to the DB to take care of effective storing of blobs.
I think a home rolled solution will include something like a fileLink column in your table and your api will create files on the first save and then write that file on update.
I don't know of any code base that will do this for you. There are a bunch that provide an in memory file system for java. But it's only a few lines of code to write something that writes and reads java objects to a file.
You'll have to handle any file system limitations yourself. Though I doubt you'll ever burn through the limitations of modern file systems like btrfs or zfs. FAT32 is limited to 65K files per directory. But even last generation file systems support something on the order of 4 billion files per directory.
So by all means, write a class with two functions. One to serialize an object to a file; given it a unique key as a name. And another to deserialize the object by that key. If you are using a modern file system, you'll never run out of resources.
As far as I can tell there is no framework for this. The closest I could find was Hadoop's HDFS.
That being said the advice of just putting the BLOB's into the database as per the answers below is not always advisable. Sometimes it's good and sometimes it's not, it really depends on your situation. Here are a few links to such discussions:
Storing Images in DB - Yea or Nay?
https://softwareengineering.stackexchange.com/questions/150669/is-it-a-bad-practice-to-store-large-files-10-mb-in-a-database
I did find some addition really good links but I can't remember them offhand. There was one in particular on StackOverFlow but I can't find it. If you believe you know the link please add it in the comments so that I can confirm it's the right one.

Java API for considering multiple physical drives as a single logical drive(clustered storage)

We need to store files in a particular directory on a windows machine(say c:/datalocation). Due to huge number of files, the c drive gets filled eventually. Now we need a location in another drive, let it be d:/anotherstore.
Initially we can use the following code to access the store location.
File store = new File("c:/datalocation");
But later when we add another drive, is there any way to consider the new location as logical part of the first location?
Something like the below code.
store.addAnotherLocation("c:/anotherstore");
Here store should be able to retrieve the data from both the locations.
There is no java API, but you can catch the "Not enough disk space" exception which would be a IOException and handle it by making your code to save the files in the other location. And while retrieving the files, you look in both the locations if the requested file exists.
Ok, if you want to randomly save in two locations, then save the file in both locations based on a (int)(Math.random()*2); . If you get 0 , you save in c:/datalocation else in d:/otherStore

Creating an uneditable data file in Java

I am currently writing a program which takes user input and creates rows of a comma delimited .csv file. I am in need of a way to save this data in a way in which users are not able to easily edit this data. It does not need to be super secure, just enough so that it couldn't accidentally be edited. I also need another file (or the same file?) created to then be easily accessible (in the file system) by the user so that they may then email this file to a system admin who can then open the .csv file. I could provide this second person with a conversion program if necessary.
The file I save data in and the file to be sent can be two different files if there are any advantages to this. I was currently considering just using a file with a weird file extension, but saving it as a text file so that the user will only be able to open it if they know to try that. The other option being some sort of encryption, but I'm not sure if this is necessary and even if it was where I would start.
Thanks for the help :)
Edit: This file is meant to store the actual data being entered. Currently the data is being gathered on paper forms which are then sent to the admin to manually enter all of the data. This little app is meant to have someone else enter the data from the paper form and then tell them if they've entered it all correctly. After they've entered it all they then need to send the data to the admin. It would be preferable if the sending was handled automatically, but this app needs to be very simple and low budget and I don't want an internet connection to be a requirement.
You could store your data in a serializable object and save that. It would resist casual editing and be very simple to read and write from your app. This page should get you started: http://java.sun.com/developer/technicalArticles/Programming/serialization/
From your question, I am guessing that the uneditable file's purpose is to store some kind of system config and you don't want it to get messed up easily. From your own suggestions, it seems that even knowing that the file has been edited would help you, since you can then avoid using it. If that is the case, then you can use simple checks, such as save the total number of characters in the line as the first or last comma delimited value. Then, before you use the file, you just run a small validation code on it to verify that the file is indeed unaltered.
Another approach may just be to use a ZIP (file) of a "plain text format" (CSV, XML, other serialization method, etc) and, optionally, utilize a well-known (to you) password.
This approach could be used with other stream/package types: the idea behind using a ZIP (as opposed to an object serializer directly) is so that one can open/inspect/modify said data/file(s) easily without special program support. This may or may not be a benefit and using a password may or may not even be required, see below.
Some advantages of using a ZIP (or CAB):
The ability for multiple resources (aids in extensibility)
The ability to save the actual data in a "text format" (XML, perhaps)
Maintain competitive file-sizes for "common data"
Re-use existing tooling support (also get checksum validation for free!)
Additionally, using a non-ZIP file extension will prevent most users from casually associating the file (a similar approach to what is presented in the original post, but subtly different because the ZIP format itself is not "plain text") with the ZIP format and being able to open it. A number of modern Microsoft formats utilize the fact that the file-extension plays an important role and use CAB (and sometimes ZIP) formats as the container format for the document. That is, an ".XSN" or ".WSP" or ".gadget" file can be opened with a tool like 7-zip, but are generally only done so by developers who are "in the know". Also, just consider ".WAR" and ".JAR" files as other examples of this approach, since this is Java we're in.
Traditional ZIP passwords are not secure, and more-so is using a static password embedded in the program. However, if this is just a deterrent (e.g. not for "security") then those issues are not important. Coupled with an "un-associated" file-type/extension, I believe this offers the protection asked for in the question while remaining flexible. It may be possible to entirely drop the password usage and still prevent "accidental modifications" just by using a ZIP (or other) container format, depending upon requirement/desires.
Happy coding.
Can you set file permissions to make it read-only?
Other than doing a binary output file, the file system that Windows runs (I know for sure it works from XP through x64 Windows 7) has a little trick that you can use to hide data from anyone simply perusing through your files:
Append your output and input files with a colon and then an arbitrary value, eg if your filename is "data.csv", make it instead "data.csv:42". Any existing or non-existing file can be appended to to access a whole hidden area (and every file for every value after the colon is distinct, so "data.csv:42" != "data.csv:carrots" != "second.csv:carrots").
If this file doesn't exist, it will be created and initialized to have 0 bytes of data with it. If you open up the file in Notepad you will indeed see that it holds exactly the data it held before writing to the :42 file, no more, no less, but in reality subsequent data read from this "data.csv:42" file will persist. This makes it a perfect place to hide data from any annoying user!
Caveats: If you delete "data.csv", all associated hidden data will be deleted too. Also, there are indeed programs that will find these files, but if your user goes through all that trouble to manually edit some csv file, I say let them.
I also have no idea if this will work on other platforms, I've never thought to try it.

Categories