I am developing an application that makes use of a Service. The Service itself works, but the Android systems kills it within 30 seconds of exiting my Activity, sometimes as early as 6 seconds.
I've had a look at a lot of different posts regarding this and know that I can use a foreground service with an icon. At this stage I don't want to go down this path.
I am explicitly starting the service with the following code. The service is controlled by a SwitchPreference.
The service also returns START_STICKY so it does get restarted.
This is the code I am using (not run together like this).
// starting within the activity
Intent intent = new Intent(context, ListenerService.class);
startService(intent);
// stopping within the activity
Intent intent = new Intent(context, ListenerService.class);
stopService(intent);
// Service onStartCommand
return START_STICKY;
When I exit the application the first time, I see the activity being destroyed and then within 30 seconds I see my toast message displayed stating that the service has been restarted.
I understand that the Android system has every right to kill my service when memory is low, but should I expect it to be killed almost immediately after I exit my application?
Is it just garbage collecting my activity references and starting the service "clean"?
I am cleaning up objects in my onStop() method of the activity.
Also, when I return into my application via the activity, is it good practice to bind to the service to get a reference to the service object?
The binding is completed in onStart() method of the activity as follows:
Intent intent = new Intent(this, ListenerService.class);
bindService(intent, serviceConnection, 0);
Unbinding is completed in the onStop() method
unbindService(serviceConnection);
So 2 questions:
1. Should I expect the Android system to kill and restart my service almost immediately?
2. Is my binding methodology acceptable?
Many thanks
From what i understand you are controlling the lifecycle of your service through your activity by calling startService and stopService. Is this correct?
If you want to keep the service running why are you calling stopService on it?
Regarding the rebooting of the service - everything depends on your service configuration, and your code implementation.
Related
I have made an Intent service and that is working as expected, And I know that intent service does it works and stop itself after its working , so there is not need to stop it. I have made my intent service as you can google it , but I have launched it in a separate process. the code goes like this in xml
android:process=":MYPROCESS"
so in my app , I launch the intent service in the following way on button click
Intent intent = new Intent(DownloadService.ALARM_SERVICE);
intent.setClass(this,DownloadService.class);
/* Send optional extras to Download IntentService */
intent.putExtra("url", "http://myurl.com");
intent.putExtra("receiver", mReceiver);
intent.putExtra("requestId", 101);
startService(intent);
this is just to give you idea How I am starting it , its normal.
What is Happening
I have made a button to stop a service , my this service is downloading something. so What I did , I killed the process , but that start the service again .
As I wanted my service to start again when it is killed by the system or when app is killed so I have set intent to redeliver like following
setIntentRedelivery(true);
So it is amazing situation :so simplifying my question as following
I want to stop service to not to start again , but when it is killed by system or it is killed when user removes app from recent apps , then service should start again (which is going good).
Please tell me how can I achieve this .
In order to do this, you'd have to further modify your custom DownloadService derived from IntentService. The IntentService base class is automatically starting a thread and servicing your Intent there, shutting down the thread and the service when it has no more work to do. You have 2 choices you could use to stop the service:
Implement onStop() in your service and have it set an internal (synchronized) shutdown boolean. In your onHandleIntent() you could check for this flag and prematurely exit the handler and possibly call stopSelf() to prematurely exit.
Alternatively, you could add your own onBind() implementation and have your Activity bind with the service. Then expose a binder method (see docs on AIDL) to be called by your Activity when you want to exit the service. Like above, your service's onHandleIntent() would need to watch for this early-exit type flag and cause itself to stop prematurely.
Note that in either case the service's process will most likely not get killed and this is normal. Android keeps processes cached and in a ready-to-go state so it is very responsive when new requests to start its components arrive. This does not mean your service is "running". It just means the process which will host the service is already created and ready to go.
According to the standard Android documentation, the prefered way to start a service (started service that is) is to use an explicit intent like this:
// Using explicit intent:
Intent serviceIntent = new Intent(getApplicationContext(), MyService.class);
// or:
Intent serviceIntent = new Intent(this, MyService.class);
startService(serviceIntent);
You can also start/stop a service using an implicit intent with an action string specified in the manifest, like this:
// Using implicit intent:
static final String serviceAction = "com.example.my.app.services.MYSERVICE";
Intent serviceIntent = new Intent(serviceAction);
startService(serviceIntent);
// AndroidManifest.xml:
<service android:name="com.example.my.app.services.MyService"
android:exported="false" android:process=":services" >
<intent-filter>
<!-- Start/Stop service -->
<action android:name="com.example.my.app.services.MYSERVICE" />
</intent-filter>
</service>
When the service is used only locally (third party applications are not allowed to start or bind to it), the documentation says that you should not include an intent-filter in the manifest service tag and you should set the exported tag to false.
Note: the activities and services run in separate processes (:application and :services processes). The communication between activity and service is done by implementing AIDL interfaces (this is done because only AIDL remote interfacing allows me to do multi-threading within the service that needs to handle IPC simultanously, not only between activities but mostly between services running within the :services process).
My questions are:
Q1: When the activities and services I use in my app are run in two different processes, do I need to use implicit intents over explicit intents to start and stop the services?
Q2: When the :application process is gone (destroyed, not in memory anymore) and the :services process is running in the background, how do I connect again from a new :application process to the already running :services process? Somehow I need to get a reference to the :services process again so that I can stop the running service inside that process. This cannot be done using AIDL afaik.
The problem is that Android can and will destroy the :application process easily when out of resources, and that is fine by me as long as the :services process keeps running.
(Yes, I know about influencing the process by setting the service as a foreground service, etc. I too can read manuals ;) but that is not my problem).
I cannot find any information or answers related to my questions when the activities and services are in separated processes and use AIDL, AND when the :application process needs to "find" the :services process again after it has been killed by Android or when the user enters the app again (after he/she left the app before).
Any expert-level advise is welcome.
A1 : Even though your activity and service run in different processes they still belong to same Application. You can still use explicit intent, I don't see any specific advantage of using implicit intent here (let me know if find any :) )
A2 : let me list down few facts here
Life cycle of "Started" service (rather than "Bind"ed service) is independent of the life cycle of Activity which has started this service. This is true irrespective whether both are running in the same process or not.
Only one instance of Service will be alive at any point of time. when your activity calls startService() , service instance will be created if it is not already running (in this case you service will receive onCreate() callback as well). But if Service is already running, Framework would simply call onStartCommand() callback on already running process(No onCreate() callback in this case). Again all this is true irrespective of activity and service are running on same process or different processes.
Now to answer your question, if you service is still running (because of startService() call by previous activity), then bindService()/startService() will make sure to connect to existing service.
Hope this is of some help to you. Let me know if you have any other specific questions.
You don't need to use an implicit intent to start a service or activity in a separate process; however, using a separate process for an Activity is a rare scenario. Using a separate process for a Service is more common, but nevertheless I'd like to know what the use case is.
If your application process is destroyed and then restarted, you'd use startService to reconnect to the Service. If the Service is running, you connect to it, otherwise the Service is restarted. If you then want to kill the Service, you can kill it, or you can run stopService() from your main app.
What is the service doing?
I have a Service that has to launch an external Activity.
I would like that even after have launched the Activity, that Service will continue to be running. The problem is that the onDestroy() is invoked and the service is killed.
here it is my code:
How I start the external Activity from inside the Service:
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
Any idea?
Is it normal that when I start an activity from inside a Service, that Service is being killed?
Services are not "killed".
Your service will run until:
You call stopService() referencing the service, or
The service calls stopSelf(), or
If you are using the binding pattern, all bindings (via bindService()) are unbound (via unbindService()), or
Android terminates your process, such as due to low memory conditions or by user request
Hence, you need to determine which of the conditions is true. None necessarily have anything to do with starting an activity.
Note that starting an activity from a service is generally not a good idea, particularly if this may occur at arbitrary times rather than based on user input. Users dislike activities appearing out of nowhere.
I have a service which I know is already running, how does my activity communicate with it without restarting the service.
to elaborate, I have a widget which starts a service, upon click an activity gets loaded, in that scenario the service should still be running.
How do I do something along the lines of:
conditionally checking if the service is alive
accessing methods in the service
Basically, the main thing I do not want to do is run startService(new Intent(...)) within my activity. I don't want to run onStart again within my service.
Ideally I can just add some methods within my service class, and call those within my activity, like I would call any other public method in the project.
I want to start some new threads within my service, and I don't want to make a second service class if I don't have to.
Thanks for the insight
The documentation on startService() might help:
Request that a given application service be started. The Intent can either contain the complete class name of a specific service implementation to start, or an abstract definition through the action and other fields of the kind of service to start. If this service is not already running, it will be instantiated and started (creating a process for it if needed); if it is running then it remains running.
...
Returns
If the service is being started or is already running, the ComponentName of the actual service that was started is returned; else if the service does not exist null is returned.
So if your Service is already running, startService() won't start a new version.
This is my first time experimenting with android services, so I am a little bit lost. I am developing an application that requires a service to run in the background at all time. This service is initialized from an onclick event in the main activity. To start the service I use the following code:
Intent Test = new Intent(this, testService.class);
startService(Test);
In the service I basically have two things. In the method onCreate I initialize a timer and every 30min it opens a new thread and checks if the server has any new data. While on the onStart methods I register a Receiver.
After a couple of hours the service is being killed, is it possible that the garbage collector is removing the service? My suspicion is that the way I am initializing the service it is still binded to the activity "main" process. What can I do to make sure that the service keeps running?
Thanks
You need AlarmManager instead of timer for this task.
OS can kill any normal priority or user defined background service when OS required resources, so if you want that your service run always then you can set your background service to foreground or and if you don't want to let your phone on sleep mode, you can use wake lock...by these you can set your service on always on mode.....
Thanks