Android Service is terminated when App destroyed - android

I'm trying to learn Android Service, I'm very noob. I'm creating a service which will run even after the app is destroyed but when I terminate the App, the Service gets terminated too. I'm trying to make a NotificationService, below is my code that I just tried working with Service.
Manifest:
<service
android:name="com.test.testworks.MyService"
/>
Starting Service via Button Click:
startService(new Intent(this, MyService.class));
Service class MyService.class:
public class MyService extends Service {
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
/* 1. *//*ScheduledExecutorService scheduleTaskExecutor = Executors.newScheduledThreadPool(5);
// This schedule a runnable task every 2 minutes
scheduleTaskExecutor.scheduleAtFixedRate(new Runnable() {
public void run() {
}
}, 0, 10000, TimeUnit.SECONDS);*/
/* 2. *//*final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
Toast.makeText(MyService.this, "suiubsibddubsuidv", Toast.LENGTH_LONG).show();
handler.postDelayed(this, 10000); //now is every 2 minutes
}
}, 10000);*/
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
I'm checking on my phone where the other Services are running and when I terminate the App, the Service terminates also.

On some phones, you need to add your app explicitly to the list of apps that are allowed to run in the background. Otherwise, Android will not restart your app if it is killed for whatever reason. There should be a settings page which lists installed apps and allows you to add them to this list. It is called "protected apps" on some devices. Especially devices from Xiaomi, LG, Huawei have this feature, but also other phones.

Related

How can we call an api in every 2 minutes in android N or higher versions even when the app is closed or killed

I want a best consistent solution to call an api to update current location in every 2 minutes on Nougat and higher version. The process should not be terminated even when the app is killed or closed.
Thanks in advance
Create a services:
public class MyServices extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
startService(new Intent(this,MyServices.class));
Timer t = new Timer();
final Handler handler = new Handler();
// Timer task makes your service will repeat after every 20 Sec.
TimerTask doAsynchronousTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
//Do network call here
}
});
}
};
//Starts after 20 sec and will repeat on every 20 sec of time interval.
t.schedule(doAsynchronousTask, 3000,3000); // 20 sec timer
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
}
Register the service in menifest
<service android:name=".MyServices" />
Start the service in your activity
Intent intent = new Intent(this, MyServices.class);
startService(intent);
if version > N use this
startForegroundService(intent);
Create a service and update from there.
Service will not stop after closing the application but it will get stopped if the application is force stopped.
And also if your app goes to doze mode your app cannot use Internet or GPS service from the background.
You should check out WorkManager to schedule any kind of work you want your app to do.

TimerTask stops firing in Service

