I have a Foregound Service with a broadcaster.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Service
Log.d("Service","Service started");
startTime = intent.getLongExtra("STARTTIME", 0);
endTime = intent.getLongExtra("ENDTIME", 0);
isRunning = true;
postNotification();
// Broadcaster
handler.removeCallbacks(updateRunnable);
handler.postDelayed(updateRunnable, DELAY);
return START_STICKY;
}
When I try to stop the service the onDestroy() runs and all is fine, but the updateRunnable keeps on going so the broadcasting still occurs.
private Runnable updateRunnable = new Runnable() {
public void run() {
Log.d("Service", "run");
currentTime = System.currentTimeMillis();
if(endTime > 0 && (currentTime-startTime) >= endTime) {
isRunning = false;
// Alarm
AlarmNotification alarmNotification = new AlarmNotification(context);
alarmNotification.startAlarm();
// Notification
AppNotification notify = new AppNotification(context);
notify.stopNotification();
update();
// Tried them all:
stopService(intentBroadcaster);
stopForeground(true);
stopSelf();
} else {
update();
}
handler.postDelayed(this, 1000); // 1 seconds
}
};
As you can see I have tried every stop command I can think of. What am I doing wrong here? How do I stop the broadcasting / runnable?
Your broadcaster keeps running because your application process is still running, so your thread will keep on executing unless you told it not to.
It's easy to stop your thread, in your run method:
private boolean shouldContinue = true;
private Runnable updateRunnable = new Runnable() {
public void run(){
// ... whaterver your doing
if(shouldContinue){
handler.postDelayed(this, 1000);
}
}
};
public void onDestroy(){
shouldContinue = false;
}
Related
I have a activity that call startService(intent) and this one in his method onStatCommand() create a thread that checks the running app every second.
The problem is that the thread freze the creation of the activity and the screen show only a white screen. If i delete the for(;;) statment in the thread it works. why?
here there is the onStartCommand() code:
#Override
public int onStartCommand(Intent intent,int flags,int startid)
{
super.onStartCommand(intent,flags,startid);
final Thread thread= new Thread(){
#Override
public void run()
{
Context context = getApplicationContext();
for(;;) {
long current = System.currentTimeMillis();
UsageStatsManager usageStatsManager = ((UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE));
for (UsageStats usageStats : usageStatsManager.queryAndAggregateUsageStats( current - 1000*2, current).values()) {
Log.i("Path changed name",usageStats.getPackageName());
if(usageStats.getPackageName()=="com.android.chrome")
{
Log.i("Path name",usageStats.getPackageName());
stopSelf();
break;
}
}
try {
currentThread().sleep(1000);
}catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
};
thread.run();;
return 0;
}
There is problem with Thread code, You should call Start method to start a new Thread not run.
Problem code:
thread.run();
Fixed code:
thread.start();
I am using a DatagramSocket to receive packets in background (using service). but it does not receive when my phone is locked while when I add a ScheduledTask to start the thread every 1 sec, it works well. Why it doesn't work in first case and how can I fix it whitout starting the Tread every 1 sec?
public class RecThread2 implements Runnable {
public void run() {
while(running){
try {
int MESSAGE_LEN = 60;
byte[] recvBuffer = new byte[MESSAGE_LEN];
DatagramPacket datagram = new DatagramPacket(recvBuffer,
MESSAGE_LEN);
socket1.receive(datagram);
String recvdString = new String(recvBuffer);
Log.i("Recieved", recvdString);
mess = recvdString;
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
and I run the thread here:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "receiveTag");
wl.acquire();
Thread sThread2 = new Thread(new runSoc1());
sThread2.start();
return super.onStartCommand(intent, flags, startId);
}
But when I use the following code to run Thread periodically it works even when the phone is locked (and I remove the while(running) from the Thread code):
time = new Timer();
ScheduledTask st = new ScheduledTask();
time.schedule(st, 0, 1000);
and :
public class ScheduledTask extends TimerTask {
public void run() {
Thread sThread2 = new Thread(new RecThread2());
sThread2.start();
}
}
I am trying to create a service with background task. 24 hrs once the thread would start and do the process.
I have tried like this. but its not worked.
public class MyService extends Service {
int counter = 0;
static final int UPDATE_INTERVAL = 10 * 1000; // / 1000 = 1 second
private Timer timer = new Timer();
Home home;
private boolean isRunning = true;
#Override
public IBinder onBind(Intent intent) {
// Not implemented...this sample is only for starting and stopping
// services.
// Service binding will be covered in another tutorial
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
// Announcement about starting
Toast.makeText(this, "Starting the Demo Service", Toast.LENGTH_SHORT)
.show();
// Start a Background thread
isRunning = true;
// Thread backgroundThread = new Thread(new BackgroundThread());
BackgroundThread();
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
// Stop the Background thread
isRunning = false;
// Announcement about stopping
Toast.makeText(this, "Stopping the Demo Service", Toast.LENGTH_SHORT)
.show();
}
private void BackgroundThread() {
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
// TODO Auto-generated method stub
Calendar c = Calendar.getInstance();
String month = String.valueOf(c.get(Calendar.MONTH) + 1);
String year = String.valueOf(c.get(Calendar.YEAR));
String day = String.valueOf(c.get(Calendar.DAY_OF_MONTH));
String months = null;
if (month.startsWith("0") || month.startsWith("1")) {
months = year + "-" + month + "-" + day;
home.loadCalender(months);
} else {
months = year + "-" + "0" + month + "-" + day;
home.loadCalender(months);
}
}
}, 0, UPDATE_INTERVAL);
/*
* counter = 0; while(isRunning) { System.out.println(""+counter++);
* //Thread.currentThread().sleep(5000);
*
* }
*/
System.out.println("Background Thread is finished.........");
}
}
In my main activity, i have started the Service...
plz help me to do this task.
Use AlarmManager to schedule your alarm to occur once per day, using setRepeating() (or perhaps setInexactRepeating(). Please do not waste the user's RAM trying to have a service running all of the time watching the clock tick.
Friends,
I set up an AlarmManager within my application. The AlarmManager is scheduled to start a background Service every xx , here 1 Min. Its working quite well for a while. But freuqently I get an Error: thead already started / scheduled.
I have the feeling that i might dont use destructors correct.
Would be grateful for your support.
Heres my code of the Activity that starts the AlarmManager
PendingIntent pi;
AlarmManager mgr;
mgr=(AlarmManager)ctx.getSystemService(Context.ALARM_SERVICE);
Intent i=new Intent(DataCollectionActivity.this, HUJIDataCollectionService.class);
pi = PendingIntent.getService(DataCollectionActivity.this, 0, i, 0);
........
if (viewId == R.id.b_startService) {
mgr.cancel(pi);
mgr.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() , 1* 60* 1000, pi);}
........
if (viewId == R.id.b_stopService) {
mgr.cancel(pi);}
and heres the important code of my Service:
private Runnable LocationUpdateTimerTask = new Runnable() {
public void run() {
Log.i(ctx.getString(R.string.app_name),
"HUJIDataCollectionService, 1 LocationUpdateTimerTask, start");
setuplistenerandrequestupdates();
mHandler.removeCallbacks(LocationUpdateTimerTask);
}
};
private Runnable SendDataStopLocationUpdatesTimerTask = new Runnable() {
public void run() {
sendDataToServer();
mHandler.removeCallbacks(SendDataStopLocationUpdatesTimerTask);
ServiceIntervalTimerTask.cancel();
Intent service = new Intent(ctx, HUJIDataCollectionService.class);
stopService(service);
}
};
private TimerTask ServiceIntervalTimerTask = new TimerTask() {
#Override
public void run() {
// remove old timer updates
mHandler.removeCallbacks(LocationUpdateTimerTask);
mHandler.removeCallbacks(SendDataStopLocationUpdatesTimerTask);
// Start TimerTasks delayed
mHandler.postDelayed(LocationUpdateTimerTask, 1000);
mHandler.postDelayed(SendDataStopLocationUpdatesTimerTask,
conf_LocationUpdatePeriodInSec * 1000);
}
};
#Override
public void onDestroy() {
super.onDestroy();
startDataCollectionServiceIntervallTimer.cancel();
startDataCollectionServiceIntervallTimer = null;
// Remove all kinds of updates
mHandler.removeCallbacks(LocationUpdateTimerTask);
mHandler.removeCallbacks(SendDataStopLocationUpdatesTimerTask);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
startDataCollectionServiceIntervallTimer = new Timer(
"HUJIDataCollectionServiceStartTimer");
startDataCollectionServiceIntervallTimer.schedule(ServiceIntervalTimerTask,
1000L, conf_sampleTimeInMin * 60 * 1000L);
mHandler = new Handler();
return START_STICKY;
}
When you start a service it runs in the backround even when app is destroyed. Where and when you call your Alarm manager??? But if you often call a service i think that you will have memory leak or something like that...
I think i found the solution for the problem my own.
First i bypassed the problem by starting a Broadcastreceiver. But this is not an answer to the described problem.
Here is a solution:
public void pause(){
while(true){
try { // goes through this thread until our thread died
ourthread.join(); //Blocks the current Thread (Thread.currentThread()) until the receiver finishes its execution and dies.
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
Thanks for the support anyways!!!
Cheers
I have a service B that sends a specific number of messages in a fixed interval.
this service is called from another service A.
the code used in service A is
#Override
public void onStart (Intent intent,int startid)
{
Toast.makeText(this, "Service A Running onStart", Toast.LENGTH_LONG).show();
Thread MessagesThread = new Thread(new Runnable()
{
public void run()
{
ApplicationPreferences AppPrefs = new ApplicationPreferences(getApplicationContext());
int NumberOfMessagesToSend = Integer.parseInt(AppPrefs.getNumberOfMessagesToSend());
int NumberOfSentMessages;
for (NumberOfSentMessages = 0 ; NumberOfSentMessages < NumberOfMessagesToSend; NumberOfSentMessages++ )
{startServiceB();
}
}
});
MessagesThread.start();
}
public void startServiceB()
{
final Intent sendingMessages = new Intent(this, ServiceB.class);
startService(sendingMessages);
}
the toasts are to keep track of what is happening
The code in service B is as follow
#Override
public void onStart(Intent intent, int startId)
{
super.onStart(intent, startId);
Toast.makeText(getApplicationContext(), "Service B at start ", Toast.LENGTH_LONG).show();
new CountDownTimer(30000,1000)
{
public void onTick (long millisUntilFinished) {}
public void onFinish()
{
showToast();
}
}.start();
}
the showToast() function is as follow
public void showToast()
{
Toast.makeText(getApplicationContext(), "Service B in timer", Toast.LENGTH_LONG).show();
}
As I said I am using the toasts to keep track of what's happening. the problem is when running it, i am getting the first toast (service B at start) 10 times consequently then the second one (service B in timer) 10 times consequently with no time between them.
how do i make each of this toasts appear once every 30 seconds?
Ok, so the final answer could be something like this:
Call only once the B service and in it we will have the handler that will loop at an interval of 30 seconds..
Service B code:
int loop = 5;
int counter = 0;
Handler myHandler;
Runnable run;
#Override
public void onStart(Intent intent, int startId)
{
super.onStart(intent, startId);
Toast.makeText(getApplicationContext(), "Service B at start ", Toast.LENGTH_LONG).show();
myHandler = new Handler();
run = new Runnable()
{
public void run()
{
if (counter<loop){
showToast();
counter++;
} else {
myHandler.removeCallbacks(run);
}
}
};
myHandler.postDelayed(run, 30000);
}
I hope this helps someone else too!
If you want to make a toast every 30 seconds than you can do it by using a handler:
Handler myHandler = new Handler();
Runnable run = new Runnable()
{
public void run()
{
showToast();
}
};
myHandler.postDelayed(run, 30000);
If you have problem with this just post here and I will try to help you..