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.
Related
I'm developing an Android app that is going to be embedded on a non-mobile device owned by our client, and used by our client's customers. My boss is envisioning a second app for the machine that runs in the background and sends data about the device to the backend periodically via a Service. I've employed this method, though I'm aware that it is imperfect because Android is prone to killing background services at will and at unspecified times, namely when it decides the service is obsolete or the system needs more memory.
That said, we are running the open-source version of Android (v5.1.1). I'm wondering if there are any options available to my OS team that aren't available for those building apps for the Google Android flavors, some way to remove those typical house-keeping mechanisms or auto-restart apps that have been closed?
Set android:persistent="true" on your <application> tag in the manifest.
The docs say:
Whether or not the application should remain running at all times — "true" if it should, and "false" if not. The default value is "false". Applications should not normally set this flag; persistence mode is intended only for certain system applications.
For this to work, your APK will need to be installed on the system partition. It may also need to be in the priv-app dir or be signed with the same key as the system (some of these things do; I don't remember for this specific case).
Note that your Application.onCreate() will be started automatically; your Service will not be started automatically. Not that you need it; when you're persistent, the Android system won't (normally) kill your process, so you can just run normal threads doing what you need to.
Finally, make very sure that you're not leaking memory. Persistent apps are killed very late (if at all..?) by the LMK, so it could have adverse effects on the performance or stability of your device.
You have 3 options here in my opinion:
Modify Android OOMKiller to exclude your app. Wouldn't recommend this.
Create a Java system service, that is started by SystemServer
Create a native C "app" (binary), that is started in one of the init.rc scripts. ( The daemon suggested by CommonsWare comment ). This can have the benefit of being able to be run as root if you need it.
In my app, I'm using a contact sync adapter, but it has a lot of information that it shares with the main app. There are settings that the adapter needs to work proplery (like login information and if the user changes any sync settings), so I currently have it running in the same process, and it communicates with the main ap using getApplicationContext(), and then I have some shared variables in the Application that the sync adapter is using during the sync process.
But in the training document, and a few tutorials online, the sample adapter is set up to run in its own process -- it's using android:process=":sync" in the manifest. Is that necessary? And if it does run in a separate process, how can I communicate back to the main app?
In our context, due to fast searching requirement, we are using remote service to hold a huge database in memory.
The reason we are using remote service, instead of local service is that, we believe running the service in separate process, will make us harder to hit maximum memory per process limitation (The limitation is vary based on different devices and OS version).
In our initial design, we are using AIDL. Later, we switch to Messenger. I cannot recall the reason behind. I will check back our source code history log to figure out why. But, I think it is mostly, Messenger is less complicated than AIDL, and we do not need the multi-thread capability provided by AIDL.
Running Service in its own process may be helpful
1) if you want your service to withstand your main app's process destruction (but START_STICKY is more than enough for that case),
2) if you'd like to designate this process for all "sync" tasks of your application (as stated in the tutorial),
3) if you want other apps to use your Service.
To communicate with the Service running in separate process, you use Bound Services.
However, running Service in separate process increases the complexity of communicating with it, so consider if any of cases mentioned above relates to your app purposes.
I think it should be separated, but it's not required.
In general, separating a Service process is well worth to consider if it may be used independently from system components or other applications. In this perspective, the lifecycle of the process should be managed independently from other components such as Activity in the same app, so Android can mark which process is currently used easily and precisely to decide which process to be killed in case of a memory shortage. Also the service can keep running even if the front activity crashed unexpectedly.
It's hard to maintain sharing data between separate processes. For login credentials and preferences, I guess you may go with a combination of SharedPreferences and OnSharedPreferenceChangeListener.
When the application starts, it may cache different things, in particular for the UI. By splitting the sync logic in a different process, you allow the UI process to be killed when the device is running low in memory, which will free these UI caches.
Hence, this technique is primarily of interest to apps that run services for a long time. Typical examples:
the service that plays music in a music app
the service that uploads the video in Youtube
However:
this increases the complexity of the app
if done incorrectly, it can actually increase the overall memory footprint of the app
I am getting started on Android & iOS development and hence links to relevant resources will also be appreciated, just that I couldn't find anything much relevant.
Case Detail: I have to build an app that holds some critical information in a variable that is created, sent over a ssl-encrypted connection and destroyed. This variable shouldn't be read by any other process on the device. So far, I know of two cases that can happen:
[1] a service or program monitors the foreground app(which here would be my app) and then if it can inject some code(getting the foreground to bind to the rogue service for example) to read off the variable contents in question. I know OS safeguards exist, but are there any proofs out in the wild that demonstrate this ability of injecting code?
[2] a service or program monitors the network connections and logs the data being sent over the wire. Is there a possibility of apps reading network data like this? I know apps exist which can log the amount of data exchanged per app, but I have no clue as to whether they read system log files or actually monitor the connection.
It will be appreciated if details could be provided for both the platforms.
I work only with android, so this is valid for android only:
No, a service cannot inject code in foreground up, due to (at least) 2 reasons:
Each installed application gets it's own user id, and each process, and their data is protected by the user id. So one process cannot access the memory of another process. So no process can modify the memory either (by inserting code)
The java bytecode is converted to dalvik code, and stored in a place where only the system process can write. So no other process can inject code by changing the compiled dex files.
That is the protection provided by the system. Of course hackers might find an exploit in a certain library, and using buffer overflow might be able to run some snippet of code, but that's a different story. Also note that the data files of the process are private by default (no other process can see it), but processes could have read access to the code. Which means storing private keys in the code is probably not safe.
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.
I'm currently trying to assess whether a project can be realised for Android. One major problem I see it that, since it's a P2P client, we'd have to keep a considerable amount of connections open when running. Now the connections do not transfer large amounts of data, it's more of a messaging system, so having a thread for each connection creates a useless overhead if we're reading a single message of 64 bytes every now and then.
So I was wondering whether there is support for non blocking IO such as select() or poll() on Linux.
Any suggestion?
Check out java.nio Sockets, Selectors, and Channels. Some links:
Android: Unbuffered IO
http://developer.android.com/reference/java/nio/channels/ServerSocketChannel.html
http://developer.android.com/reference/java/nio/channels/SocketChannel.html
http://www.developer.com/java/article.php/3837316/Non-Blocking-IO-Made-Possible-in-Java.htm
Or, maybe I didn't read your question right.
Of course. Once your application declares uses internet permission, you can do all normal linux networking things normally available to a non-root user in C using the NDK, and any of them from java that someone (possibly you if no one beat you too it) has bothered to write support for.
Well, one exception: your mobile provider probably won't permit incoming connections, and neither will most wifi routers unless you specially set them up to. But those are infrastructure issues rather than issues with android itself.
You will probably also need to come up with some combination of an Activity to provide the foreground UI and a Service to continue the actual transfers in the background with just a status bar icon showing.