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".
Related
I have a service inside an app: serviceA. I want to insure that serviceA is the first service to run at boot (after the system services, of course).
I currently have implemented all the necessary intent-filters: BOOT_COMPLETED, QUICKBOOT_POWERON, PRE_BOOT_COMPLETED, and REBOOT. (From reading I know that QUICKBOOT_POWERON and PRE_BOOT_COMPLETED are redundant, but I keep them to make me happy).
However, my service is not the first. I'm assuming that there is no real way to deterministically guarantee that my application's service is the first one to start.
I'm assuming that there is no real way to deterministically guarantee that my application's service is the first one to start.
You could build your own custom ROM. Then, you could tinker with how Android handles the BOOT_COMPLETED broadcast and arrange to get it first yourself. Or, you could dump Android services entirely and do whatever it is that your are doing via a Linux daemon.
Otherwise, no, as BOOT_COMPLETED is not an ordered broadcast.
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
I'm building an application which have a Service. I know that all application components run in the same UI process, at least you specify it in the manifest. So to avoid ANR's messages i have three ways.
Specify the service in the manifest to run in a separate process like
android:process=":remote" but i've read some StackOverflow's post that
says that it's not a good idea, because it consume a lot of battery and cpu processing.
That i really respect since those post are from trusted people.
Use an IntentService. it's probably a good way out. but i need my service running even if the
activity isn't visible. Because i need the service keep checking against a web service for new
messages from other users and notify thru Notification. Could it be posible using a
an IntentService? is that an ellegant solution.
Use a local service. just removing the android:process=":remote" attribute from the manifest file.
But i get some ...OnMainThreadException errors. it means that i need to create an special
thread to execute those long running operations or use AsyncTask,
maybe there are another ways to do it. please let me know, how to execute long runnig operations on the service. is really imperative.
thanks.
Android Service executing in UI thread. So you should use AsyncTask or another way to work with threads for network requests.
First of all, let's accept that there 2 parts: an active part (the networking) and some sleeping part before the next active part. I think you can use a plain local IntentService for active parts. Each active part on its completion should reschedule the next active part using AlarmManager. This approach makes sure your app does not consume resources during sleeping parts. You are right - once the IntentService gets a result to be presented to user it can use Notification.
I'm developing an app designed to transform an android phone into a remote device running without user action. At the time the app is made by an Activity that sets AlarmManager to execute a service (class inside project) every X minutes.
All this works OK, but occasionally after 5-6 DAYS continuosly running the application crashes (currently I don't know why, because i can't get the phone now). It isn't a connection problem (I know) and the phone is still running (plugged into AC). The only thing that i can suppose is that the application is down.
I don't think that this is due to a bug, because the prew debugging doesn't give me any errors.
So I must suppose that android has killed the activity (system needs more memory?) and as the image explain there is no way to back it up.
But I have a doubt: in my application the activity doesn't matter, because all the work is done by the service. The service itself is called by an Alarm Manager and in the time between two calls the service is terminated by StopSelf().
In my case the system may kill my alarm manager service schedule?
What can I do to have the service start up by Alarm Manager forever?
(ATTENTION: currently there is yet a WAKE LOCK but this consider only the execution of the service! I hope that you have understand that the service is called each x minutes by alarm manager and than terminated...i want to perform this operations for an indefinite time)
[I haven't posted the source code because is too long]
Lork,
After wrestling with a similar issues myself, I may have some pointers for you. I assume that you are using your Android device as a sort of remote ‘embedded controller’, which performs its functions with minimum user interaction. I believe that you are 95% there and just need to make some slight architectural changes. As you have not provided code, I’ll just explain in abstract terms rather than give code examples.
CommonsWare is correct that you need to use AlarmManager, but I suspect you already knew that.
A couple of background comments first, just to make sure that everything is understandable.
Alarms created by AlarmManager exist at the system level, that is they can exist beyond the lifecycle of the activity and application that created them. If you set an alarm but don’t want it to go off if your app changes state (for example after it has been destroyed), then you can cancel it using alarmManager.cancel(pendingIntent) – just create the intents and alarm manager with the same parameters and Android will match the alarm).
Similarly, BroadcastReceivers are registered at the system level (at least if they are declared in manifest.xml) and can exist beyond the lifecycle of the activity and application that created them. Again if you want to ensure that a BroadcastReceiver does not fire in response to an event occurring after your app has changed state (for example after it has been destroyed), you need to explicitly unregister in it code. If it was registered programmatically then use context.unregisterReceiver(broadcastReceiver); if it was registered statically in the Manifest its not so easy – you will have to retrieve the receiver using PackageManager and ComponentName (see: Android - how to unregister a receiver created in the manifest? ) - and remember that you will need to re-enable the receiver if you need it again.
You say you have already set up your alarm. Make sure you specify ELAPSED_REALTIME_WAKEUP or RTC_WAKUP for the alarm Type to ensure that it runs even when the phone is in ‘sleep’ mode.
You also say you have already created the associated BroadcastReceiver to handle to alarm event. The BroadcastReceiver should do a minimum of work, so you should handle any processing in a separate thread or by launching a Service. You opted to launch a Service and terminate it using stopSelf() when it has finished, so that it doesn’t use up system resources. So far so good.
This is fine when the app is running, however as you require something that runs reliably for an indefinite period, you need to ensure that you manage the 'exception' situations where it has paused, the device is ‘sleeping’, the app has crashed/terminated, or the device has rebooted (and any other exception scenarios you may think of). Here are the issues I have identified that you need to address:
First: WakeLock is only guaranteed for the duration of the onReceive() method of the BroadcastReceiver. After it has terminated, the device could go back to ‘sleep’ even if your Service has not started or even completed, so you need to create a WakeLock, pass it to the Service and release it before you stop the Service. (Note: for your application, you require a PARTIAL_WAKE_LOCK). Be very careful using WakeLocks – make sure you only hold a WakeLock for the minimum required time and ensure you release it, as it’s use can lead to excessive battery drain). See http://www.netmite.com/android/mydroid/development/pdk/docs/power_management.html for an example of using WakeLocks.
Second: If you reset your alarm in code (rather than defining an automatically repeating one), do this in the OnReceive() method of the BroadcastReceiver or as the first thing in the Service you have launched – this will ensure that the alarm repeats, irrespective of the state of the application or device.
Third: Make sure that any Contexts you use are going to be non-null values. You can dynamically fetch the context in the Service using getApplicationContext(). Otherwise this can be achieved by EXPLICITLY passing the Context from your application to the alarm and make sure it is passed all the way through the BroadcastReceiver, and associated threads and Services. If you have statically stored Context in your application so you can retrieve it anywhere, then this will return a null value if the application has terminated. If you use the Context (for example to retrieve a resource, access a database etc), and it is null, it will cause a null pointer exception and the Service or BroadcastReceiver will crash. I believe this is the most likely reason for your Broadcast receivers not to be working when your app has terminated.
Fourth: You may wish to make references to ResourceIDs (e.g. R.drawable.icon) in your Service or BroadcastReceiver fully qualified (. R.drawable.icon) or generated from the passed Context. I haven’t yet found this to be necessary, but I suspect it may be prudent.
Fifth: Implement a separate BroadcastReceiver to handle a device reboot scenario (ON_BOOT_COMPLETE event). You could get this receiver to re-launch the app if appropriate or it could launch a service to check that your app is supposed to be active, set up any required parameters and set up the relevant alarms, then terminate it using stopSelf(), or just set the alarm again and let that receiver handle it all. Remember to ensure the service has a WakeLock for its duration and to release the WakeLock when it is complete. If you don’t just relaunch the app, or a Service (declared as part of your application) then you should also statically store the correct Context as a class attribute in your BroadcastReceiver, if you need it, so that it is available to access resources.
A couple of other things you may wish to consider:
As your set up is remote, I would seriously consider storing any persistent data in SQLite database tables. This will ensure that data is recoverable between application terminations and device reboots, without having to regenerate it.
If your application communicates with a server service, consider using push notifications for server initiated communication, rather than have the app periodically poll. Push Notifications can also be used to ‘wake up and launch services and apps’, so could be used as part of a remote mechanism to query the status of the device and your application. This approach is also more power efficient and timely.
Post information to LogCat at key points in your code for debugging. If the application terminates, then adb stops tracking the source code running for the receiver and service, but LogCat continues to function, so can be used to check the path through the code and variable values.
Other people may have better ways to address these issues or some other pointers (I would certainly be very happy to see other input), but I hope these ideas are helpful and good luck!
The point behind using AlarmManager with a service is to start up a service that will run briefly, then the service goes away (e.g., an IntentService). If you are going to try to have an everlasting service, you do not need AlarmManager, and your service will be shut down by Android after some period of time.
If you rewrite your app to not need an everlasting service, but rather use AlarmManager as it was intended, you should have better survivability.
I believe that what Lork wants to achieve is similar to something I am also wrestling with.
He wants the alarm manager to trigger a broadcast receiver that will handle the alarm, even when the application it is part of, has been terminated (for example by the Android OS).
For example: The application sets an alarm, with a type of ELAPSED_REALTIME_WAKEUP or RTC_WAKUP and has a Broadcast Receiver to handle it when it fires, via an Intent which references the application context and the Broadcast receiver class. The receiver is declared as a in the application manifest.
Under normal circumstances, when the application is running or paused, when the alarm goes off, the Broadcast Receiver is triggered, waking up the device and resuming the application as necessary, and the alarm in handled.
However, if the application has been killed (for example by the OS), then the alarm will still go off (as it is still registered) but the Broadcast Receiver will not be triggered and LogCat shows a null pointer exception, (I assume because the reference to the application is no longer in memory). This will occur, even if the Context has been passed.
Am I (and I assume Lork) missing an easy strategy here? Or is it not possible? Can a broadcast receiver exist on its own and trigger the app if necessary?
One, imperfect strategy I have been toying with, is to move all the app data access into a Content Provider, and have a separate low profile app which just implements the broadcast receiver – triggering a service to do the work and accessing the application data it requires via the Content Provider. This would still be subject to being terminated by the OS, but would be less likely.
What are the practical differences between putting a service in a separate process or keeping it in the app's main process? What would each scenario be used for?
When a service is running in the main process it will be stopped in case your application crashes for whatever reason. Put a service into it's own process is reasonable for some services which can be used from different applications or services which should run independently from your main app.
The only reasons I see for putting a service in another process is
The application is resource heavy and likely going to be killed quickly by the OS. Putting the service in a separate process will distribute the resources and if you application dies your service won't.
JUST in case your application has errors and dies your service will keep going.
However if you create a good application and use good programming you should not run into either of these issues. By having your service in a separate process it causes trouble with things like SharedPreferences and concurrent DB access... I would recommend not doing it.
Not to mention... another process means another DVM. This will take more resources than running in one DVM and slow things down.
Also putting service in another process makes your changes of static variables invisible for main process. You can get situation, when you assign a variable with some value, and it is not changed!! I spent whole day for this issue!
Following is a quote from Android Developer's web site.
Note that services, like other application objects, run in the main thread of their hosting process. This means that, if your service is going to do any CPU intensive (such as MP3 playback) or blocking (such as networking) operations, it should spawn its own thread in which to do that work.
Jake points out that you can, thru manifest, control the Name of the process it is running. But following findings from Documentatioin:
Most confusion about the Service class actually revolves around what it is not:
A Service is not a separate process. The Service object itself does not imply it is running in its own process; unless otherwise specified, it runs in the same process as the application it is part of.
This is interesting, what is said Here is:
The name of the process where the service is to run. Normally, all components of an application run in the default process created for the application. It has the same name as the application package. The element's process attribute can set a different default for all components. But component can override the default with its own process attribute, allowing you to spread your application across multiple processes.
But anyway, if you need Service to be exposed to other applications, for example, you need to provide content (like phonebook) to other applications, setting service to run in different process is the reason.
Using the process attribute of a service is rejected by the manifest parser so it is rather misleading!