I am trying to give a LocationClient a two-minute period to connect before calling getLastLocation on it. Initially I implemented this with a Timer (and TimerTask), but because Timers do not work in sleepmode, I would like to translate it to an AlarmManager. However, I am a bit confused as to how to do this, considering an AlarmManager calls another class, whereas I want to remain in the same class and simply delay for a two-minute period.
This is how it looks with a Timer.
Timer theTimer = new Timer();
theTimer.schedule(new TimerTask() {
#Override
public void run() {
if(checkIfGooglePlay() && checkTime()) {
getPostLocation();
stopSelf();
mLocationClient.disconnect();
}
}
}, TWO_MINUTES);
Alarm Manager calls a broadcast receiver via a pending intent. Just make that BroadcastReceiver implementation a private subclass of the class that registers it. That way it has full access to class member variables and functions.
You may try using Java's Thread.sleep(). It's a static method so you don't need to instantiate a new Thread. It throws a InterruptedException, which, in simpler cases, shouldn't bother you.
From http://developer.android.com/reference/java/lang/Thread.html:
Causes the thread which sent this message to sleep for the given interval of time (given in milliseconds and nanoseconds).
Related
I'm writing application which need to periodically (around about 15min) download JSON data from server in the background and notify user with Notification.
I don't have a lot of experience with android coding and I'm asking how I should do that correctly and with best coding practises?
I don't need too much precision, AlarmManager with inexact repeating should work perfectly. I know how use BroadcastReceiver to receive BOOT_COMPLETE and start service. However I don't know how can I set AlarmManager to run specific action in Service and if I should do this in that way? I don't want use android mechanisms in way that has not been provided.
Use the class TimerTask:
private TimerTask timerTask;
private final long PERIOD_TIME=1000 * 60 * 15; //15min
#Override
public void onCreate() {
Timer timer = new Timer();
timerTask = new TimerTask() {
#Override
public void run() {
//Your request JSON
}
};
timer.scheduleAtFixedRate(timerTask, 0, PERIOD_TIME);
}
Use AsyncTask for getting info from server. In onReceive method of Receiver class create new AsyncTask object and execute it as below:
private class GetContent extends AsyncTask<String,Void,String> // Assume class name
extras = extras.getString("json");
GetContent().execute(extras);
In default function of AsyncTask doInBackground, retrive data and return JSON. In the other default function onPostExecute, create a NotificationCompat.Builder object and notify.
In the onHandleIntent of my my IntentService class, I created handle containing a runnable which should be done after 20 seconds. Unfortunatly my service sleeps or is destroyed before this period.
I tried also with the CountDownTimer, but i had the same problem.
Do someone have any idea can I make the onHnadleIntent waiting? Thank you!
This is the code:
public class MyService extends IntentService {
//...
#Override
protected void onHandleIntent(Intent workIntent) {
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
Log.i("20 seconds later","I am here");
}
}, 20000);
//...
}
//...
}
Don't use an IntentService. It is not designed for your scenario. Use a regular Service. Put your code in onStartCommand(). At the bottom of your run() method, call stopSelf() on the Service instance to shut it down.
You need to stop onHandleIntent from returning until the Runnable has completed. This can be achieved by using a CountdownLatch, which awaits at the end of your onHandleIntent method, and gets released at the end of the run method.
NOTE: this will cause the intent service to not process other Intents you sent it until the previous one has completed (after 20 seconds).
You may also want to obtain a partial wakelock at the start of onHandleIntent and release it at the end.
For example my app, it starts and runs the service(which is meant to check the database for new messages) but as far as I know you can have a AlarmManager to keep opening the Service if so is not opened.
But can you have aAlarmManager inside the Service class to keep on checking for new message in the database? Instead of re-opening the Service class just keep checking the database?
I want to know if it is possible to have a AlarmManager inside the Service class to keep checking the database every X seconds, because the Service will open when the App is Launched
The real question:
Is it possible to have a AlarmManager inside the Service class that runs a Method() to check a database?
Use a Timer
Timer myTimer = new Timer();
myTimer.schedule(new TimerTask() {
#Override
public void run() {
/**
*
*Do something. CODE HERE
*/
}
}, 0, 30000); //30000 = 30 Seconds Interval.
If I create a service in my app's onCreatelike this:
Intent srv = new Intent( this, MyService.class );
startService( srv );
how do I get a reference to the service object and how does the service object reference the app which launched it?
(Yes, I have listed the service in my AndroidManifest).
There are a few ways to handle this. You can bind to the service (bindService) where you will be called back with an IBinder interface.
Another approach is to just keep calling startService() with different intent data as a way of messaging to the service, with intent extra data containing message specifics.
Finally, if you know the service is in the same process, you can share the service instance in some static memory.
Building a Service
First of all, we need to create the Service in the AndroidManifest.xml file. Remember, that every Activity, Service, Content Provider you create in the code, you need to create a reference for here, in the Manifest, if not, the application will not recognize it.
<service android:name=".subpackagename.ServiceName"/>
In the code, we need to create a class that extends from “Service”
public class ServiceName extends Service {
private Timer timer = new Timer();
protected void onCreate() {
super.onCreate();
startservice();
}
}
This is a way to create Services, there are others ways, or the way I use to work with them. Here, we create a Timer, that every X seconds, calls to a method. This is running until we stop it. This can be used, for example, to check updates in an RSS feed. The “Timer” class is used in the startservice method like this
private void startservice() {
timer.scheduleAtFixedRate( new TimerTask() {
public void run() {
//Do whatever you want to do every “INTERVAL”
}
}, 0, INTERVAL);
; }
Where INTERVAL, is the time, every time the run method is executed.
To stop the service, we can stop the timer, for example, when the application is destroyed (in onDestroy())
private void stopservice() {
if (timer != null){
timer.cancel();
}
}
So, this application will be running in the background...
I need to run a periodic task in an Android application. I currently use a timer like this:
final Handler guiHandler = new Handler();
// the task to run
final Runnable myRunnable = new Runnable() {
#Override
public void run() {
doMyStuff();
}
};
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
guiHandler.post(myRunnable);
}
}, 0, 30000); // run every 30 seconds
This does exactly what I need, but there is a problem: if I change the time on the emulator or phone, the timer stops running. This is what appears in the log when I change the time:
D/SystemClock( 331): Setting time of day to sec=1278920137
W/SystemClock( 331): Unable to set rtc to 1278920137: Invalid argument
Nothing about the timer being interrupted, but it clearly doesn't run anymore after the system clock has changed. I need the task to keep running all the time as long as the application is running.
How can I restart the timer if it gets stopped like this? There's no method on the Timer or TimerTask to check whether it's currently running, so I can't know when to reschedule it. Any ideas?
I think there are a few ways to do this. I wouldn't use the timer in either case.
You can use a handler to run your task in a postDelayed call. Your task would then have to re-register itself with the handler from within itself.
final int ONE_SECOND = 1000; // one second
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
... // do some stuff
if (expression) {
handler.postDelayed(this, ONE_SECOND);
}
}
}, ONE_SECOND);
This will keep the task running while your app is alive. You can also adjust the delayed rate in the postDelayed within the Runnable. This way is semi predictable as long as you make another Looper. Using the main thread may or may not be appropriate depending on what the task is.
There is also an AlarmManager, that you can gain access to via the Context interface, which is meant for recurring tasks tasks at more precise intervals. It's a little more complex to use but you get the flexibility of having use of the RTC and persisted repeatable tasks.
AlarmManager manager = mContext.getSystemService(Context.ALARM_SERVICE);
manager.setRepeating(AlarmManager.RTC,
<start_time_millis>,
<period_millis>,
pendingIntent);
For example, the pending intent can fire a broadcast intent that you can listen to elsewhere. You can create this pendingintent in the onCreate of your custom Application object and cancel the intent in the onTerminate().