Android: Keep asynctask even after app is killed - android

I have this code below that I'm using to test the life cycle of the asynctask. What I want to do is to let the asynctask finish even if the app is forcibly closed by the user. It shows a notification which increments the progress every second. The asynctask is called from a Fragment. However, when I forcibly terminate the app by pressing all apps then swiping it off, the notification stops and no longer increments. See my code below.
Is this the case or am I doing something wrong?
Also, the reason I'm using asynctask is because I want to allow the user to cancel the task whenever possible. I believe this can't be done with IntentService? (Correct me if I'm wrong on this).
Appreciate any help.
UPDATE: I am now trying foreground service as suggested by #John Wick and #Abishek. However, I am not able to stop the service the way I want it to. When I click stop, the loop goes on and does not stop.
public class ForegroundService extends Service {
boolean isCancelled = false;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent.getAction().equals("Start")) {
Log.d("Action", "Start");
Intent notificationIntent = new Intent(this, MainActivity.class);
notificationIntent.setAction("Start");
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
Intent closeIntent = new Intent(this, ForegroundService.class);
closeIntent.setAction("Stop");
PendingIntent pCloseIntent = PendingIntent.getService(this, 0, closeIntent, 0);
Bitmap icon = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
NotificationManagerCompat manager = (NotificationManagerCompat.from(this));
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentTitle("Truiton Music Player");
builder.setTicker("Truiton Music Player");
builder.setContentText("My Music");
builder.setSmallIcon(R.mipmap.ic_launcher);
builder.setLargeIcon(Bitmap.createScaledBitmap(icon, 128, 128, false));
builder.setContentIntent(pendingIntent);
builder.addAction(android.R.drawable.ic_media_pause, "Stop", pCloseIntent);
startForeground(1, builder.build());
for (int i = 0; i < 10; i++) {
Log.d("Service", String.valueOf(i));
builder.setProgress(9, i, false);
if (isCancelled) {
builder.setContentTitle("Cancelled");
builder.setContentText("");
builder.setProgress(0, 0, false);
builder.mActions.clear();
manager.notify(1, builder.build());
} else {
if (i == 9) {
builder.setContentTitle("Done");
builder.setContentText("");
builder.setProgress(0, 0, false);
manager.notify(1, builder.build());
} else {
manager.notify(1, builder.build());
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
stopForeground(true);
} else {
Log.d("Action", "Start");
isCancelled = true;
stopForeground(true);
stopSelf();
}
return START_STICKY;
}
}

You need to use a Foreground Service to make it work even if app is closed. See this link for a demo implementation.
http://www.truiton.com/2014/10/android-foreground-service-example/

What you need here is Service and yes it can be stopped when you no longer need it, the advantage over AysncTask is even when you terminate your app from task manager you service whon't get affected.
To stop a service you will need to call
stopService(new Intent(//Service));
Now if you want to show notification which updates a counter then use foreground service for this.
https://developer.android.com/guide/components/services.html#Foreground

You can Keep asynctask even after app is killed but when your doInBackground work finished and onPostExecute method work on that time you need to require available object of context otherwise app will crashed.

Related

How to prevent android to stop a service with forground (for android version>O ) and notification

I want to take signal measurements. My app activity takes masurements (and provide charts) when is in foreground and at the onPause event I call and bind a service to take measurements (and store them in the database) in order to replace the activity.
However if the phone is unpluged the app stop taking measurements. I have study a lot of other posts and I have implemented in foreground with notification.
Here is a code sample from the Service
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent,START_STICKY,startId);
goForeground();
return Service.START_STICKY; }
private void goForeground() {
Log.i(TAG ,"goForeground");
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
Notification n = new Notification.Builder(this)
.setContentTitle("Measurements Service")
.setContentText("App still collects measurements.")
.setSmallIcon(R.drawable.myApp)
.setContentIntent(pendingIntent)
.setPriority(Notification.PRIORITY_DEFAULT)
.setContentIntent(pendingIntent)
.build();
NotificationManager notificationManger =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManger.notify(01, n);
startForeground(FOREGROUND_NOTIFICATION_ID, n);
}
and the MainActivity
Intent serviceIntent = new Intent(MainActivity.this, SnoopService.class);
if (SnoopService.isRunning()) {
Log.d(TAG, "Service is running");
doBindService(intent);
} else {
Log.d(TAG, "Service will run");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(intent);
} else
startService(intent);
doBindService(intent);
}
isBound = true;
}
Does anyone knows if I am doing something wrong?
I have test it with Samsung Galaxy S8.

