Keep alive Service in background? - android

For a demo I print a Toast after Evert 10 sec. using Service class.
It works fine, I'm getting the Toast after every 10 sec if I am on the Activity when I leave the app, Service is not giving the o/p.
But I want to that toast either I'll kill the App or back press Here is code snippet :
ServiceDemo.java
public class ServiceDemo extends Activity {
private Handler myHandler = new Handler();
private Runnable drawRunnable = new Runnable() {
#Override
public void run() {
as();
myHandler.postDelayed(this, 10000);
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_service_demo);
myHandler.postDelayed(drawRunnable, 10000);
startService(new Intent(this, MyService.class));
}
public void as(){
startService(new Intent(this, MyService.class));
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
}
}
Service.java
public class MyService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
Toast.makeText(this, "HOHO Service Created...", Toast.LENGTH_LONG).show();
}
#Override
public void onDestroy() {
}
#Override
public void onStart(Intent intent, int startid) {
Toast.makeText(this, "Service Started...", Toast.LENGTH_LONG).show();
}
}
Edit 1
moveTaskToBack(true);
I put this into the onBackPressed method I Service give the o/p if I am not on the screen but When I kill the App, Service not responding

I think you need to override onStartCommand instead of onStart()
like:
public int onStartCommand(Intent intent, int flags, int startid)
{
Toast.makeText(this, "Service Started...", Toast.LENGTH_LONG).show();
return Service.START_STICKY;
}

i think AlarmManager is what you want.

You have to user AlarmManager, here's an example : Alarm Manager Example
Your task will be executed even if the application is terminated.
But if the application is killed by the user, the Alarm will be canceled. See this discussion How to create a persistent AlarmManager

Related

Android: Run code when application is permanently closed

