I am making an Android app which runs a simple Service in the background.
Nothing fancy but the service toasts a msg every 5 secs confirming that it is running in the background, even when the App activity is terminated.
But when i checked the task manager, i found that the process is utilizing 4MB of ram initially but later keeps on increasing with time.
I want to know that if there is any way i can stop the extra memory usage and keep it to a bare minimum, since i know i am not doing any heavy work in the background.
Any help will be appreciated!
Thanks.
P.S. I will post the service code below.
public class BgmService extends Service {
public Handler mHandler = new Handler();
public BgmService() {
}
#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();
Toast.makeText(this, "Service has started!!!", Toast.LENGTH_SHORT).show();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mHandler.post(mtask);
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service was Killed!!!", Toast.LENGTH_SHORT).show();
mHandler.removeCallbacks(mtask);
}
public Runnable mtask = new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "Service is Running!!!", Toast.LENGTH_SHORT).show();
mHandler.postDelayed(mtask, 4000);
}
};
}
As #PunK_l_RuLz told, your Runnable is getting created after every 4000 mili seconds. So, you can create a subclass of Runnable and use single object of this class for every Toast :
public class PostRunnable extends Runnable {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "Service is Running!!!", Toast.LENGTH_SHORT).show();
mHandler.postDelayed(mRunnable, 4000);
}
}
Use above class like :
PostRunnable mRunnable;
if(mRunnable != null) {
mHandler.post(mRunnable);
} else {
mRunnable = new PostRunnable();
mHandler.post(mRunnable);
}
you are calling the mTask from inside your mTask, every time a new object of Runnable is created and as your Service holds the reference of every runnable object created your memory goes on increasing. I think using a Timer with TimerTask might solve your problem. Hope this helps
Have you tried using a timer instead of a post delay?
It's odd though, I can't see why it would leak.
Related
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
Actually i have to perform some technique in which some particular method will be called after specified time until app destroyed.I Google it and have found services.Using services this work can be performed.I have gone through many Service tutorials so now i can work with services but can anybody tell me how to do this. Should i use services for call particular tack in the background of the activity after specified time?...Thanks....
Edit: I have used following code
public class MyService extends Service {
int count = 0;
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
handler.removeCallbacks(updateTimeTask);
handler.postDelayed(updateTimeTask, 1000);
Toast.makeText(this, "Service started................",
Toast.LENGTH_SHORT).show();
}
private Runnable updateTimeTask = new Runnable() {
public void run() {
if (count == 50) {
count = 0;
Tocken_parser tocken = new Tocken_parser();
tocken.tockenParser("1");
Toast.makeText(MyService.this, "coutn===", Toast.LENGTH_SHORT)
.show();
System.out.println("Count ===============");
}
count++;
handler.postDelayed(this, 1000);
}
};
private Handler handler = new Handler();
#Override
public void onDestroy() {
super.onDestroy();
System.out
.println("Service destroyed........................................");
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
Its working properly but tell me one thing, how to stop services when activity destroyed.
The answer is YES. Also, the Service that spawned by Activity will be destroyed together; unless, you assign a schedule check on Alarm to wake up your dead Service.
My question is Android related:
How do I run a task every 20 seconds within an intentservice ?
Problem is, I have to init some classes which will be used in the Handler "run" process.
It works one time - but then the service stops & the application crashes when the handler-loop starts again after 20 seconds (probably because of the classes that got eliminated when the service stopped?). So maybe the solution is to get the service to stay running as long as the Handler runs or to throw away the code and do it right ?
Hope, someone can help me.
public class Fadenzieher extends IntentService{
private Handler handler = new Handler();
private Runnable timedTask = new Runnable(){
#Override
public void run() {
// My functions get called here...
// class1member.getDBWorkdone();
handler.postDelayed(timedTask, 20000);
handler.obtainMessage();
}};
public Fadenzieher() {
super("Fadenzieher");
}
#Override
protected void onHandleIntent(Intent intent) {
// SOME INITIALISING
// I have to init some vars & functions here that
// will also be used inside the handler loop
// Class1 class1member = new Class1();
// class1member.startUpDB();
handler.post(timedTask); }
Thank you very much in advance!!!
---- So this is the updated code now (14. nov. 2011)
public class Fadenzieher extends Service{
private static final long UPDATE_INTERVAL = 60000;
Context context = this;
private Timer timer = new Timer();
DbHelper dbHelper;
public void onCreate(){
dbHelper = new DbHelper(context);
runTheLoop();
}
protected void runTheLoop() {
timer.scheduleAtFixedRate(new TimerTask(){
#Override
public void run() {
dbHelper.dosomethings();
Toast.makeText(context, "CALL", Toast.LENGTH_LONG).show();
}}, 0, UPDATE_INTERVAL);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "Starte Service“, Toast.LENGTH_SHORT).show();
return super.onStartCommand(intent,flags,startId);
}
public void onDestroy() {
super.onDestroy();
dbHelper.close();
Toast.makeText(this, "Stoppe Service“, Toast.LENGTH_LONG).show();
}
// We return the binder class upon a call of bindService
#Override
public IBinder onBind(Intent arg0) {
return mBinder;
}
public class MyBinder extends Binder {
Fadenzieher getService() {
return Fadenzieher.this;
}
}
}
The whole application crashes immediately.
How do I run a task every 20 seconds within an intentservice ?
That is not an appropriate use of IntentService. Use a regular Service, please.
It works one time - but then the service stops & the application crashes when the handler-loop starts again after 20 seconds
IntentService shuts down when onHandleIntent() returns, which is why this is breaking for you. Use a regular Service, please.
Also:
Please allow the user to configure the polling period
Make sure that this service will shut down when the user no longer wants it to be running
I need a service that should always be running till its stopped explicitly by my activity and should start again even if it is stopped due to some issue (START_STICKY flag). This service should continuously do something (every couple of seconds) using a TimerTask. I ended up with the following code.
public class SomeService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
TimerTask timerTask;
final Handler handler = new Handler();
Timer timer = new Timer();
#Override
public void onCreate() {
// code to execute when the service is first created
super.onCreate();
}
#Override
public void onDestroy() {
// code to execute when the service is shutting down
super.onDestroy();
}
#Override
public void onStart(Intent intent, int startid) {
// code to execute when the service is starting up
timerTask = new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
//KEEP RUNNING SOME ERRANDS HERE
}
}
});
}
};
timer.scheduleAtFixedRate(timerTask, 100L, 1700L);
}
}
Is there anyway that I can optimize this to run continuously?
Running every second sounds pretty excessive, but is there a reason why you don't use the AlarmManager to trigger an IntentService? Then the system would be responsible for triggering your service reliably. Whether you can achieve reliable 1 second retriggers, I don't know. Seems like a bad idea for the reasons Mark is mentioning in the other answer.