I have read this answer and it's not useful in my case.
I have create a simple service, it does nothing but logs method names. I run it from my activity and kill it by using
adb shell am stopservice -n serviceComponent
onDestroy() is called on service. Now as I have returned Service.START_STICKY from onStartCommand(); I wait for the system to restart
the service and it never restarts.
Is this the right behavior? I have gone through this issue but couldn't find a reliable answer.
public class SampleService extends Service {
private static final boolean LOG = true;
public static final String CALLER = "sample.service.caller";
/**
* called once when service is created.
*/
#Override
public void onCreate() {
super.onCreate();
if(LOG){
log("onCreate() -> thread: %s", Thread.currentThread().getName());
}
} // onCreate
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(LOG){
log(">>>>>> onStartCommand()");
}
if(LOG){
log("thread: %s", Thread.currentThread().getName());
}
if(LOG){
log("caller[%s]", intent.getStringExtra(CALLER));
}
if(LOG){
log("<<<<<< onStartCommand()");
}
return Service.START_STICKY;
} // onStartCommand
#Override
public void onDestroy() {
super.onDestroy();
if(LOG){
log("onDestroy() -> thread: %s", Thread.currentThread().getName());
}
Toast.makeText(this, "destroying", Toast.LENGTH_SHORT).show();
} // onDestroy
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
} // onBind
private void log(String format, Object... args){
Utils.log("SampleService", String.format(format, args));
} // log
} // SampleService
Here is what I have tried so far
I start the service by calling using this code
Intent intent = new Intent(this, SampleService.class);
intent.putExtra(SampleService.CALLER, "main activity");
if(null == startService(intent)){
if(LOG){
log("startService -> %s", "service not found!");
}
} //
After starting service, adb shell dumpsys activity services | grep "com.mallaudin" returns this
ServiceRecord{8bc884d u0 com.mallaudin.services/.SampleService}
intent={cmp=com.mallaudin.services/.SampleService}
packageName=com.mallaudin.services
processName=com.mallaudin.services
baseDir=/data/app/com.mallaudin.services-2/base.apk
dataDir=/data/user/0/com.mallaudin.services
app=ProcessRecord{b1c1c5a 32017:com.mallaudin.services/u0a94}
Now I stop service by invoking adb shell am stopservice -n com.mallaudin.services/.SampleService. It stops the service and onDestroy is
called. Same behaviour is observe when I kill the service from services list in my phone.
Stopping service: Intent { cmp=com.mallaudin.services/.SampleService }
Service stopped
When I use adb shell force-stop com.mallaudin.services command, service is stopped but onDestroy() is not called.
START_STICKY documentation:
... if this service's process is killed while it is started...
adb shell am stopservice and context.stopService(Intent) don't actually kill the service process, but rather just stops the service while keeping the app process running. So the system won't restart the service in this case.
You can try the following: create an app with an Activity and a Service. Then start the activity, start the service, and kill the app by sliding it from the overview screen (aka the recents menu). Your service should restart.
Related
i'm trying to create an app that communicates with my localhost and search in a database.
I already make the connection and find the data, but i need to stay connected and send a notification if there's any changes in the table, but I can't figure it out how to keep the connection even when I close the app, because it closes everything, even the service.
The service doesn't stay open.
This is my Class:
public class SensorService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
Toast.makeText(this,"Starting",Toast.LENGTH_SHORT).show();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
boolean bandera = true;
Toast.makeText(this, "Checking data...", Toast.LENGTH_SHORT).show();
return START_STICKY;
}
#Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
stopService(new Intent(this,SensorService.class));
startService(new Intent(this,SensorService.class));
}
#Override
public void onDestroy() {
startService(new Intent(this,SensorService.class));
}
}
Every time I close the app, the service execute one more time and no more.
If you want the service to continue running after the app is closed, you need to call the startForeground(int, Notification) method from within the service. Android limits you to running longer running services in the background only as long as a notification is displayed to the user letting them know that a service is running (like a music player or a downloading service).
This is an intentional design constraint to ensure developers do not start services in the background that run indefinitely without the user being aware. Supply your own notification (can be anything) and you should be able to run the service in the background.
For more detailed information on this method, read it at: startForeground(int, Notification)
You can use onTaskRemoved and restart the service if needed.
#Override
public void onTaskRemoved(Intent rootIntent){
super.onTaskRemoved(rootIntent);
//restart your service
}
Please note that if you use onTaskRemoved, start your service as not sticky so it won't be restarted.
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
return START_NOT_STICKY;
}
I started a foreground service with a notification id however when i try to call stopForeground(false) the service is getting restarted. But according to the android docs calling this method does not stop the service.
#Override
public void onCreate() {
LogHelper.d(TAG, "onCreate");
super.onCreate();
initMediaSeesion();
}
#Override
public int onStartCommand(Intent startIntent, int flags, int startId) {
LogHelper.d(TAG, "onStartCommand");
MediaButtonReceiver.handleIntent(mSession, startIntent);
return START_STICKY;
}
public void startNotification() {
if (!mStarted) {
Notification notification = createNotification();
if (notification != null) {
mService.startForeground(NOTIFICATION_ID, notification);
mStarted = true;
}
}
}
#Override
public void pause() {
LogHelper.d(TAG, "Calling stopForeground false");
giveUpAudioFocus();
mService.stopForeground(false);
}
Logs:
03-25 08:50:40.200 19564-19564/? D/MusicService: Calling stopForeground false
03-25 08:50:40.352 19564-19564/? D/MusicService: onCreate
03-25 08:50:40.475 19564-19564/? D/MusicService: onStartCommand
03-25 08:50:40.476 19564-19564/? D/MusicService: onStartCommand
Because you set START_STICKY when you stop the service it automatically restart.
This is what Android DOC says
For started services, there are two additional major modes of operation they can decide to run in, depending on the value they return from onStartCommand(): START_STICKY is used for services that are explicitly started and stopped as needed, while START_NOT_STICKY or START_REDELIVER_INTENT are used for services that should only remain running while processing any commands sent to them. See the linked documentation for more detail on the semantics.
Try using stopSelf();
I am trying to learn service in android.My goal is like that i will pass a LatLng Object to the service then service will do something with that and when the work will be finished then it will buzz the phone for sometime and stop.Finally the service will be finished.Now I have some query on that:
I will call the service from my app and user can close my app though
service is not finished.will service do the job initiated by my app or
it will also finish??
What i studied take me here that service will continue to execute and one thing i don't have to return anything back to activity who has initiated the service.I have written some code.Can anyone help me out??
public class MapService extends Service {
private boolean isRunning = false;
#Override
public void onCreate() {
Log.i(TAG, "Service onCreate");
isRunning = true;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "Service onStartCommand");
//Creating new thread for my service
//Always write your long running tasks in a separate thread, to avoid ANR
new Thread(new Runnable() {
#Override
public void run() {
//here i will do my work
if(isRunning){
Log.i(TAG, "Service running");
}
}
//Stop service once it finishes its task
stopSelf();
}
}).start();
return Service.START_STICKY;
}
#Override
public IBinder onBind(Intent arg0) {
Log.i(TAG, "Service onBind");
return null;
}
#Override
public void onDestroy() {
isRunning = false;
Log.i(TAG, "Service onDestroy");
}
}
Will it work if user closes the app??
Yes this service will run even if user will close app.It is also possible if android system demands memory service will be stopped but it will restart again
as you have set your flag START_STICKY in your onStartCommand.
On Android KitKat and above(4.4+), the service will be stopped if user swipe kills the application and it won't be restarted by the system. See this discussion(1). If the application was stopped by Android system itself (for low resources), the service will be restarted after a while(use START_STICKY flag).
On Android 4.3 and below, service will be restarted irrespective of whether application was stopped by system or user(use START_STICKY flag).
#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;
}
I am facing a critical issue with binded service running as foreground and with notification. I am doing everything correct as mentioned by most of the tutorials and solutions I found. I have an activity which starts a service and then bind with it. In onCreate() of service, i am using startForeground() and showing notification as well. I am also returning START_STICKY in onStartCommand() but when my application gets killed i see this in my log cat ..
Force stopping package com.example.voicerecognizersp appid=10102 user=0
I/ActivityManager( 929): Killing proc 27176:com.example.voicerecognizersp/u0a10102: force stop com.example.voicerecognizersp
W/ActivityManager( 929): Scheduling restart of crashed service com.example.voicerecognizersp/.RecordingMfccService in 5000ms
I/ActivityManager( 929): Force stopping service ServiceRecord{453068e0 u0 com.example.voicerecognizersp/.RecordingMfccService}
Service is trying to restart but gets force stopped. I want service to restart if app gets killed for any reason. I know its a binded service and runs in the same process as activity but to fix it, i am already calling startService before bind and using foreground to reduce max chances of getting killed. Can anyone explain still why service gets force stopped when its trying to restart ?
My main chunk of Service class looks like this
#Override
public void onCreate() {
Log.d(TAG, "onCreate called");
mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
// Display a notification about us starting. We put an icon in the status bar.
runAsForeground();
}
/**
* Show a notification while this service is running and run as foreground so
* that OS knows that Activity depends on service and service is not a candidate
* to be killed
*/
//http://stackoverflow.com/a/28144499/1016544
private void runAsForeground() {
Intent notificationIntent = new Intent(this, MainBindingActivity.class);
PendingIntent pendingIntent=PendingIntent.getActivity(this, 0, notificationIntent, Intent.FLAG_ACTIVITY_NEW_TASK);
Notification notification=new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("VoiceRecognizerSP")
.setContentText("Service is running ...")//.build();
.setContentIntent(pendingIntent).build();
startForeground(NOTIFICATION, notification);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
int rc = super.onStartCommand(intent, flags, startId);
Log.i("LocalService", "onStartCommand Received start id " + startId + ": " + intent + "rc : " + rc );
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
//return START_REDELIVER_INTENT;
}
#Override
public void onDestroy() {
super.onDestroy();
// Cancel the persistent notification.
mNM.cancel(NOTIFICATION);
Log.d(TAG, "Service onDestroy() called");
}
/**
* Class used for the client Binder. Because we know this service always
* runs in the same process as its clients, we don't need to deal with IPC.
*/
public class LocalBinder extends Binder {
RecordingMfccService getService() {
Log.d(TAG, "getService done");
// Return this instance of LocalService so clients can call public methods
return RecordingMfccService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind called");
return mBinder;
}
#Override
public void onRebind(Intent intent) {
Log.d(TAG, "onRebind called");
super.onRebind(intent);
}
#Override
public boolean onUnbind(Intent intent) {
Log.d(TAG, "onUnbind called");
return true; //to make sure next time onRebind is called
}
I am starting service and binding in onCreate() of Activity
if(!isMyServiceRunning())
{
startService(new Intent(this,RecordingMfccService.class));
}
boolean result = bindService(new Intent(this, RecordingMfccService.class), mConnection, Context.BIND_AUTO_CREATE);
LocalBroadcastManager.getInstance(this).registerReceiver((receiver), new IntentFilter(RecordingMfccService.COPA_RESULT));
if(!result)
throw new RuntimeException("Unable to bind with service in onCreate");
and unbinding in onDestroy()
if (isBound ) {
Log.i(TAG, "Unbind called");
unbindService(mConnection);
isBound = false;
//Log.i(TAG, "onStopRecording Service unbinded & isbound : " + isBound);
//needToBind = true;
LocalBroadcastManager.getInstance(getApplicationContext()).unregisterReceiver(receiver);
}
On click of a button I want to start service using method startService(new Intent(currentActivity.this,MyService.class)) but if service is running I don't want to call this method to avoid run service that is already running.How this is possible.I am using both Intent service and Service in same project and want to apply same condition for both.
A service will only run once, so you can call startService(Intent) multiple times.
You will receive an onStartCommand() in the service. So keep that in mind.
Source:
Note that multiple calls to Context.startService() do not nest (though they do result in multiple corresponding calls to onStartCommand()), so no matter how many times it is started a service will be stopped once Context.stopService() or stopSelf() is called; however, services can use their stopSelf(int) method to ensure the service is not stopped until started intents have been processed.
At: http://developer.android.com/reference/android/app/Service.html on topic: Service Lifecycle
Use startService().
Start Service will call onStartCommand() If the Service isn't started yet it will Call onCreate(). Initialize your variables and/or start a Thread in onCreate().
Bind your service; when starting call:
Intent bindIntent = new Intent(this,ServiceTask.class);
startService(bindIntent);
bindService(bindIntent,mConnection,0);
Then to check if your service is working, use a method like:
public static boolean isServiceRunning(String serviceClassName){
final ActivityManager activityManager = (ActivityManager)Application.getContext().getSystemService(Context.ACTIVITY_SERVICE);
final List<RunningServiceInfo> services = activityManager.getRunningServices(Integer.MAX_VALUE);
for (RunningServiceInfo runningServiceInfo : services) {
if (runningServiceInfo.service.getClassName().equals(serviceClassName)){
return true;
}
}
return false;
}
Whenever we start any service from any activity , Android system calls the service's onStartCommand() method And If the service is not already running, the system first calls onCreate(), and then it calls onStartCommand().
So mean to say is that android service start's only once in its lifecycle and keep it running till stopped.if any other client want to start it again then only onStartCommand() method will invoked all the time.
So, for avoiding restarting a task again and again, You can use boolean values, that the task is already started or ongoing. Put the method both in oncreate and onstartCommand, and checked with the boolean:
boolean isTimerTaskRunning = false;
private boolean isServiceKeepRunning(){
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
return settings.getBoolean("silentModeKeepRunning", true);
}
#Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate: Called");
Log.i(TAG, "onCreate: keepRunning "+isServiceKeepRunning());
if(!isTimerTaskRunning) {
startTimerTask();
isTimerTaskRunning = true;
}
//startForeground(REQUEST_CODE /* ID of notification */, notificationbuilder().build());
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
localData = new LocalData(this);
// return super.onStartCommand(intent, flags, startId);
Log.i(TAG, "onStartCommand: Called");
Log.i(TAG, "onStartCommand: keepRunning "+isServiceKeepRunning());
Toast.makeText(this, "This is The Mode For Silent. ", Toast.LENGTH_LONG).show();
if(!isTimerTaskRunning) {
Log.i(TAG, "TimerTask was not Running - started from onStartCommand");
startTimerTask();
isTimerTaskRunning = true;
}else {
Log.i(TAG, "TimerTask was already Running - checked from onStartCommand");
}
//return START_REDELIVER_INTENT;
startForeground(REQUEST_CODE /* ID of notification */, notificationbuilder().build());
return START_STICKY;
}