13

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?

user496854
  • 6,461
  • 10
  • 47
  • 84

4 Answers4

4

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.

Cheok Yan Cheng
  • 47,586
  • 132
  • 466
  • 875
2

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.

a.ch.
  • 8,285
  • 5
  • 40
  • 53
  • 1
    Will running it in a separate process get rid of the slowdowns caused when a huge number of contacts need to be synced? Right now that's happening for users syncing 5000+ contacts. – user496854 Dec 24 '13 at 05:15
  • To avoid slowdowns just run syncing in a [separate thread](http://developer.android.com/guide/components/processes-and-threads.html#Threads), no need to dive into separate process overhead for this reason. – a.ch. Dec 24 '13 at 06:08
  • 1
    Isn't running a sync adapter in a separate thread pretty pointless? PreformSync would exit while the thread is still running, which would kill the service, and leak the thread. On top of that, the sync adapter will mark the sync as finished, but it really isn't, and that could cause major issues. – user496854 Dec 25 '13 at 14:08
  • As stated [here](http://developer.android.com/training/sync-adapters/creating-sync-adapter.html#CreateSyncAdapter): _The sync adapter framework runs onPerformSync() on a background thread, so you don't have to set up your own background processing._ So everything seems even easier to implement – a.ch. Dec 25 '13 at 14:59
  • 1
    But it still runs it on the main process -- when there is a very large number of contacts, I have users reporting that the UI freezes. And that only happens when the sync adapter is running (I went through a bunch of troubleshooting to verify this) – user496854 Dec 25 '13 at 17:45
  • This is odd. Could you add the code showing how you run syncing to your question? – a.ch. Dec 26 '13 at 06:36
  • 1
    There is a lot of code, and I honestly don't think that it would give you any helpful information. But basically, the freezes happen if there is a ContactsContract provider query from the main app (to look up a phone number, or a photo, or anything else) at the same time as the sync adapter adapter is reading all the contacts from the same provider – user496854 Dec 26 '13 at 10:38
  • @user496854 This is kind of old by now but are you still having that problem? If so, I'm assuming you're probably using `applyBatch` with `ContentProviderOperation` for your sync and wrapping it in a transaction? As long as the transaction is running, you're effectively "shut out" of your data unless you insert yield points. (Check out [this](http://developer.android.com/reference/android/content/ContentProviderOperation.Builder.html#withYieldAllowed%28boolean%29) ) – BadIdeaException Mar 25 '14 at 17:24
1

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.

tnj
  • 921
  • 7
  • 12
1

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
rds
  • 26,253
  • 19
  • 107
  • 134