So I have code that I want called when my application is closed. Not just when it is sent to the background or the surface is destroyed. How do I do this? Is there a method that I can override in a SurfaceView or Activity class?
New Edit - current BackgroundService class:
public class BackgroundService extends Service {
private String savedString;
public void onCreate() {
System.out.println("Service created");
super.onCreate();
}
public int onStartCommand(Intent intent, int flags, int startId) {
System.out.println("start command: ");
savedString = intent.getStringExtra("myString);
return super.onStartCommand(intent, flags, startId);
}
public IBinder onBind(Intent intent) {
return null;
}
public void onTaskRemoved(Intent rootIntent) {
System.out.println("the saved string was: " + savedString);
super.onTaskRemoved(rootIntent);
}
public void onDestroy() {
System.out.println("destroyed service");
super.onDestroy();
}
}
Where I then have this in my other class:
Intent serviceIntent = new Intent(activity.getApplicationContext(), BackgroundService.class);
serviceIntent.putExtra("myString", "this is my saved string");
activity.startService(serviceIntent);
you need to add a background service
public class BackgroundServices extends Service
{
#Override
public void onCreate() {
Toast.makeText(this, "start", Toast.LENGTH_SHORT).show();
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
then in your activity. where you want to trigger this service
use
startService(new Intent(getBaseContext(), BackgroundServices.class));
in your case it will be call on onDestory function of that activity
Yes when the process is terminated
That is not possible in general. Nothing in your app is called when the process is terminated.
For example when you open the running apps screen, and swipe away the app to stop it from running
That is a task removal. It may result in your process being terminated, and there are many ways in which your process can be terminated that has nothing to do with task removal.
To detect task removal, override onTaskRemoved() in a Service.

Run a service in background continuously

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.

How to send data from local service to activity in ANDROID

I have one activity and one service. My requirement is to start service from activity and in activity countdown timer will start, but problem is that I'm unable to get value from service to my activity. Please help me out.
Is any code,tutorial,example which will help me for this.
TIMER SERVICE
public class TimerService extends Service {
MyCounter timer;
#Override
public void onCreate() {
timer = new MyCounter(1 * 60 * 1000, 1000);
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
timer.start();
return super.onStartCommand(intent, flags, startId);
}
private class MyCounter extends CountDownTimer {
public MyCounter(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onFinish() {
Toast.makeText(getApplicationContext(), "death", Toast.LENGTH_LONG)
.show();
stopSelf();
}
#Override
public void onTick(long millisUntilFinished) {
Toast.makeText(getApplicationContext(),
(millisUntilFinished / 1000) + "", Toast.LENGTH_SHORT)
.show();
}
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
timer.cancel();
super.onDestroy();
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
}
what should i write in this service so i will get toast message value in my activity
Read about broadcast receivers.
Create a broadcast receiver in activity and register it with some IntentFilter(Set action in a string value).
private BroadcastReceiver receiver = new BroadcastReceiver() {
public void onReceive(android.content.Context context, Intent intent) {
Toast.makeText(context, "death", Toast.LENGTH_LONG)
.show();
}}
Register in onResume
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("Your Action");
this.registerReceiver(receiver, intentFilter);
And in your service just call setBroadcast
#Override
public void onFinish() {
Intent intent = new Intent();
intent.setAction("YourAction");
sendBroadcast(intent);
stopSelf();
}
You can achieve this in many ways.
A elegant one would be to have a controller class which sends events to your activity.
You could register your Activity as observable in your onResume method and unregister it in the onPause method. Then, send the data from your service to the controller, and it pass the data to your Activity from there. For example:
//Let your activity implement this interface
interface MyObservableActivity{
public receiveData(Data yourData);
}
//Your observer controller
class MyController{
Vector<MyObservableActivity> observedItems;
public void registerObservable(MyObservableActivity a){
if(!observedItems.contains(a))
observedItems.add(a);
}
public void unregisterObservable(MyObservableActivity a){
if(observedItems.contains(a))
observedItems.remove(a);
}
public void sendDataToObservers(Data d){
for(MyObservableActivity a: observedItems){
a.receiveData(d);
}
}
}
So from your service, you should call the sendDataToObservers method and you'll get it from your activity.

Can not close the service when close the background

I write this code in the onDestroy() method.
#Override
public void onDestroy()
{
MessageService.this.stopSelf();
messageThread.isRunning = false;
System.exit(0);
super.onDestroy();
}
And close the service in other Activity.
stopService(new Intent(MainOptionActivity.this,MessageService.class));
I tried many code, it can not close the service when close the background. Could anyone give me some advice? Thanks.
Here is a simple code for service class
public class MyService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
Toast.makeText(getApplicationContext(), "MSG onCreate SERVICE", Toast.LENGTH_LONG).show();
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(getApplicationContext(), "MSG onStartCommand SERVICE", Toast.LENGTH_LONG).show();
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
Toast.makeText(getApplicationContext(), "MSG STOP SERVICE", Toast.LENGTH_LONG).show();
super.onDestroy();
}
}
and here is the code for testing this service
startService(new Intent(this, MyService.class));
new Timer().schedule(new TimerTask() {
#Override
public void run() {
startService(new Intent(getApplicationContext(), MyService.class));
}
}, 5000);
new Timer().schedule(new TimerTask() {
#Override
public void run() {
stopService(new Intent(getApplicationContext(), MyService.class));
}
}, 10000);
this is working just fine. Also add this code in manifest
<service android:name=".MyService" />
Don't use System.exit(0) on Android, instead use finish (in Activity for example).
But there is no need to stop itself onDestroy method, it is actually gonna be stopped and destroyed (that's what onDestroy method is for).
You stop the execution of the method with System.exit(0); and therefore system never reaches super.onDestroy(); point and service is not destroyed.
Try just
#Override
public void onDestroy() {
messageThread.isRunning = false;
super.onDestroy();
}

onDestroy being called but service not ending

I'm following the book 'Beginning Android 4 Development', and I'm controlling a service using the following functions from buttons:
public void startService(View view) {
startService(new Intent(getBaseContext(), QOLService.class));
}
public void stopService(View view) {
stopService(new Intent(getBaseContext(), QOLService.class));
}
QOLService.java includes
public class QOLService extends Service {
int counter = 0;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//Keep running service until stopped, so return sticky
Timer timer=new Timer();
TimerTask tt =new TimerTask() {
#Override
public void run() {
Log.d("QOLService", String.valueOf(++counter));
}
};
timer.scheduleAtFixedRate(tt, 0, 1000);
Toast.makeText(this, "Service started", Toast.LENGTH_LONG).show();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service destroyed", Toast.LENGTH_LONG).show();
}
As intended, on pressing the start button I get the 'service started' toast, and in logcat I get a message incrementing every second. This continues, as intended, even when the application is closed.
When I click the stopservice button, I also get the expected 'service destroyed' message, but the timer lives on! If I close the application it still keeps going. If I click the stopservice button again, it does NOT given the service destroyed message, as if it had been successfully destroyed the first time.
Am I calling my timer inappropriately? If so, I seem to be doing it exactly as the book advises!
Am I calling my timer inappropriately?
You are never stopping the timer. Hence, it will keep running until the process is terminated. You should stop the timer in onDestroy().
I am agree with CommonsWare, You haven't stop your timer in the code. I suggest you to go this way,
public class QOLService extends Service {
int counter = 0;
Timer timer;
TimerTask tt;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//Keep running service until stopped, so return sticky
timer=new Timer();
tt =new TimerTask() {
#Override
public void run() {
Log.d("QOLService", String.valueOf(++counter));
}
};
timer.scheduleAtFixedRate(tt, 0, 1000);
Toast.makeText(this, "Service started", Toast.LENGTH_LONG).show();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service destroyed", Toast.LENGTH_LONG).show();
tt.cancel();
timer.cancel();
}
}
The cancel() method will stop your Timer as well as.
It might be because the system is trying to restart your service because you are returning START_STICKY from onStartCommand. Try returning START_NOT_STICKY instead.

Categories

Resources