If i have to write a lot of bytes to 'disk' how do i make sure, that this operation is not interrupted or the user/system starts other file operations that could cause trouble ?
I am just worried, that when my ASyncTask writes to disk for about 30 seconds, that other processes in the foreground may work on the disk and my stuff gets corrupted. I have no idea how android manages its disk accesses.
Or is it no problem at all ? I just need to know, that my data is written to disk correctly, no matter how long it takes.
I know that the SQLite database i can start exclusive transfers and stuff, but i doubt i can lock the disk for my app only, that would be malware heaven.
Android is running on a mature Linux Kernel. At any given time, there are dozens of 'disk' operations active. Your app is but a small part of the big game. No worries, write as long as you want -- as long as you close your file before the system shuts down, your app crashes, or the user kills it, your file operation will complete. Even in any of the above cases, the storage should not be corrupted. Proper system shutdowns and process terminations should close all open resources. Even if your system suddenly loses power, thanks to the ext4 file system, disk corruption should be rare.
Related
I'm having trouble understanding the use cases for AtomicFile. Since it does not confer any thread safety, is it just for ensuring no partial/invalid files are written if the app crashes or device loses power during a file write? What would be the purpose of reading a file with AtomicFile?
is it just for ensuring no partial/invalid files are written if the app crashes or device loses power during a file write?
Yes.
Adding on to the cases, the OS can kill the process at anytime. AtomicFile should provide atomic guarantees in that case too.
I have an android app that needs to store critical information coming from a sensor. The sensor updates data every 5 ms. I need to persist each of these data points on internal memory in text files.
In the current scenario, I am collecting data points for 2 seconds in memory and then writing to the file at the end of 2 seconds to save battery life. However, under situations where the app crashes, I am loosing the critical data points.
Does anyone have any suggestions on how to handle this?
Is it a good idea to write the data point to the file every 5ms. Would this significantly reduce the battery life and increase the load on the CPU? If anyone has come across a similar situation, can you please share how you resolved the issue?
I would suggest you to study the reason of your app crash. If your app is crashing because of internal exceptions there is a better way of dealing with this thing.
Write a good exception management and use this blocks to write data to internal memory whenever there is an exception generated. Re-start the app after the data has been successfully written.
It you app is crashing because of external reasons and you are unable to catch exceptions, you have to think of some other way.
As your App is critical, I would look into setting up a DefaultUncaughtExceptionHandler by calling Thread.setDefaultUncaughtExceptionHandler in your Application class. This way in the handler, you can write all unsaved data, AND you can restart the app for continued handling of your critical data. I would put some seconds counter in there, to prevent an infinite loop of crashes. The Open Source ACRA library uses Thread.setDefaultUncaughtExceptionHandler, so you may get some idea from there on how to use it.
An additional idea is to write the data using a service in a separate process, search for "Remote Service". This way, even if the app crashes, the service will still be alive. You will have to setup some functionality on how to share the data between the app and the service. If the app is really critical, I would setup 2 remote services, one that gets the info from the sensor (and caches it as a backup until confirmed that it's written), and one that caches the data and writes it every few seconds. Each service should also have a DefaultUncaughtExceptionHandler as above. This is in addition to the actual app, that will have the user interface. Though it is a little waste of resources, but for critical data it is not wasted.
i donot think there's a good method. What more important is to avoid crash maybe
Instead of writing to a file every 5 ms, which will be a costly operation, you can save data to SharedPreferences every 5 ms and every 2 sec, save the data from SharedPreferences to a file. SharedPreferences content won't be deleted even if app crashes and hence you will not have any data loss.
Basically I have an app that would require things(around 20 index files) to be loaded at the start of the app in-order to do some instant-searching later in the app. Although all in all, the index files totally is only several hundred K, as decompression has to be done, the loading actually takes a while. So I am wondering if it is possible to keep it in memory by running service? I wrote a local service within the same package with my app. And when I force closed my app, my service closes too. Should I be using a remote service? if so what I have to do is when I open up my app, it should be able to get 1 int[] and 1 ArrayList from the service, is this doable? or are there any other better options? Thanks a lot
Keep in mind - you're developing for a mobile phone. Memory is limited. Your app will not be the only app the user will be running. Trying to hog memory persistently for the benefit of your own app is bad practice. The user will not want to have your service running all the time.
Sure, the operating system will eventually kick your service out of the window if memory gets tight, but it's better practice to not use a service to store data. Use a separate thread on startup and decompress the data.
You could consider writing the decompressed index file to external storage, or compressing it in chunks so that you can get by without having to decompress the entire thing.
If you really think this is an important feature for your app, make it optional in the settings and add a service (possibly even using a broadcast receiver on boot if your app is so important to the user) to load and decompress the data. But I would really recommend against having a service for storage, if that's what you're planning to use.
Lets say I have a Service S and Activity A. S downloads data for A (or handles some long running work, whatever), but A is not always present. I don't want S to hang around when it's job queue is empty: S should post the results of the finished works to some kind of a mailbox for A, so A can pull the messages when it comes back again.
Can this be achieved without using SQLite of file storage for the implementation of the mailbox? I'd prefer some faster mechanism, write operations tend to be quite slow on a device. I thought about using a simple static list inside the ApplicationContext, but afaik relying on the ApplicationContext results a risky/fragile solution.
Could anyone recommend a pattern for this problem?
Can this be achieved without using SQLite of file storage for the implementation of the mailbox?
Not reliably. Either it's a file, or it might be nuked before A comes back again. Remember that your process -- where all your static data members and the Application object reside -- does not live forever. Once S shuts down (which is a good thing, thanks!), Android is welcome to terminate the process, taking your "mailbox" with you if it is solely in RAM.
You could persist it to disk yet keep a singleton or something around as a cache, so if A returns quickly you can skip some of the I/O. Or, if it does not really matter much if the messages exist for A, you could keep them in RAM and simply shrug your shoulders if the process gets terminated first.
I there a place where I can do some housekeeping activities if an Android application crashes for some reason? Some things like closing handles, connections etc?
You can use Thread.setDefaultUncaughtExceptionHandler() to register for crash events. Though if your entire app crashes you don't have to worry about closing connections as they will all be killed along with the app.
The OS kernel will close all your open filehandles, sockets, allocated memory, and so forth. It can't flush buffered IO internal to the program, and it'll just tear down your TCP sockets without saying BYE to the remote peer, but there isn't much you can (or need) to do when the OS reaps your process.
But you might need to do some cleanup at next startup, if your application crashed while leaving inconsistent data on the persistent storage.