How to press ON a foreground service Notification?

I have a foreground service notification and i want when the user closes the app and presses the notification to open the application again.I implemented an
onclicklistener with onClick() method but it did nothing.If that is not possible i want the "Play" button to be shown in the notification because it is only being shown when i expand the notification.
Here is the service class:
public class MyForeGroundService extends Service {
public MyForeGroundService() {
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG_FOREGROUND_SERVICE, "My foreground service onCreate().");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null) {
String action = intent.getAction();
switch (action) {
case ACTION_START_FOREGROUND_SERVICE:
startForegroundService();
Toast.makeText(getApplicationContext(), "Foreground service is started.", Toast.LENGTH_LONG).show();
break;
case ACTION_STOP_FOREGROUND_SERVICE:
stopForegroundService();
Toast.makeText(getApplicationContext(), "Foreground service is stopped.", Toast.LENGTH_LONG).show();
break;
case ACTION_PLAY:
Toast.makeText(getApplicationContext(), "You click Play button.", Toast.LENGTH_LONG).show();
break;
case ACTION_PAUSE:
Toast.makeText(getApplicationContext(), "You click Pause button.", Toast.LENGTH_LONG).show();
break;
}
}
return super.onStartCommand(intent, flags, startId);
}
/* Used to build and start foreground service. */
private void startForegroundService() {
Log.d(TAG_FOREGROUND_SERVICE, "Start foreground service.");
// Create notification default intent.
Intent intent = new Intent();
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
// Create notification builder.
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
// Make notification show big text.
NotificationCompat.BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle();
bigTextStyle.setBigContentTitle("Music player implemented by foreground service.");
bigTextStyle.bigText("Android foreground service is a android service which can run in foreground always, it can be controlled by user via notification.");
// Set big text style.
builder.setStyle(bigTextStyle);
builder.setWhen(System.currentTimeMillis());
builder.setSmallIcon(R.mipmap.ic_launcher);
Bitmap largeIconBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.strava);
builder.setLargeIcon(largeIconBitmap);
// Make the notification max priority.
builder.setPriority(Notification.PRIORITY_MAX);
// Make head-up notification.
builder.setFullScreenIntent(pendingIntent, true);
// Add Play button intent in notification.
Intent playIntent = new Intent(this, MyForeGroundService.class);
playIntent.setAction(ACTION_PLAY);
PendingIntent pendingPlayIntent = PendingIntent.getService(this, 0, playIntent, 0);
NotificationCompat.Action playAction = new NotificationCompat.Action(android.R.drawable.ic_media_play, "Play", pendingPlayIntent);
builder.addAction(playAction);
// Build the notification.
Notification notification = builder.build();
// Start foreground service.
startForeground(1, notification);
}
private void stopForegroundService() {
Log.d(TAG_FOREGROUND_SERVICE, "Stop foreground service.");
// Stop foreground service and remove the notification.
stopForeground(true);
// Stop the foreground service.
stopSelf();
}
}
So to add an "onClick" effect to a notification you should use the ".setContentIntent(pendingIntent)" method in the NotificationCompat.Builder.
For the play button to always be visible is a little bit more tricky from what I read, some say that "setPriority(Notification.PRIORITY_MAX) + setWhen(0)" can solve this, others say that it depends on device and if you have other notifications, are you connected to USB etc and that there is no single working solution for this.

Foreground Service dont run constantly

