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();
Related
I've created a service that its job is to clear the notifications when the app is closed by the user. Everything works perfectly well but sometimes when the application is in the background for more than 1 minute the service is killed (which means that the notifications are not cancelled).
Why is this happening? I thought that the only way that you can stop a service is by using either stopSelf() or stopService().
public class OnClearFromRecentService extends Service {
private static final String TAG = "onClearFromRecentServic";
private NotificationManagerCompat mNotificationManagerCompat;
#Override
public void onCreate() {
super.onCreate();
mNotificationManagerCompat = NotificationManagerCompat.from(getApplicationContext());
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "Service Started");
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "Service Destroyed");
}
#Override
public void onTaskRemoved(Intent rootIntent) {
//Put code here which will be executed when app is closed from user.
Log.d(TAG, "onTaskRemoved was executed ");
if (mNotificationManagerCompat != null) {
mNotificationManagerCompat.cancelAll();
} else {
Log.d(TAG, "onTaskRemoved: mNotifManager is null!");
}
stopSelf();
}
}
I start the service from the splash screen Activity like this: startService(new Intent(this, OnClearFromRecentService.class));
Also here are some Log messages:
Try returning START_STICKY form onStartCommand.
Then system will try to recreate.
check this official doc.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "Service Started");
return START_NOT_STICKY;
}
Also you can try returing START_REDELIVER_INTENT,if you also want Intent to be re-delivered.
START_REDELIVER_INTENT
Constant to return from onStartCommand(Intent, int, int): if this
service's process is killed while it is started (after returning from
onStartCommand(Intent, int, int)), then it will be scheduled for a
restart and the last delivered Intent re-delivered to it again via
onStartCommand(Intent, int, int).
From docs.
I found a solution with the help of #emandt.
I just added these lines of code in onStartCommand() :
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "Service Started");
Notification notification = new NotificationCompat.Builder(this, CHANNELID)
.setContentTitle("title")
.setContentText("text")
.setSmallIcon(R.drawable.baseline_pause_white_24)
.build();
startForeground(2001,notification);
return START_NOT_STICKY;
}
According to docs the startForeground method :
If your service is started then also make this service run in the foreground, supplying the ongoing notification to be shown to the user while in this state...By default started services are background, meaning that their process won't be given foreground CPU scheduling (unless something else in that process is foreground)
Also,
If your app targets API level 26 or higher, the system imposes restrictions on using or creating background services unless the app itself is in the foreground. If an app needs to create a foreground service, the app should call startForegroundService(). That method creates a background service, but the method signals to the system that the service will promote itself to the foreground. Once the service has been created, the service must call its startForeground() method within five seconds.
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 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 noticed that Service.START_STICKY doesn't work and when I tokk a closer look, I saw the onCreate() is running but onStartCommand is not called.
Any ideas why?
#Override
public void onCreate() {
mGlobalData = GlobalData.getInstance();
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if (mTimer == null)
mTimer = new Timer();
Log.e(TAG, "onCreate()");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
int t = START_STICKY;
Log.e(TAG, "call me redundant BABY! onStartCommand service");
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return t;
}
If you have the same situation I had, my Service starts up and runs just fine (onCreate() and onServiceConnected() are both invoked) but onStartCommand(Intent,int) was never called. I found it's because the system started my Service instead of me explicitly starting the Service in code. According to the docs:
[onStartCommand(Intent,int) is] called by the system every time a client explicitly starts the service by calling startService(Intent)
So I had to call startService(new Intent(context, MyService.class)) explicitly in code to get onStartCommand(Intent,int) to trigger. Note that doing this will not restart the Service created by the system and it won't create a new instance of that Service either.
Try to insert the line android.os.Debug.waitForDebugger(); at the end of onCreate(). The debugger didn't reach onStartCommand()'s breakpoints for me until I did this.
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;
}