Android kill service when app relauch and close? - android

I have to run a task in background when reach the scheduled time.i assigned the task of waking up my service to Alarm Manager and it does well if the app is background/running.service keep running fine on app's background as well as foreground states if am not changing the state of app after beginning the service.for the purpose of well understanding the scenario's given below.
Case 1:
1.Setting up the schedule and sending the time to alarm manager and keep the app running.
2.Alarm manager calls the service when the time is reaching.
3.Service start running
4.when i close my app service get stopped
Case 2:
1.Setting up the schedule and sending the time to alarm manager and closing the app.now app in background.
2.Alarm manager calls the service when the time is reaching.
3.Service start running
4.Relaunching the app.service continuing running/working fine.
5.Now closing the app and the result is service dead.
I have to call the service only by Alarm Manager , not on every time when app launches for that purpose in service onStartCommand method i returned START_NOT_STICKY and i don't want to use START_STICKY.if i goes to START_STICKY it won't consider the scheduled time.and the thing is i don't want to check the time again as it's doing well by Alarm Manager.
When app running on low memory the services get destroyed.is the solution using startForeground instead of startService ?
How can i make my service running stable without bothering about the app opening/closing states ?
Setting schedule
public void setAction(View v) {
Calendar calendar = Calendar.getInstance();
int hour = Integer.parseInt(HH.getText().toString());
int minute = Integer.parseInt(MM.getText().toString());
int second = Integer.parseInt(SS.getText().toString());
String peried = PP.getText().toString();
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.SECOND, second);
calendar.set(Calendar.AM_PM, peried.equalsIgnoreCase("AM") ? Calendar.AM : Calendar.PM);
Intent myIntent = new Intent(MainActivity.this, MyReceiver.class);
myIntent.putExtra(ACTION,
ACTION_SC_1);
pendingIntent = PendingIntent.getBroadcast(MainActivity.this, REQUEST_CODE_SC_1, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC, calendar.getTimeInMillis(), pendingIntent);
}
Service class
public class MyService extends Service {
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
final String action = intent.getStringExtra(ACTION);
final Handler handler = new Handler();
final Timer timer = new Timer();
final TimerTask doAsynchronousTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
try {
Toast.makeText(MyAlarmService.this, "Running....", Toast.LENGTH_LONG).show();
} catch (Exception e) {
// TODO Auto-generated catch block
}
}
});
}
};
timer.schedule(doAsynchronousTask, 1000, 5000); //execute in every 5000 msdo
// this.stopSelf();
} catch (Exception e) {
//TODO
}
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Toast.makeText(this, "Killed", Toast.LENGTH_LONG).show();
}

There are many ways to avoid killing of service...but we can not guarantee it. In low memory situations the service will be killed by the os. At this situation if you return START_STICKY this will restart the service with null intent. If you want the intent to be not null return START_REDELIVER_INTENT
See the android docs here

Related

I have an android background service that keeps on being called

I have a background service to be called everyday at 1pm. At 1 pm, 3 values in my Firebase database should be set to 0. When the user launches a certain activity the background service is triggered. The values reset to 0 at 1pm like i want but, every time after 1pm when the activity is launched by the user the service runs resetting my values. How can I get the values reset to 0 at 1pm and not again until 1pm the next day?
Below is my code within the Service class
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 13);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
timer = new Timer();
timer.schedule(new TimerTask()
{
#Override
public void run()
{
String id = FirebaseAuth.getInstance().getCurrentUser().getUid();
FirebaseDatabase.getInstance().getReference().child("Users").child(id).child("steps").setValue(0);
FirebaseDatabase.getInstance().getReference().child("Users").child(id).child("bonusScore").setValue(0);
FirebaseDatabase.getInstance().getReference().child("Users").child(id).child("stepsScore").setValue(0);
}
}, calendar.getTime(), TimeUnit.MILLISECONDS.convert(1, TimeUnit.DAYS));
return START_STICKY;
}
#Override
public void onDestroy()
{
super.onDestroy();
}
This is the Code starting the service. This method is called in the oncreate method of this activity.
private void startBackgroundService()
{
startService(new Intent(this, BackgroundService.class));
}
you can use work manager to schedule a task.here you can find getting started guide......

Callback listener when application is killed from recent applications in android

