Three questions concerning processes in Android. I am developing one app. If I declare a service to be running in another process in AndroidManifest.xml
<service android:name=".MyService" android:process=":MyProcess"/>
Does it mean there will be two JVM instances , one used by MyService while the other one used by other code?
If the answer of above question is YES, then does it also mean if I have a singleton class used by both Activity & MyService, then there will be two instances created for the singleton?
How to ensure only one instance be created & shared by two processes then? Better provide a sample :)
====UPDATE====
Thanks for all your comments and answer(s), unfortunately, my project needs to use separate service process as it has long running background tasks. According to your replies, I have a 4th question:
If I need to pass a non-parcelable object across MyService process and the other code's process. Is it possible? And how?
Does it mean there will be two JVM instances , one used by MyService while the other one used by other code?
yes (in a certain way, but not exactly, it's a dalvik VM, or in Lollipop ART), but yeah, you have two separate things running the service and rest of code.
If the answer of above question is YES, then does it also mean if I have a singleton class used by both Activity & MyService, then there
will be two instances created for the singleton?
yes
How to ensure only one instance be created & shared by two processes then? Better provide a sample :)
you can't! You just told the system to have separate processes. So it cannot have "the same" singleton.
An approach to that is have your service implement a binder or AIDL (in case you to direct calls methods) or implement a ContentProvider, which is the same across processes that you can read values out of it.
Or you can just make it all simpler and NOT use the process. 99.9% of use cases android:process is not advised. So re-evaluate your software. Do you really need it?
edit:
unfortunately, my project need to use separate service process as it
has long running background tasks
If your project need a long running background task, you need a Service for sure. But it doesn't mean it needs to be in a separate process. All the activities from your project can go to background and be garbage collected and your service still runs fine. It will keep running on the same process as the Activities were running but the Service and singletons will still be alive. Just remember to return START_STICKY from it.
If you still think you need to use it in a separate process (I don't think you need). Then you need to implement a bound service (or maybe AIDL, I'm not sure bound service will work across process), connect the activity to it and give the reference of the object using a normal method like public void takeThisObJect(Object reference);
links to bound and AIDL service guides:
http://developer.android.com/guide/components/bound-services.html
http://developer.android.com/guide/components/aidl.html
Related
I have an Android foreground service that contains a map of session (key, session). In my activities, I receive a key and I want to get the session from the service. So I bind each of my activities to the service and I can ask the service to get my session with my key. But doing this means that I have to wait for onServiceConnected() to get the session.
Is it a good idea to bind the service once in my application class and put my service in a static variable, then all my activities can access the service directly in their onCreate() instead of waiting for the call of onServiceConnected()? But is it sure that my static variable will always be there? Do you know if Android can delete that static variable if it needs resources? I guess the application instance is never deleted, am I right? So it could be a good idea to keep my service in a static variable. What do you think?
What you are trying to do sounds like a dirty implementation of some sort of dispatcher from React, I have being tempt to do it my self, but haven't because of lack of time. Please let us know your results.
I would suggest to use a Messager, the doc have information about it, so no need for static https://developer.android.com/guide/components/bound-services.html?hl=en-419
And yes, Android OS can clean anything, it can kill the service, it can null the variables. Most of the time this doesn't happen because it will be done only to prioritize the foreground app. So if a user opens 10 apps and your is on backgound it probably will. Which seems ok to me. From time to tome I have also experienced variables become null in a Fragment, but then I reduced the variable scope and that fix it.
Also if you are considering this, try with EventBus library or by using ReactJava, maybe Realm ORM or even Firebase could help you.
You can bind to the Service in your Application class. The Application instance is basically a singleton and will live as long as the OS process hosting your app is alive. At some point, Android will kill the OS process hosting your app, and then all your app components will go away (Application instance, Service, Activity instances, etc.). If the user returns to your app, Android will create a new OS process, instantiate a new Application instance and then instantiate your app components as needed.
Application itself doesn't have a lifecycle as other Android components, so if you call bindService() during its onCreate() callback, there is no guaranteed point to call unbindService(), which may lead to memory leaks and unpredictable states. Others have also pointed that here.
Instead, you could start your service in the foreground (displaying a notification like "Remote Desktop Manager is running"), which should keep your app alive, and make the map<key, session> a static variable in your Application. In this way, Activities can retrieve sessions without the connection delay. Just don't forget to stop the service by either calling stopService(Intent intent) or stopSelf() when all sessions get closed.
By the way, it should work even considering background restrictions of Android O.
I a am building an android application and at some point I need to build a new specific "Thread", let's call it A.
A will communicate with a distant server (download pictures and send some small data)
A will communicate with several activities of my application (send int/string)
A need to stay alive even if the application is closed
A will stay alive for a specific duration (around 10 minutes)
What should A be ? a Service ? an AsyncTasck ?
I think it can't just be a thread because a thread is linked to a specific activity butI might be wrong.
Bonus question : what is the best way to communicate between A and my Activities ?
Thank you for your help.
Make a Bounded service.
It will work for all the points.
In AsyncTask documentation you can see:
"AsyncTasks should ideally be used for short operations (a few seconds at the most.) If you need to keep threads running for long periods of time, it is highly recommended you use the various APIs provided by the java.util.concurrent package such as Executor, ThreadPoolExecutor and FutureTask."
So is no for this case
A service is the best way to wrap your thread and keep it active after the UI is closed. You service would then communicate with the activity in two ways: either by broadcasting intents or by implementing callbacks. I personally prefer callbacks for a general case.
A main problem based on my experience is keeping the service alive and keeping Android from killing it to save memory. Just because I know this issue might come up I will say that you either have to add a START_STICKY flag to the service or create a foreground service instead of background to keep the service running.
Is there a potential issue using a Singleton Java class by both a Service and Activity in an Android application?
Example: Singleton is Singleton
Activity is A
Service S
Service S has a handle to Singleton. S requests Singleton to launch Activity. Activity calls operational methods defined in Singleton.
I have several Singletons in my application which encapsulate various operations for a functional area. So Activities will interact with various Singletons to perform various operations.
I don't think there is an issue with this approach. I use singletons quite often and never had any problems. You just need to keep in mind that android might remove the singleton instance when it needs the memory, so you need to check for null every time you get the singleton instance.
Usually it won't introduce the issue. The only case You could expect it - using service running in separate process (service has android:process attribute defined which starts with '.'). In that case You'll simply has two instances of the singleton - one for each process.
I have a BroadcastReceiver which is called every so often, and I have noticed many people use
android: process =":remote"
in their receiver. Mine is used to check a few things and if the conditions match then activate an alarm. My question is should I use the line I had posted above in my manifest? And if so what are the benefits of doing so?
By defining your receiver with android:process=":remote" you basically run your receiver in a different process (= VM). For typical use-cases, you don't need to run this in a different process, and whatever you want to do can probably run just fine locally (in your APK process).
The drawback of using android:process=":remote" is that you need additional resources for it to run (in this case a separate process). When doing so, you're basically dealing with 2 VMs, and some patterns like singletons, static fields can no longer be shared between your app and your remote service.
The benefit of using android:process=":remote" is that for some use-cases, it might be handy to start a service that will keep on running (in its own process) after you've shutdown your application, or if you want remote clients to be able to bind to your service. Your broadcast receiver will not block your applications main thread when running in a separate process upon calling the onReceive() method (however, there are other ways of implementing this).
I've found that most of the time, for most common use-cases, you can get away without using android:process=":remote".
In Android, if I want to do some background work, what is the difference between
Creating a Service to do the work, and having the Activity start the Service
VS.
Creating a standard java class to do the work, and having the Activity create an object of the class and invoke methods, to do the work in separate thread.
Doing your own threads is overkill, there are solutions for this, so you don't have to worry about the hard parts of concurrency. Have a look at AsyncTask or IntentService. If you go for a service please keep in mind that your service can be killed at any time.
Well, Android provides some useful methods for making worker threads easily. Look at the Looper class definition. It allows you to send events via a Handler to be executed one after another in another thread or transmit messages between different threads.
A service is nothing fancy. Creating a Service is just a way of telling the OS that you need to do some work even when your Activity is not visible.
Depending on the application you're building it might not be an option.
Nearly every network application will have some of its functionality on a Service to allow the user change active Activity while something is being downloaded.
In an RSS reader, for example you can click 'Update all' and, depending on the current data connection, it might take a bit longer than you wish. So if you want the user to be able to get back to the Home screen and do anything else while the files are being dowloaded you'll have to use a Service.
A Service allows you to run tasks on the background while the user is not on your Activity. This doesn't mean it'll be running all the time. Check the Service lifecycle.
BTW IntentService is a service.