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.
Related
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.
As far as I can read, Android may kill my process at any time 1.
One might interpret the article [1] such that, at any point, a process must be able to survive a crash. How is that handled? Are there any guarantees of any methods being called if a process is killed this way? The article* doesn't mention it.
My question is, how do you guarantee that a force-killed process resumes in some sane way on next start? The only state my process has (assuming no guarantees are made for methods being called when process is killed) is the state in persistent storage (a DB or elsewhere) and this is likely to be incomplete if process is force-killed.
Concrete example: Let's say I ask a Service to perform some work. This work is not something like playing a music file. It is work that can be considered "done" at some point (e.g. sending data to the web). If my Service gets killed, say after 50% of the work is done, how would my app know if the work was successful? I could have a flag in persistent storage saying "done", but even then, Android might kill my Service after I send the last byte and before I set the flag.
Is there any common way of handling this? My Service could, when restarted, negotiate with the web server to see if the file was transferred, but it quickly gets really complicated and I don't think it would really solve the problem.
[Edit 1 start]
I am aware of the following text [1] but that does not solve the problem for services, "This last state is generated each time the user leaves that part of the application, not when it is killed"
[Edit 1 end]
[Edit 2 start]
I found something really interesting. An apparent inconsistency in the Android documentation related to this. Please see my new question at 2
[Edit 2 end]
[Edit 3 start]
The "apparent inconsistency" has been resolved. It was due to me not being precise about "app"/"process"/"activity" terms. This question still stands, though.
[Edit 3 end]
Are there any guarantees of any methods being called if a process is killed this way?
Nothing is called on your app when your process is terminated.
how do you guarantee that a force-killed process resumes in some sane way on next start?
That cannot be answered in the abstract.
The only state my process has (assuming no guarantees are made for methods being called when process is killed) is the state in persistent storage (a DB or elsewhere) and this is likely to be incomplete if process is force-killed.
You should be updating your local persistent store when the data changes. Hence, your persistent store is likely to be up to date when your process is terminated. An in-memory cache should be treated as a read cache, not a write cache.
It is work that can be considered "done" at some point (e.g. sending data to the web). If my Service gets killed, say after 50% of the work is done, how would my app know if the work was successful?
It would have to negotiate with the Web server to determine what was and was not successfully uploaded.
Is there any common way of handling this?
There are various approaches for trying to maintain "transactional integrity", particularly for long-running operations where process termination poses a greater issue. None of those are unique to Android, as this has been a problem in computers for decades. Most boil down to "check what succeeded, and re-try what didn't". How complicated this is depends entirely on the nature of the data you are trying to update and the available means for updating it.
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.
I have an Android application that writes data to the SD card. I want to be able to see this data from my PC, when I connect via a USB cable. Unfortunately the application remains in the background when I quit it, and some system buffers do not get flushed properly (or at least I think that is what happens). As a result I cannot see the data properly, unless I manually force the application to stop. Then the data becomes visible on the PC, as if by magic.
I would like to have the program terminate automatically when I quit the main activity, or better still I would like to find some way to flush the system buffers. Does anyone have any ideas?
Do you close your file? Best would be in onPause() probably.
Check the activity lifecycle in http://developer.android.com/guide/topics/fundamentals.html
EDIT:
If you really feel you need to kill your process, you can use
android.os.Process.killProcess(android.os.Process.myPid());
or
System.exit(n)
I really doubt its a file flush issue, you may not be writing the data to the SD card properly. Getting your application to "exit" is as simple as calling finish() in their onStop or onPause, depending on when you'd like it to quit.
Without code, we can't help!
I have project where i'm developing an Android App using a lot of existing C++ code accessed through JNI which opens and closes sockets.
Even though this C++ properly handles the closeing of the sockets it opens, it seems either the Android OS or the JVM keeps around references to those sockets/ports being used until the next GC call.
What happens is if we stop the app and start it again before the next GC call, the app cannot create connections on that same socket/port. If we wait for GC to be called by the OS and then restart the app, it successfully creates the connections.
Is there a way to manually free up a socket from Android's/the JVM's perspective? Perhaps a socket class utility? A manual call to GC?
The operating system's TCP/IP protocol stack holds TCP ports for two minutes after the application closes them. So if you've had a listening socket that has accepted connections, the port will remain unusable for a couple of minutes.
Before you bind the socket to the listening address, call setsockopt() on the socket with option=SO_REUSEADDR and value of 1.
Try
System.gc();
Docs say...
void java.lang.System.gc()
Indicates to the virtual
machine that it would be a good time
to run the garbage collector. Note
that this is a hint only. There is no
guarantee that the garbage collector
will actually be run.