In my app I use a foreground service that must run constantly. Sometimes the foreground service is stopped.
Under what circumstances can the OS kill my service (it happen even if there is enough memory, battery is full, phone is charging)?
This is what my code looks like until now:
public class ServiceTest extends Service {
public static Thread serverThread = null;
public Context context = this;
public ServiceTest(Context context) {
super();
this.context = context;
}
public ServiceTest() {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
if (this.serverThread == null) {
this.serverThread = new Thread(new ThreadTest());
this.serverThread.start();
}
return START_STICKY;
}
private class ThreadTest implements Runnable {
#Override
public void run() {
Intent notificationIntent = new Intent(context, MainActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);
Notification notification = new NotificationCompat.Builder(context)
.setContentTitle("Notification title")
.setContentText("Notification text")
.setContentIntent(pendingIntent)
.setAutoCancel(false)
.setSmallIcon(R.drawable.android)
.setOngoing(true).build();
startForeground(101, notification);
while(true){
//work to do
}
}
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
There is not a single... Many problems in your code... You may be getting it "0 Errors" as it is syntactically correct but it is androidicaly wrong, your basics are poor, reading of android documentation and implementation is very poor. Android never runs very poor things...
Problem : 1
Do you know for a service conventionally you should override onCreate, onStartCommand, onBind, onDestroy methods....?
I don't see onDestroy there....!!
Problem : 2
Do you know how to notify...? Your onStartCommand implementation is again making no sense.
KEEP IT EMPTY JUST RETURN START_STICKY
Problem : 3
How do you expect to run this under background execution limits...? Notify android first by making notification in oncreate only and with startforeground if needed...
I don't see it there.... you trying to do it in onstartcommand and again it is very poorly...
Well... take a look at working code below :
public class RunnerService extends Service
{
NotificationManager mNotifyManager;
NotificationCompat.Builder mBuilder;
NotificationChannel notificationChannel;
String NOTIFICATION_CHANNEL_ID = "1";
public RunnerService() { }
#Override
public void onCreate()
{
super.onCreate();
Log.d("RUNNER : ", "OnCreate... \n");
Bitmap IconLg = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_foreground);
mNotifyManager = (NotificationManager) getApplicationContext().getSystemService(NOTIFICATION_SERVICE);
mBuilder = new NotificationCompat.Builder(this, null);
mBuilder.setContentTitle("My App")
.setContentText("Always running...")
.setTicker("Always running...")
.setSmallIcon(R.drawable.ic_menu_slideshow)
.setLargeIcon(IconLg)
.setPriority(Notification.PRIORITY_HIGH)
.setVibrate(new long[] {1000})
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setOngoing(true)
.setAutoCancel(false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "My Notifications", NotificationManager.IMPORTANCE_HIGH);
// Configure the notification channel.
notificationChannel.setDescription("Channel description");
notificationChannel.enableLights(true);
notificationChannel.setLightColor(Color.RED);
notificationChannel.setVibrationPattern(new long[]{1000});
notificationChannel.enableVibration(true);
notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
mNotifyManager.createNotificationChannel(notificationChannel);
mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
startForeground(1, mBuilder.build());
}
else
{
mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
mNotifyManager.notify(1, mBuilder.build());
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.d("RUNNER : ", "\nPERFORMING....");
return START_STICKY;
}
#Override
public void onDestroy()
{
Log.d("RUNNER : ", "\nDestroyed....");
Log.d("RUNNER : ", "\nWill be created again automaticcaly....");
super.onDestroy();
}
#Override
public IBinder onBind(Intent intent)
{
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("NOT_YET_IMPLEMENTED");
}
}
How to check....???
Remove the app from recents list and you should see in your logs the "Performing " message in logcat...
In what conditions it stops...?
It never stops ( until next boot..!! )... Yes it stops when user force stops application. And rarely if system finds it is having very low resources .... which is a very rare condition seems to occur as android has improved a lot over the time....
How to start it....?????
Wherever it may be from mainactivity or from receiver or from any class :
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
context.startForegroundService(new Intent(context, RunnerService.class));
}
else
{
context.startService(new Intent(context, RunnerService.class));
}
How to check is service started or not....?
Simply Don't..... Even if you starts service how many times you wants.... If it is already running... then it won't be start again.... If not running then... will start it...!!
The criticism made in the chosen answer is not reasonable if the service needs an intent to work.
On higher version of Android, System will pause any foreground service while the device is locked, to minimize the power consumption even if it returns START_STICKY. So, to make a foreground task constantly, a wakelock is required.
Here's what android documentation describes wakeLock:
To avoid draining the battery, an Android device that is left idle quickly falls asleep. However, there are times when an application needs to wake up the screen or the CPU and keep it awake to complete some work.
To make a foreground service running constantly, acquire a wakeLock from inside the onCreate().
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"MyApp::MyWakelockTag");
wakeLock.acquire();
For further detail, have a look at official Android Documentation.