I need to have a Service running in Android that stores a value to database every so often. How often is based on user preferences, and also if other events have happened, which can be as often as 30 seconds or up to 30 minutes.
This is not something that is hidden from the user and in fact the user should probably be aware its running. As such I think a foreground service is probably the best approach.
I have a foreground service running, with a TimerTask that calculates how often it needs to fire. That Service is 'sticky' so it should stick around and it low on resources the OS should start it back up after a while.
My problem is that the TimerTask seems to stop running after a while when the the app is backgrounded.
Here is my service:
public class TimerService extends Service {
private static final String LOG_NAME = TimerService.class.getName();
private Timer timer;
private final Handler timerHandler = new Handler();
#Override
public void onCreate() {
super.onCreate();
Notification notification = new NotificationCompat.Builder(this, "MY_APP_CHANNEL_ID")
.setContentTitle("My Timer Service")
.setContentText("Background timer task")
.setSmallIcon(R.drawable.timer)
.build();
startForeground(1, notification);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
startTimer();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
stopTimer();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
private void stopTimer() {
if (timer != null) {
timer.cancel();
timer = null;
}
}
private void startTimer() {
stopTimer();
timer = new Timer();
long frequency = // calculate frequency
long delay = // calculate delay
timer.scheduleAtFixedRate(new MyTimerTask(), delay, frequency);
}
private void saveToDatabase() {
// Save some stuff to the database...
if (some condition) {
// might need to reschedule timer delay and frequency.
startTimer();
}
}
private class MyTimerTask extends TimerTask {
#Override
public void run() {
timerHandler.post(new Runnable() {
#Override
public void run() {
onTimerFire();
}
});
}
private void onTimerFire() {
try {
saveToDatabase();
} catch (Exception e) {
Log.e(LOG_NAME, "Error in onTimerFire", e);
}
}
}
}
Should this work? IE can I have a simple Timer in a foreground Service that fires continuously until that service is stopped? If so is there a bug in my code?
I chose a Timer to try to keep it simple, I only ever need one timer running and I wanted it to be able to reschedule easily. I do realize that I could try a Handler, ScheduledThreadPoolExecutor, or even an AlarmManager. I thought an AlarmManager might be overkill and a drain on resources if it is firing a ton. Not to mention rescheduling.
Why won’t it run in the background?
It is running in the background. It is not running when the device is asleep, as the CPU is powered down. In Android, "background" simply means "has no foreground UI" (activity, service with a foreground Notification).
I need to have a Service running in Android that stores a value to database every so often. How often is based on user preferences, and also if other events have happened, which can be as often as 30 seconds or up to 30 minutes.
What you want has not been practical on Android since 6.0.
I thought an AlarmManager might be overkill and a drain on resources if it is firing a ton.
That is true. However, the only way to get your existing code to work would be for you to acquire a partial WakeLock, thereby keeping the CPU running forever. This will be orders of magnitude worse for power than is AlarmManager. And AlarmManager is bad enough that each Android release, starting with 6.0, has made it progressively more difficult to use AlarmManager (or JobScheduler, or Timer and a wakelock) to do anything reliably.
You are going to need to learn what Android is and is not capable of with respect to background processing, then adjust your product plans accordingly. That subject is way too long for a Stack Overflow answer.
Here is a set of slides from a presentation that I delivered last year on this subject, with Android 8.0 in mind (use Space to advance to the next slide). You might also read:
My thoughts on Android P DP2, particularly "What’s New in the War on Background Processing"
This preview of one of my book chapters, where the section on Android 8.0 and its phase in "The War on Background Processing" happens to be included
Wakelock and doze mode
IMHO, writing an app that relies upon periodic background processing is a very risky venture nowadays.
You should use ScheduledExecutorService for the same. There can be many ways to schedule background task like Alarm Manager, JobDispatcher, Sync Adapter, Job Scheduler. I will suggest ScheduledExecutorService over them.
I have one good example of using ScheduledExecutorService in service. (Currently using in highly optimised location sync service)
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* Created by KHEMRAJ on 1/29/2018.
*/
public class SyncService extends Service {
private Thread mThread;
ScheduledExecutorService worker;
private static final int SYNC_TIME = 60 * 1000; // 60 seconds
#Override
public int onStartCommand(#Nullable Intent intent, int flags, int startId) {
startSyncService();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
stopThread();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
private void stopThread() {
worker = null;
if (mThread != null && mThread.isAlive()) mThread.interrupt();
}
private void startSyncService() {
if (worker == null) worker = Executors.newSingleThreadScheduledExecutor();
if (mThread == null || !mThread.isAlive()) {
mThread = new Thread(new Runnable() {
#Override
public void run() {
saveToDb();
if (worker != null) {
worker.schedule(this, SYNC_TIME, TimeUnit.MILLISECONDS);
}
}
});
mThread.start();
}
}
private void saveToDb() {
// TODO: 5/15/2018
}
}

Run task periodically, *even when device is in idle*

I'm writing an app which should collect some sensor data every 10 seconds or so and write them to disk.
So far, I have an Activity which starts a service. The service has a runnable, which uses a handler to run my task periodically via handler.postDelayed(). See below for the (shortened) code.
So far, this works fine as long as the device is active. As soon as the device goes into idle, it doesn't run my task until it wakes up again.
So, my question is how to run my task ALWAYS.
With setExactAndAllowWhileIdle(), the AlarmManager seems to offer exactly what I need, but...
To reduce abuse, there are restrictions on how frequently these alarms will go off for a particular application. Under normal system operation, it will not dispatch these alarms more than about every minute (at which point every such pending alarm is dispatched); when in low-power idle modes this duration may be significantly longer, such as 15 minutes.
Battery life has just a minor priority, though not being awake the entire time would be fine. (Not sure if android can be awake for just a second or so)
MyActivity
...
public void onStartService(View view) {
Intent i= new Intent(getBaseContext(), MyAppService.class);
getBaseContext().startService(i);
}
public void onStopService(View view) {
stopService(new Intent(getBaseContext(), MyAppService.class));
}
....
MyService
public class MyAppService extends Service {
MyRunnable mr;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mr= new MyRunnable(getApplicationContext() );
mr.Start();
return Service.START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
mr.Stop();
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}
MyRunnable
public class MyRunnable implements Runnable{
// context is needed for sensorListener (?)
private Context myContext;
private Handler handler;
public MyRunnable(Context c){
myContext=c;
handler= new Handler();
}
public void Start(){
run();
}
public void Stop(){
handler.removeCallbacks(this);
// some clean-up
}
#Override
public void run() {
//acquire and write to file some sensor data
handler.postDelayed(this, 10000);
}
}
i think what you are looking for is STICKY SERVICE.
Officail Docs: If the system kills the service after onStartCommand() returns, recreate the service and call onStartCommand(), but do not redeliver the last intent. Instead, the system calls onStartCommand() with a null intent, unless there were pending intents to start the service, in which case, those intents are delivered. This is suitable for media players (or similar services) that are not executing commands, but running indefinitely and waiting for a job.
you just need to pass a flag at the time of calling the service.

Stop the Service after the Vibrating the Phone in android?

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;
}

Service stops when deploying android app (disapears from settings>>application>>RunningServices)

This is my situation: I have a service running and every time I deploy my app the service disappears from settings>>application>>runningService (therefore, the service is not running) how can I set it so that the service does not disappears?
I have tried to startForeground but it did not worked.
AndroidManifest:
<service
android:name=".service.PhoneCallInOutService"
android:enabled="true"
android:exported="false" >
</service>
This is how I start the service in my Activity:
chkCallsRecord.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
boolean isChecked = chkCallsRecord.isChecked();
updateBackgroundTasks(isChecked);
}
});
The method actually starting the service:
private void updateBackgroundTasks(boolean start) {
Intent serviceIntent = new Intent(getApplicationContext(),PhoneCallInOutService.class);
if (start) {
getApplicationContext().startService(serviceIntent);
} else {
getApplicationContext().stopService(serviceIntent);
}
}
And here is the service:
public class PhoneCallInOutService extends Service {
private TelephonyManager telephonyMgr;
private PhoneCallStateListener pcsListener;
private OutgoingCallReceiver ocReceiver;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
// Listener
pcsListener = new PhoneCallStateListener(getApplicationContext(),appDto);
telephonyMgr = (TelephonyManager)getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE);
telephonyMgr.listen(pcsListener, PhoneStateListener.LISTEN_CALL_STATE);
// Receiver
ocReceiver = new OutgoingCallReceiver(getApplication());
IntentFilter intentF = new IntentFilter(Intent.ACTION_NEW_OUTGOING_CALL);
getApplicationContext().registerReceiver(ocReceiver, intentF);
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
// Listener
telephonyMgr.listen(pcsListener, PhoneStateListener.LISTEN_NONE);
// Receiver
getApplicationContext().unregisterReceiver(ocReceiver);
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
}
Thank you very much in advance.
If by deploy you mean you try to launch new build of your app, then this is actually normal and expected behaviour. By deploying new build you replace old code (incl. service code) therefore it have to be killed first to avoid any crashes and other oddities. So your old iteration of app is completely killed. Then new app is installed and most often auto-launched. Your data create by the app usually stay, but it's also normal.
EDIT
For security reasons you are not allowed to re-launch itself after being updated. User has to to this. As for "he/she may assume the service is still there running, which is not true", use notification of type "On Going" to indicate running service

Categories

Resources