Let me come straight to my issue.
There is an old similar question:
Continue Service even if application is cleared from Recent app. Please go through the link before going ahead.
I have to save some data to the local database before the application is destroyed completely.
I have following issues with onTaskRemoved() method of the service:
onTaskRemoved() method is not triggered every time the application(and hence the service) is stopped from the recent applications screen.
Even if onTaskRemoved() is called every time, the method is not executed completely. I mean if there are 20 statements in the method, only 5 or 10 statements are executed and the method breaks after that. Like if I have 20 System.out.println() statements than only 5 or 10 or 12(any random number) statement prints and method breaks after that.
So I can rely on the method onTaskRemoved() method for cleaning up resources acquired by the application.
This is a blocking issue for my application release. I have tried every trick. Like having at least one activity in the stack(I am calling it GhostActivity) so that if the application is killed from the recent applications screen, we can do clean up in onDestroyed() method the activity. onDestroyed() is called but it has exact same issues like onTaskRemoved() method.
I am stuck on the issue since weeks and it's very annoying. Please let me know if anyone has any solution.
I finally myself got it worked. I used a combination of service and alarm manager. Every-time I want to handle the force close scenario, I start a service in which I run an infinite loop. This loop will iterator every 15 secs. In the loop, I set an alarm 20 secs from the current time. Now if the next iteration of the loop happens the alarm is updated and reset to 20 secs after new current time. In this way, the alarm will trigger only if the service was not destroyed by the user by calling stopService() method.
public class MyIntentService extends IntentService {
public MyIntentService() {
super("My IntentService");
}
private boolean stopped = false;
private Thread runningThread;
private static MyIntentService mInstance;
#Override
public void onCreate() {
super.onCreate();
mInstance = MyIntentService.this;
}
#Override
public int onStartCommand(#Nullable Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
#Override
protected void onHandleIntent(Intent intent) {
stopped = false;
runningThread = Thread.currentThread();
while(!this.stopped) {
Intent intent = new Intent("Your_Custom_Broadcast_Action");
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
PendingIntent broadcastIntent = PendingIntent.getBroadcast(WifiService.this, CLEAN_UP_ALARM_REQUEST_CODE,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 20000, broadcastIntent);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 20000, broadcastIntent);
} else {
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 20000, broadcastIntent);
}
try {
Thread.sleep(15000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
#Override
public void onDestroy() {
super.onDestroy();
mInstance = null;
if (runningThread != null) {
runningThread.interrupt();
}
}
public void stopService() {
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
PendingIntent broadcastIntent = PendingIntent.getBroadcast(WifiService.this, CLEAN_UP_ALARM_REQUEST_CODE,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.cancel(broadcastIntent);
stopped = true;
if (runningThread != null)
runningThread.interrupt();
}
public static MyIntentService getActiveInstance() {
return mInstance;
}
}

Run upload process in background even when phone is asleep

So I have developed an android application that determines the user's location every 5 seconds using the fused location (LocationClient), and send this data to my server. This whole process repeats itself every 5 seconds when the app is running. I am uploading the data in background using AsyncTask class.
The Problem:
Data uploading stops when user closes the app or when the phone is put to sleep.
What I want:
I want the app to continuously send location data to my server even when the user closes the app or when the phone is asleep. This process should run on a seperate thread as I don't want this process to make my UI thread unresponsive.
What I found till now:
I have heard of services, intentservices and alarmmanager but I don't know which one to use. I also heard of wakelocks to force the CPU not to sleep. Remember I don't want to keep the screen ON all the time as this will drain the battery.
How can I make my app send data to server all the time ?
Here you can create one Service and call this service with AlarmManager at every 5/10 seconds as per your need...
In your MainActivity
public static AlarmManager alarm;
public static PendingIntent pintent;
// write this code on button click
Calendar cal = Calendar.getInstance();
cal.add(Calendar.SECOND, 10);
Intent intent = new Intent(this, MyService.class);
pintent = PendingIntent.getService(this, 0, intent, 0);
alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 5000, pintent);
// button click functionality over
// write this code outside onCreate()
protected ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
}
#Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
};
MyService
public class MyService extends Service {
public static int counter = 0;
public MyService() {
}
#Override
public IBinder onBind(Intent intent) {
return new Binder() ;
}
#Override
public void onCreate() {
Toast.makeText(this, "First Service was Created", Toast.LENGTH_SHORT).show();
}
#Override
public void onStart(Intent intent, int startId) {
counter++;
Toast.makeText(this, " First Service Started" + " " + counter, Toast.LENGTH_SHORT).show();
}
#Override
public void onDestroy() {
Toast.makeText(this, "Service Destroyed", Toast.LENGTH_SHORT).show();
}
public void onTaskRemoved (Intent rootIntent){
MainActivity.alarm.cancel(MainActivity.pintent);
this.stopSelf();
}
Add this to
manifest
<application
....
<activity
.....
</activity>
<service
android:name=".MyService"
android:enabled="true"
android:exported="true" >
</service>
</application>
you can create a service lunched by your application. It will work in the background , and keep working until the user close it from the task-manager (if you don't call onDestroy in your code).

Service to create a notification everyday at a specified time

I want my app to show a notification with a "GOOD MORNING" message at 6 A.M everyday. As I read, for this I need the app to run in background so I need to use Service.
I have tried the following code but I'm stuck.
MainActivity.java
public void onClickStartService(View v)
{
startService(new Intent(this,MyService.class));
}
public void onClickStopService(View v)
{
stopService(new Intent(this,MyService.class));
}
and MyService.java is
public class MyService extends Service{
private static final String TAG = "MyService";
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
Toast.makeText(this, "Congrats! MyService Created", Toast.LENGTH_LONG).show();
Log.d(TAG, "onCreate");
}
#Override
public void onStart(Intent intent, int startId) {
Toast.makeText(this, "My Service Started", Toast.LENGTH_LONG).show();
Log.d(TAG, "onStart");
//Note: You can start a new thread and use it for long background processing from here.
}
#Override
public void onDestroy() {
Toast.makeText(this, "MyService Stopped", Toast.LENGTH_LONG).show();
Log.d(TAG, "onDestroy");
}
}
I have buttons to start and stop the Service and it works. Now I want the service to create notification as I have mentioned at the beginning of the post. How can I do this?
To start the service at a specific time, I suggest you create a BroadcastReceiver triggered by an Alarm, which will in turn start your service.
First write a BroadcastReceiver like this :
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, final Intent intent) {
context.startService(new Intent(context, MyService.class));
}
/**
* Schedule the next update
*
* #param context
* the current application context
*/
private static void scheduleServiceUpdates(final Context context) {
// create intent for our alarm receiver (or update it if it exists)
final Intent intent = new Intent(context, AlarmReceiver.class);
final PendingIntent pending = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
// compute first call time 1 minute from now
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.MINUTE, 10);
long trigger = calendar.getTimeInMillis();
// set delay between each call : 24 Hours
long delay = 24 * 60 * 60 * 1000;
// Set alarm
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC, trigger, delay, pending);
// you can use RTC_WAKEUP instead of RTC to wake up the device
}
}
Then you just need to call the scheduleServiceUpdate method to start the reccuring event. If you only use the RTC type, then if the phone is locked when the alarm should trigger the service, it won't and will wait until the device is unlocked by the user. If you use RTC_Wakeup, the service will start exactly at the time given.
Note that there are other methods in the AlarmManager to trigger events.
You can start from PendingIntent and AlarmManager
Tutorial here
Dont forget to add possibility to cancel alarm manager with
mAlarmManager.cancel(pendingIntent);
Also you may want to intercept android.intent.action.BOOT_COMPLETED event to make you app starting immediately after reboot if you want to start your service by schedule.