Android service gets killed on swiping out the application

I have an Android Service class the code for which is as follows:
public class LoginService extends Service {
BroadcastReceiver wifiStateChangeReciever;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("AndroidLearning", "Service onStartCommand Started.");
return Service.START_STICKY;
}
#Override
public void onCreate() {
super.onCreate();
Log.i("AndroidLearning", "Service Started.");
final IntentFilter intentFilter = new IntentFilter();
// intentFilter.addAction("android.net.wifi.WIFI_STATE_CHANGED");
intentFilter.addAction("android.net.wifi.STATE_CHANGE");
wifiStateChangeReciever = new WifiStateChangeReciever();
this.registerReceiver(wifiStateChangeReciever, intentFilter, null, null);
Log.i("AndroidLearning", "Reciever Registered.");
}
#Override
public void onDestroy() {
Log.i("AndroidLearning", "Service Destroyed.");
this.unregisterReceiver(wifiStateChangeReciever);
}
#Override
public void onTaskRemoved(Intent rootIntent) {
Log.w("AndroidLearning", "On Task Remove: FLAG_STOP_WITH_TASK - "
+ ServiceInfo.FLAG_STOP_WITH_TASK);
this.unregisterReceiver(wifiStateChangeReciever);
Intent restartServiceIntent = new Intent(getApplicationContext(),
this.getClass()); restartServiceIntent.setPackage(getPackageName());
PendingIntent restartServicePendingIntent = PendingIntent.getService(
getApplicationContext(), 1, restartServiceIntent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmService = (AlarmManager)this.getSystemService(Context.ALARM_SERVICE);
alarmService.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + 1000, restartServicePendingIntent);
Log.w("AndroidLearning", "End on task removed");
super.onTaskRemoved(rootIntent);
}
}
It registers a BroadcastReciever. The Activity which starts this service has the following code:
Intent intent = new Intent(this, LoginService.class);
startService(intent);
However whenever the Activity is swiped out from the task list (recent) the service is also stopped. I over rode the onTaskRemoved to remedy it but it still does not seem to work and the AlarmManager never starts the pendingIntent. I have tries using both method: set and setExact for the AlarmManager.
I also tried adding the following options to <service> tags
android:stopWithTask="false"
android:process=":remote"
but to no avail.
What am I doing wrong here? Thanks for the help.
I finally found the answer to my own problem. It seems this was a problem with the particular flavor of android that I was running on my phone (Mi UI). There was a separate setting regarding each application whether it needed to be allowed to be restarted or not.
Unless this setting is configured no amount of changing permissions and setting Alarms helped me.
This is a different approach from you but I recently fixed this by adding a notification when the service was running
private void showNotification(){
NotificationCompat.Builder builer = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.logo)
.setContentTitle("Service active")
.setContentText("Your service keeps running")
.setOngoing(true);
mNotificationManager.notify(NOTIFICATION_ID, builer.build());
}
The notification is shown in onStartCommand and dismissed in the service ondestroy method.
You need to start service in foreground if you don't want android to shut it down.
Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),
System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_title),
getText(R.string.notification_message), pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);
http://developer.android.com/guide/components/services.html#Foreground
If you try this on some devices, sadly, it won't work.
Some OEMs decided to change the normal behavior of what happens when you remove an app from the recent tasks, so they become semi-disabled:
https://issuetracker.google.com/issues/122098785
https://dontkillmyapp.com/

