I'm blocked with this for a few days and can't find the answer on this.
I start a remote service from an Activity. After starting the service, I close the launching Activity.
I close the main Activity from the task manager like this: home_btn long press and the list of opened app appears and then swipe left on the main Activity.
The thing that happens is that my service gets restarted! even thought it is a remote service, that has it's own process, doesn't depend on the launching activity!
All the internal variables are going to be reset and I don't want that.
-I don't want to use useForeground() method because I don't want my service to be visible in Notification
I currently start a Remote Service like this and the service starts(I can see it in the menu Settings->Apps-> tab Running):
btnStartSrv.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
startService(new Intent("com.example.servicerst_tst.RemoteService"));
}
});
android manifest xml looks like this:
<service android:name="com.example.servicerst_tst.RemoteService"
android:process=":serviceTST" >
<intent-filter>
<action android:name="com.example.servicerst_tst.RemoteService" >
</action>
</intent-filter>
</service>
the service class:
public class RemoteService extends Service{
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
I'm seeing the service restarting or reseting .. in the DDMS.
When closing main Activity the service disappears from the list in the DDMS and the gets started by itself in about 2 seconds. This can be visible in the service also. If you place some internal variables that get change during the life of the service. They will get reset, like the the service is restarting itself after closing the main Activity.
I just want my service not to reset, restart when I'm closing the main launcher Activity.
If the user closes the launcher Activity, from task manager or by his mistake, I want the service to run in background.
Am I doing something wrong here or missing something from my code to prevent restarting?
Why is reseting the service?
From Android Developers - Services : "if the service is declared to run in the foreground (discussed later), then it will almost never be killed. Otherwise, if the service was started and is long-running, then the system will lower its position in the list of background tasks over time and the service will become highly susceptible to killing—if your service is started, then you must design it to gracefully handle restarts by the system".
Declaring your service to run in the foreground has specific requirements: "A foreground service must provide a notification for the status bar, which is placed under the "Ongoing" heading, which means that the notification cannot be dismissed unless the service is either stopped or removed from the foreground." and "To request that your service run in the foreground, call startForeground()." I know you said you don't want it to be a foreground service, but you have to live with the parameters Android sets out for you.
Solved problem with restarting service when launching Activity closes!
You should use startForeground() to not have this issue.
So startForeground() solved the restarting problem when closing launching Activity.
I've made also the service, restarting reliable.
Still I have a question..how the services ... like facebook and other big services run in background without any startForeground() implemented.
Also they are not killed by the system and they run in background forever without any startForeground() implementation. they live forever in background. For sure is somehow possible.
Does anyone know how?
How to avoid notification but still implementing the startForeground() method:
This is done By implementing the notification without
.setSmallIcon(R.drawable.ic_launcher)
for other details see
How to correctly handle startForegrounds two notifications
Related
I am trying to run a service in the background. What my app does is when user checks checkbox then service starts and when it is unchecked service is stopped. Which is working perfectly fine. But the problem is when I closed the app from task manager it then also stops the service. What I want is to keep the service running even after it is close from task manager. Then only way to stop that service is by user himself by unckecking the box.
How can I achieve this?
Here is my code
My main activity
public class SampleServiceActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final CheckBox cb = (CheckBox) findViewById(R.id.checkBox1);
cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
if(isChecked) {
Toast.makeText(getBaseContext(), "Checked", Toast.LENGTH_LONG).show();
startService(new Intent(getBaseContext(), MyService.class));
} else {
Toast.makeText(getBaseContext(), "Unchecked", Toast.LENGTH_LONG).show();
stopService(new Intent(getBaseContext(), MyService.class));
}
}
});
}
}
My service class
public class MyService extends Service {
Notify n = new Notify();
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
n.initNotification(getBaseContext(), true);
return START_STICKY;
}
//method to stop service
public void onDestroy() {
super.onDestroy();
n.cancelNotification(getBaseContext());
Toast.makeText(this, "Service Stopped", Toast.LENGTH_LONG).show();
}
}
Update
How can we make this service so that it runs like gtalk service?
I am not sure which 'Task Manager' you are referring to as different ones would act differently, so I am basing my answer on the action when the user goes to Settings-->manage Applications and--> force stops the app the way android has given him.
Assuming that your service is running as part of the process and if the user force-stops your process, you are prevented from ever running the service again until the user manually launches you.This is especially valid from 3.0 and above version ( check for yours). It also seems logical when you think that there is an app which keeps a service started all the time and is annoying the user in some way. So when the user orders a hit ( :) force-stops) on the app, it should not restart the service to continue bugging the user.For instance, Imagine what would happen if you could create apps which just ate at your processor time by holding a wake lock, and you couldn't kill them. This would be horrible and a huge security disaster.
So, you will not be able to restart your service by any means until the user launches one of your activities.
Also you cannot disable the force-stop button AFAIK. You should take the viewpoint that nothing on the device is yours to control besides your app and (to a limited extent) the resources to which you're granted access.
Finnally, even the gtalk app will bend to your will if you desire to force stop. It will start only when you use Gtalk or other apps which use the gtalk service such as PUSH Gmail ( for phones where gtalk isnt a part of firmware). Also take a look at Android C2DM here:
https://stackoverflow.com/a/11238779/1218762
I think this link will help you.
Disable force stop button in manage application
Its disable the Force Stop button in Package Installer setting so, no one can stop your application.
You cannot prevent your service from being killed under all circumstances. However, you can ask the system to restart it. There are two cases: (1) the process dies for some abnormal reason (2) the phone reboots. In the former, START_STICKY or START_REDELIVER_INTENT are used to restart the service. In the latter, you'll need to add a BroadcastReceiver for android.intent.action.BOOT_COMPLETED.
Your code is returning START_STICKY from onStartCommand, so you've chosen one of the service restart paths: "if this service's process is killed while it is started (after returning from onStartCommand(Intent, int, int)), then leave it in the started state but don't retain this delivered intent. Later the system will try to re-create the service..."
"This mode makes sense for things that will be explicitly started and stopped to run for arbitrary periods of time, such as a service performing background music playback."
You can also use START_REDELIVER_INTENT.
Note that if your service is doing any significant work, it needs to run in a background thread.
http://developer.android.com/reference/android/app/Service.html#START_STICKY
I'm not entirely sure you can prevent your app from being closed by the TaskManager. If you think about it, it makes sense for it to be that way. Imagine that you have an app that fails to respond to user input and also fails to respond to being killed by the Task Manager. Not good. However I found this question which is in a similar vein to yours. Also you can have the system automatically re-start your Service as described here (scroll down on that page a little to just before 'starting a service'
use my method if you want to start a hidden app for just first time
I make a transparent Launcher activity like this
<activity android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#style/Theme.Transparent"
android:excludeFromRecents="true"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
So I make the app hidden in launcher by placing this code in oncreat()
[Code]
PackageManager p = getPackageManager();
ComponentName componentName = new ComponentName(this, MainActivity.class); // activity which is first time open in manifiest file which is declare as <category android:name="android.intent.category.LAUNCHER" />
p.setComponentEnabledSetting(componentName,PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
So I use this code for show app icon on launcher and make it run able on service class that use broadcast receiver boot and in network connection broadcast receiver class too(autostart.java and networkConnectinCheck.java):
PackageManager p = context.getPackageManager();
ComponentName componentName = new ComponentName(context, MainActivity.class);
p.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
Now I can run app for first time by user hands and after this I use my receiver's to lunch app any time.
Let your Service run in a separate process. There is a good tutorial in this blog.
You can specify the android:process attribute in <Service> tag to make your app run within its own process.
<service
android:name="MyServiceName"
android:process="my_process"
android:icon="#drawable/icon"
android:label="#string/service_name"
>
</service>
You can try to restart service on onDestroy event of service. Use some flags to find if service is closed by the User or its force closed.
Note that there is not guarantee that onDestroy will be called everytime.
I am confused right now , about service concept of running and stopping:
what i want to do:
Start Location service at the very start of application.
Keep getting location updates and store them to shared preference
Stop the service in onDestroy of Application scope!
So far i have searched and studied we can only do following things with service(correct me if i'm wrong):
Stop the service automatically by binding it to related activities/fragments/views , when all of them destroyed service unbind itself automatically so we can call stopself method in unbind
return START_NOT_STICKY in onStartCommand to tell OS , don't recreate it , and create intent local service , after completion of some work it will destroy itself.
Stopping the service manually , by declaring it's intent in some kind of static scope and stopping the service in on onActivityDestroyed of Application class [I am not sure what will happen? , maybe service will destroy each time any activity will be destroyed ? or it will be destroyed only when overall application get's destroyed?]
Either way , i am bit confused and beat , been trying to adjust my Location service with given details for 2 days
If you start your Service using START_NOT_STICKY, then your app will kill your service once your entire application is closed from background i.e. you cleaned your app from home screen.
Here START_NOT_STICKY states that you need not recreate service in case it is been killed.
If this is not the case then you have to manually kill it by your self.
Like
Intent lintent = new Intent(context, LocationService.class);
context.stopService(lintent);
You can use this code at point where your application kills.
That's it. You are good to go with this.
First of all, launch the "LocationService" on your app start:
public class MyApp extends Application {
private static final String TAG = "MyApp";
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "App started up");
startService(new Intent(this, MyLocationService.class));
}
}
Second :
As you said, the Service should better run with the "START_NOT_STICKY" flag
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_NOT_STICKY;
}
Thrid:
Once the system kills your app, the Service will automatically be killed, so no problems at all.
There is no onDestroy() method on the Application object, the only similar event is onTerminated() and it is not being launched on production devices.
onTerminate
Added in API level 1 void onTerminate () This method is for use in
emulated process environments. It will never be called on a production
Android device, where processes are removed by simply killing them; no
user code (including this callback) is executed when doing so.
More information:
https://developer.android.com/reference/android/app/Application.html#onTerminate()
Btw, If you want the MyLocationService to send updates of the location to your app (when it is open), you should consider to use Otto or EventBus (I recommend you this last one because of the simplicity to use it). You can even configure the #Suscriber to receive updates of old retrieved locations if you want.
I will try to explain in a easiest way :)
There are two type of service
IntentService and Service
IntentService when started will kill itself once it treated the content of it onHandleIntent method
as for Service well this one will not end until you give it the command to do so even if your start it using the context of an activity. It will also stop when the application is stopped in an extreme case (by system (Settings/application/YourApp/stop app OR an app crash)
Easiest way is First of all start IntentService with AlarmManager at some repeating time (10 mintutes), then in onHandleIntent() get Location and store into preference.
No Need bind to your activity, the IntentService automatically stops itself after saved in preferences.
Yes you can stop the service in onDestroy() of the activity:
#Override
public void onDestroy(){
Log.v("SERVICE","Service killed");
service.stop();
super.onDestroy();
}
I have built an app for running. It runs an Activity with a timer shown in the user interface, a gps listener that collects coordinates and a lot of other things (the activity does a lot of work).
Now the request of my client is to move all the activity logic in a Service. In this way, when you start a running session, the Service would start and the notification (very simple, just with a static text) would appear. The activity should keep track of the work made in the Service (timer should go on, speed should be shown, ecc...). Tapping on the notification should bring up the activity. If the activity is closed or crashes the Service should keep going on and when you tap on the notification a new Activity should be brought up without the user noticing any difference (the timer should keep showing the right time, the average speed should comprehend the speeds relevated before the activity crash, ecc...).
I know there are a lot of ways to do that.
What I am asking is: what is the best way? Are there examples of such behavior from where to start? What are the common errors I should avoid? Are there best practices to follow?
Thank you
I developed an app with similar service behaviour. It also requires a service which collects data and some activities for showing the data.
For these kind of applications you want to keep the service alive until the user stopps it manualy but it is still possible for android that it kills the service if the device is low on memory.
For the service - activity interaction you need to bind to a service. A good documentation is available here: http://developer.android.com/guide/components/bound-services.html
Be sure to return START_STICKY in the onStartCommand function of the service. This will make sure the intent will be null when the service was restored by the system and tell android that you start and stop your service explicit.
When binding to the service from the activity you need to check if the service is ready (was not restored by the system). This can be done by adding a "ready" field inside the service that is false by default and is set to true if the onStartCommand intent is not null. Therefore you can react properly to a restored service and start the app from the beginning.
To keep the service alive with a high priority you need to call startForeground inside the service. This also requires to show a notification so the users knows a service is running in the background.
Inside service you can use local broadcastmanager.
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
broadcaster = LocalBroadcastManager.getInstance(this);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
handler.removeCallbacks(sendUpdatesToUI);
handler.postDelayed(sendUpdatesToUI, 1000);
return START_STICKY;
}
private Runnable sendUpdatesToUI = new Runnable() {
public void run() {
DisplayLoggingInfo(); //do watever you want to push
handler.postDelayed(this, 1000); // 10 seconds
}
};
I have an app that has an Activity, which is used as the regular GUI, and a Service. My activity has two buttons. One button to stop the process and one to kill the process. I use these to methods, respectively, to start and stop my process:
Intent i = null;
Button start;
Button stop;
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
i = new Intent(this, Service.class);
start = (Button) findViewbyId(R.id.start_button);
stop = (Button) findViewById(R.id.stop_button);
start.setOnClickListener(new OnClickListener(){
public void onClick(){
startService(i);
}
}
stop.setOnClickListener(new OnClickListener(){
public void onClick(){
stopService(i);
}
}
}
This Service is not bound to the actvivty or app. I have the service configured in the Manifest as so:
<service
android:name="com.example.mypackage.Service"
android:process=":remote">
<intent-filter>
<action
android:name="com.example.mypackage.Service" />
</intent-filter>
</service>
When I start the Service it runs on it's own independent on anything else. Meaning, when I start the service and onDestroy() the app, the service is still running. I can see it is still running because through adb, I run the ps command and it says it is.
The problem is when I call stopService(intent). When I call stopService(intent) from the activity side, it will run the lines of code set in the onDestroy() of the service, but when I run ps through adb, it says that it's still running.
I want to be able to COMPLETELY destroy the service. I'm not sure how services work, so please, don't hesitate to talk remedial. I'm not sure if it has to do with what I'm doing within the service or not. Thanks!
EDIT:
When I start the service, I use the onStartCommand() and run some code there which it does. I also return START_STICKY from onStartCommand(). I also tried returning START_NOT_STICKY and the service is still running after I call startService(intent).
If you want kill service process forcefully, you can use following code:
Process.killProcess(Process.myPid());
Services are stopped after stopService is called. After stop, they are inactive, but cached.
By android documentation they become an empty process:
A process that doesn't hold any active application components. The only reason to keep this kind of process alive is for caching purposes, to improve startup time the next time a component needs to run in it. The system often kills these processes in order to balance overall system resources between process caches and the underlying kernel caches.
Service will remain in cache until it will be called by you app again or sytem cache will not have room for it to keep. RS command does not know difference between active and cache dprocess and allways shows all awailible processes. This behaviour will maintain if you remove :remote(note that separate process will not be created)
I think you could set android:exported="false" in your manifest so that other apps cannot access the service thereby starting the service. I may need to see the full implementation of your code to fully determine the cause of it. I did the same thing and it is working perfectly well.
I´ve got a background service, which pushes notifications. When you click on the notifications, my activity is opened, but the problem is, the onStartCommand is called then again, which propably could invoke another notification, which means I have a loop.
I´m using
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return Service.START_NOT_STICKY;
}
also tried Service.START_STICKY with no effect.
In my manifest:
<service
android:name=".notification.NotificationService"
android:exported="false"></service>
what could cause a recall of onStartCommand?
Check your Activity code, sounds like your accidentally starting the Service.
There are some situations where this could happen like
it may be killed by the system if it is under heavy memory pressure.
If this happens, the system will later try to restart the service.
There Is another possibility this might happen. If you rotate your device your Activity will be killed and restarted all according to Android official docs Activity . Your Service will be launched again. Read the docs, save some time and headache. On this link Android official docs Activity, scroll down 2 laps and you see a picture of the lifecycle.