25

I'm writing an Android app that contains both UI and separate processes running. I want to share simple information between the main process and a service defined in my application that is executed in a different process. I find to messy to use AIDL for inter-process communication for this purpose.

The question is: Is it safe to use Shared Preferences of the application for communicating between this two processes? This is: both read and write the same shared preferences.

I'm wondering if it actually works. In android developers reference about shared preferences (http://developer.android.com/reference/android/content/SharedPreferences.html) they state: Note: currently this class does not support use across multiple processes. This will be added later. but I don't know exactly what does this mean.

Thanks for your help

Javierfdr
  • 1,122
  • 1
  • 14
  • 22
  • 1
    "I'm writing an Android app that contains both UI and separate processes running" -- why? – CommonsWare Aug 25 '12 at 20:00
  • 1
    The application is intended to check user information periodically and send it via web services. I have a UI that allows the user to defined some configuration and stop or start the service. I don't want to force to keep the application UI process running (just the background service) – Javierfdr Aug 25 '12 at 20:02
  • Why dont you keep the data in application context? I mean write a class which extends Application class and keep the global data. – Mustafa Genç Aug 25 '12 at 20:04
  • 1
    I was actually doing that. But if you run the service as remote (background service in a different process) that data cannot be shared. They both use different "application" in this case. Am I maybe wrong with this? – Javierfdr Aug 25 '12 at 20:07
  • I dont think you need different processes. I think sharedpreferences donot work across processes because of the synchronization involved. You can still read the sharedpreferences but you might face synchronization issues – nandeesh Aug 25 '12 at 20:09
  • 3
    Step #1: Refactor this as a single app with a single process. Step #2: Use `AlarmManager` to handle the "periodic" part. Your current approach (two processes, one apparently running forever) is user-hostile. – CommonsWare Aug 25 '12 at 20:09
  • I'm using Alarm Manager for the "periodic" part. Is it possible to keep the service running once the application has been closed following this approach?. The user is aware that the service will keep running, and he'll have the UI to stop it anytime. But I don't want the service to stop, once he shuts the UI. – Javierfdr Aug 25 '12 at 20:12
  • you can never be assured of your process running in the background. Android will stop the process in case android needs more memory – nandeesh Aug 25 '12 at 20:14
  • I'm aware of that. The original question is about communication between processes of the same application, anyone have a clue?. – Javierfdr Aug 25 '12 at 20:19
  • like i said the problem is synchronization not the data exchange, you can still exchange data – nandeesh Aug 25 '12 at 20:21
  • You mean outdate data synchronization issues, or process-safe access synchronization issues?. In case is the second one, would it help that every method in my Application class has the "synchronized" modifier? – Javierfdr Aug 25 '12 at 20:25
  • To just share data between different threads/processes you can use an interface with 'synchronized' lock, so that only one of the processes is accessing that critical part at any given time. – Deepak Aug 25 '12 at 20:29
  • I am not too sure but there might be some caching involved. It wont help to have synchronized modifier because the objects are different and running on different VMs – nandeesh Aug 25 '12 at 20:29
  • 2
    @Javierfdr : You do understand that an `Activity` (your UI component) and a `Service` don't (by default) run in separate processes? – Squonk Aug 25 '12 at 20:29
  • @Squonk I'm certain about that. Im forcing them to run in separate processes. – Javierfdr Aug 25 '12 at 20:36
  • @CommonsWare The background service will be constantly delivering value, it will send geolocation info and manage some other important activities for the user, I didn't think it was completely necessary to explain the whole application purpose, but thanks for your help. – Javierfdr Aug 25 '12 at 20:36

3 Answers3

37

In Android < 2.3 it works. One process can write changes and the other process can read the changes. The code to read/write shared preferences files (they are actually stored in files) checks if there have been any changes made to the file before reading/writing and they update their cached version accordingly.

In Android > 2.3 it works, but you need to specifically set MODE_MULTI_PROCESS when calling getSharedPreferences().

In Android 2.3 it is broken and it doesn't work :-(

Please note that MODE_MULTI_PROCESS is deprecated in API Level 23 (Android M).

EpicPandaForce
  • 79,669
  • 27
  • 256
  • 428
David Wasser
  • 93,459
  • 16
  • 209
  • 274
  • I've tested on several devices with different 2.3.X sub-builds and had apparent success in every case. Is there something broken about 2.3 I should know about before shipping my code? – Darshan Rivka Whittle Feb 11 '13 at 08:13
  • 1
    @DarshanComputing We have experienced the following reproducible problem on 2.3: Process A updates (writes) the preference. Then process B reads the preference, but it gets the old (not updated) value. It could be that this is fixed in some bugfix release by particular vendors (we were using HTC Desire S for testing). – David Wasser Feb 11 '13 at 09:03
  • Here's the link for more info about [MODE_MULTI_PROCESS](http://developer.android.com/reference/android/content/Context.html#MODE_MULTI_PROCESS) – Anonsage Jun 04 '13 at 00:32
  • @DavidWasser: did android fixed the issue ?.I don't have 2.3 phone to test this one, anyway i have to validate these one because my app is multi process one. – Bytecode Oct 14 '13 at 08:05
  • @Bytecode As far as I know this is still broken in 2.3 and will probably remain broken in 2.3. – David Wasser Oct 14 '13 at 11:53
  • Is this really safe? How does this fit in with the warning in the official documentation about `SharedProcesses` not supporting "*use across multiple processes*"? What about [the known issues with doing this](https://code.google.com/p/android/issues/detail?id=66625)? – Sam Jun 12 '15 at 22:11
  • @Sam Since I wrote this answer, we have migrated our multi-process code to use SQLite database instead of Shared Preferences, which I think is the safer way to go if you need to have read/write access across multiple processes. – David Wasser Jun 12 '15 at 22:32
  • 1
    MODE_MULTI_PROCESS will be removed by Android team since SDK v23 (Android M). I would suggest that you use the library that I mentioned in my answer. – Sam Lu Aug 29 '15 at 09:12
9

You can check out https://github.com/hamsterksu/MultiprocessPreferences library which provides SharedPreferences-like APIs for accessing SharedPreferences data via a ContentProvider. It also looks like a good alternate after Google removed MODE_MULTI_PROCESS from Android 6.

Sam Lu
  • 3,448
  • 1
  • 27
  • 39
0

No; it isn't safe to do this. The note you quoted is correct. There are known issues that can occur if you try to use SharedPreferences across multiple processes. (See https://code.google.com/p/android/issues/detail?id=66625.)

If you want more proof, take a look at the source code for SharedPreferencesImpl, particularly the parts that save the preferences.

I've worked around this problem by preventing both processes from accessing the SharedPreferences file at the same time. (Here's one way to provide cross-process locking, and here's a complete example implementation I wrote.)

Warning: Unfortunately, MODE_MULTI_PROCESS has been deprecated in Android M, so it may stop working in a later release. An alternative technique such as use of a ContentProvider might be a better option.

Community
  • 1
  • 1
Sam
  • 40,644
  • 36
  • 176
  • 219