android (Service & PhoneStateListener) - service does restart but not working when app is killed by task manager, killer or shortage of memory

This is onStartCommand()
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Notification creation code
telMgr = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
telMgr.listen(new PSL(), PhoneStateListener.LISTEN_CALL_STATE);
return super.onStartCommand(intent, flags, startId);
}
and PhoneStateListener class (under service class)
public class PSL extends PhoneStateListener {
public void onCallStateChanged(int state, String incomingNum) {
switch(state) {
case TelephonyManager.CALL_STATE_IDLE:
case TelephonyManager.CALL_STATE_OFFHOOK:
//Work1
break;
case TelephonyManager.CALL_STATE_RINGING:
//Work2
break;
}
}
}
both of them are in same .java file
I have these code on one service class.
when I call startService() from main activity, it works well.
but when my app is killed by Task Manager, Killer or automatically by shortage of memory on device, Service does restarts but not working.
when i go to Setting - Application - Running, it shows process 1 and service 1, before/after killed.but after killed, memory share goes 1/10. I have tried startForeground() not to be killed easily with my notification - it didn't work. (doesn't show any notification)
and also tried return of onStartCommand(): START_STICKY, START_REDELIVER_INTENT - shows same result is there any way I can restart completely or make it not killed?
After Spending few Hours I fount that , For Android 2.0 or later you can use the startForeground() method to start your Service in the foreground.
Documentation provided by Android
A started service can use the startForeground(int, Notification) API to put the service in a foreground state, where the system considers it to be something the user is actively aware of and thus not a candidate for killing when low on memory. (It is still theoretically possible for the service to be killed under extreme memory pressure from the current foreground application, but in practice this should not be a concern.)
Ther are very rare chances of Foreground Service to kill by OS.But It works fine.
public class ServicePhoneState extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Intent notificationIntent = new Intent(this, MainActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle("Music Player")
.setTicker("Google Music Player")
.setContentText("My Music")
.setSmallIcon(R.drawable.ic_bg_icon)
.setPriority(Notification.PRIORITY_MAX)
.setContentIntent(pendingIntent)
.setOngoing(false)
.build();
startForeground(10, notification);
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
stopForeground(true);
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
I solved it by startForeground()
It didn't work because I had not used Notification.FLAG_FOREGROUND_SERVICE on Notification
After Spending few Hours I fount that , For Android 2.0 or later you can use the startForeground() method to start your Service in the foreground.
Documentation provided by Android
A started service can use the startForeground(int, Notification) API to put the service in a foreground state, where the system considers it to be something the user is actively aware of and thus not a candidate for killing when low on memory. (It is still theoretically possible for the service to be killed under extreme memory pressure from the current foreground application, but in practice this should not be a concern.) Ther are very rare chances of Foreground Service to kill by OS.But It works fine.
public class ServicePhoneState extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
MyPhoneStateListener phoneListener = new
MyPhoneStateListener(ServicePhoneState.this);
TelephonyManager telephony = (TelephonyManager)
getSystemService(Context.TELEPHONY_SERVICE);
telephony.listen(phoneListener, PhoneStateListener.LISTEN_CALL_STATE);
Intent notificationIntent = new Intent(this, MainActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle("Music Player")
.setTicker("Google Music Player")
.setContentText("My Music")
.setSmallIcon(R.drawable.ic_bg_icon)
.setPriority(Notification.PRIORITY_MAX)
.setContentIntent(pendingIntent)
.setOngoing(false)
.build();
startForeground(10, notification);
return START_NOT_STICKY;}
#Override
public void onDestroy() {
super.onDestroy();
stopForeground(true);
}
#Override
public IBinder onBind(Intent intent) {
return null;}}

Categories

Resources