I have an Activity that calls startService() in the onCreate() with some params.
The Service works well (I use a Timer) but when I quit the Activity (onPause() or onDestroy()) what happens is that the Service is recreated! It calls onCreate then onStartCommand() with a null intent! (normal)
So how should I do to retrien the old intent?!
I think there's START_REDELIVER_INTENT but how to use it! Is this the right way?
PS: Why the is the Service killed although it extends Service? Does it depend on Lifecycle of the activity => so who called him again?
public class MyService extends Service {
private static Timer timer = new Timer();
#Override
public void onCreate() {
Log.d(TAG, "onCreate");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(intent != null){
Bundle bundle = intent.getExtras();
if (bundle != null)
{
timer.scheduleAtFixedRate(new Action(),15000 , 15000);
}
}
Action() {
timer = new Timer();
timer.scheduleAtFixedRate(new Action(),15000 , 15000);
}
}
Try to use intentService instead of service
After some research i found the solution and it maybe simple for some, so with reading this: START_STICKY and START_NOT_STICKY and that we won't the service restart itself we should return on the onCommand method START_NOT_STICKY
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//TODO
return START_NOT_STICKY ;
}
Related
I successfully used a service to do a certain task in the foreground. Now, to do it in the background, I'd remove the handler.removeCallbacks method in onDestroy().
But this would also prevents me from stopping the service using stopService(intent).
I saw on the official docs that I should maybe use JobScheduler (as I target API 28).
Here is a more precise indication of my code :
public class MainActivity {
private Intent intent;
onCreate() {
if (intent == null) {
intent = new Intent(this, MyService.class);
}
}
startService(intent);
... // Then is some code to stop the service if needed with stopService(intent)
}
--------------------------------------------------------------
public class myService {
private Handler handler = null;
private static Runnable runnable = null;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
handler = new Handler();
runnable = new Runnable() {
#Override
public void run() {
System.out.println("Running service times " + i);
i++;
handler.postDelayed(runnable, 1000);
}
};
handler.post(runnable);
}
#Override
public void onDestroy() {
handler.removeCallbacks(runnable);
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
I would like it to run in the background (even if the device is locked) but still being able to disable the service (or JobScheduler?).
What are your suggestions?
you can use work manager
or job dispatcher
and there is a lot of options like
SyncAdapter, Bound services, Intent Service
you can use one of these options according to your need
Run a service in background continuously. For example, a service has to be kicked off which will display a toast message 20 seconds once even if the app is closed.
public class AppService extends IntentService {
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
public AppService() {
super("AppService");
}
#Override
protected void onHandleIntent(Intent workIntent) {
Toast.makeText(getApplicationContext(), "hai", Toast.LENGTH_SHORT).show();
SystemClock.sleep(20000);
}
}
Below code works for me...
public class AppService extends Service {
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
Toast.makeText(this, " MyService Created ", Toast.LENGTH_LONG).show();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, " MyService Started", Toast.LENGTH_LONG).show();
return START_STICKY;
}
}
Accepted answer will not work on from Android 8.0 (API level 26), see the android's background limitations here
Modification in Accepted Answer:
1: You have to invoke the service's startForeground() method within 5 seconds after starting the service. To do this, you can call startForeground() in onCreate() method of service.
public class AppService extends Service {
....
#Override
public void onCreate() {
startForeground(9999, Notification())
}
....
}
2: You must call startForegroundService() instead of startService() by checking API level from where you want to start the service.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(intent);
} else {
context.startService(intent);
}
This code work for me..
public class ServiceClass extends Service {
public static final int notify = 300000; //interval between two services(Here Service run every 5 Minute)
private Handler mHandler = new Handler(); //run on another Thread to avoid crash
private Timer mTimer = null; //timer handling
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onCreate() {
if (mTimer != null) // Cancel if already existed
mTimer.cancel();
else
mTimer = new Timer(); //recreate new
mTimer.scheduleAtFixedRate(new TimeDisplay(), 0, notify); //Schedule task
}
#Override
public void onDestroy() {
super.onDestroy();
mTimer.cancel(); //For Cancel Timer
Log.d("service is ","Destroyed");
}
//class TimeDisplay for handling task
class TimeDisplay extends TimerTask {
#Override
public void run() {
// run on another thread
mHandler.post(new Runnable() {
#Override
public void run() {
Log.d("service is ","running");
}
});
}
}
}
In your manifest, where you declare your service, add:
android:process=":processname"
This lets the service run on a separate process and thus it will not be killed with the app.
You can then chose if you want to use foreground. It will show a persistent notification, but reduces the likelihood if the service being killed.
Further, if you want to create a continuously running service, use Service, NOT IntentService. IntentService stops when it is finished doing its action.
I'm currently working on my first android app and I've run into a problem.
My app is supposed to be counting in the background using a Service and I'm creating a new thread to handle that. If I don't stop the thread in my Service's onDestroy() method, my phone gives me the message "Unfortunately, (my app) has stopped." every time I close the app. I need to stop it somehow, and I tried to do it using :
while(!Thread.currentThread().isInterrupted()){
**my code**
}:
And then interrupting it in the onDestroy() method.
It works, but it makes my app count extremely fast, so I would like to know if it can be done any other way that does not change the functionaliy of my code.
Also, since my thread gets stopped in the onDestroy method, I guess my service stops as well. Is there any way to keep my service running even when my app has been closed?
Here's my code:
public class CounterService extends Service {
private Handler handler;
private int time = -1;
private boolean isActive;
private Intent timeBroadcaster;
private Runnable counter;
private Thread serviceCounter;
#Override
public void onCreate(){
super.onCreate();
handler = new Handler();
timeBroadcaster = new Intent();
timeBroadcaster.setAction("EXAMPLE_BROADCAST");
counter = new Runnable() {
#Override
public void run() {
isActive = ((PowerManager) getSystemService(Context.POWER_SERVICE)).isInteractive();
if (isActive) {
handler.postDelayed(this, 1000);
time += 1;
} else {
if (time > 5) {
//log
}
time = 0;
handler.postDelayed(this, 1000);
}
timeBroadcaster.putExtra("counter", time);
sendBroadcast(timeBroadcaster);
}
};
serviceCounter = new Thread(counter);
serviceCounter.start();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy(){
//serviceCounter.interrupt();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
Is there any way to keep my service running even when my app has been closed?
you can use sync adapter which runs in background even app is stoped.
https://developer.android.com/training/sync-adapters/creating-sync-adapter.html
I create Service and call it from MainActivity.class with put string extra to intent but when I call getStringExtra in onStartCommand, it returns NullPointerException
Here is my code:
MainService.class :
public class MainService extends Service {
private WindowManager wm;
private WindowManager.LayoutParams params;
#Override
public IBinder onBind(Intent i) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDestroy() {
super.onDestroy();
if (mView != null) {
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
wm.removeView(mView);
}
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
final String quote = intent.getStringExtra("quote");
Log.d("datastring",quote);
return super.onStartCommand(intent, flags, startId);
}
}
In MainActivity.class I called :
Intent i=new Intent(MainActivity.this, MainService.class);
i.putExtra("quote", "dataquote");
stopService(i);
How I can get string from MainActivity in MainService?
If you want to provide more data to your Service you need to use something like:
Intent intent = new Intent(MainActivity.this, MainService.class);
intent.putExtra("quote", "dataquote");
startService(intent);
This will start the service and you should be able to get the data intent in the onStartCommand(). If the Service is already running, onStartCommand() will still be called with the new intent. This is because Service components are inherently singleton, so only one instance of a particular service run at a time.
In your case, you are providing the data via stopService(intent). Not only its not possible to get this intent, your Service will also stop after this statement so, you cannot really do much with the data even if you could have read it.
If you still need to stop your Service and pass data at the same time, you should check this post.
I hava a simple service with data - ArrayList < MyObject > , when I close the app - service is restarted, called onCreate method and data is losing. This is my onStartCommand method:
public int onStartCommand(Intent intent, int flags, int startId) {
.....
return START_STICKY;
}
Service start in Application class
Intent serviceIntent = new Intent(this, ChatNotificationService.class);
startService(serviceIntent);
I not called stopService method.
I need after closing the application, the service continued to work and the data saved in it.
How I can do it?
In activity:
#Override
protected void onCreate() {
super.onCreate();
bindService(serviceIntent, sConn, 0);
}
#Override
public void onDestroy(){
super.onDestroy();
chatNotificationService.closeConnections();
unbindService(sConn);
}