Android: Scheduling application to start with repeating alarms not working

I get my Broadcast receiver to set a recurring alarm, to fire up a service. Unfortunately this does not result in the service being called repeatedly (based on logcat). I've experimented with different values for the time interval too. Can someone help? (I'm testing through Eclipse on Android 3.2 Motorola xoom)
Below is the code for the Broadcast receiver.
alarm = (AlarmManager) arg0.getSystemService(Context.ALARM_SERVICE);
Intent intentUploadService = new Intent (arg0, com.vikramdhunta.UploaderService.class);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 3);
PendingIntent pi = PendingIntent.getBroadcast(arg0, 0, intentUploadService , 0);
alarm.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 5, pi);
Below is the code for the Service class
public UploaderService()
{
super("UploaderService");
mycounterid = globalcounter++;
}
#Override
protected void onHandleIntent(Intent intent) {
synchronized(this)
{
try
{
for (int i = 1;i < 5;i++)
{
// doesn't do much right now.. but this should appear in logcat
Log.i(TAG,"OK " + globalcounter++ + " uploading..." + System.currentTimeMillis());
}
}
catch(Exception e)
{
}
}
}
#Override
public void onCreate() {
super.onCreate();
Log.d("TAG", "Service created.");
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.i(TAG, "Starting upload service..." + mycounterid);
return super.onStartCommand(intent,flags,startId);
}
Ok Looks like I got this one. Two changes were needed -
1 - i made a mistake of using PendingIntent.getBroadcast when I needed to do getService instead (hell, who knew!)
2 - In getService, I should have supplied PendingIntent.FLAG_UPDATE_CURRENT in the end instead of 0. FLAG_ONE_SHOT did not work. I guess since the interval is only 5 seconds, this is the right way.
Now I get the right service/function to be called every 5 seconds. Hurray!

Categories

Resources