in the beginning I thought it would be fairly simple, but I guess it's not.
I want to call a URL every 10 minutes, either when the app is in the background or
in the foreground. How can I realize this?
I'd use a Service with a Handler inside. Using directly Threads is another approach but it's more likely it will be killed if the Android OS needs to free memory.
The Handler part would be something like this:
boolean stopHandler = false;
Runnable runnable = new Runnable() {
#Override
public void run() {
// Do whatever you need
...
if (!stopHandler) {
handler.postDelayed(this, 600000); // 10 minutes
}
}
};
In iOS 7 you can schedule background operations for periodically fetching data from the network. This tutorial is an example of scheduling background fetch operations -
Related
Currently, in my main app, I am sending multiple texts to status bar object.
My status bar object, is going to display multiple texts sequentially, with sleep time of N seconds for each display interval.
Here's my implementation in my main app.
public synchronized void setNextText(final CharSequence text) {
if (executor == null) {
executor = Executors.newSingleThreadExecutor();
}
executor.execute(new Runnable() {
#Override
public void run() {
Fragment fragment = getTargetFragment();
if (fragment instanceof OnStatusBarUpdaterListener) {
((OnStatusBarUpdaterListener)fragment).setNextText(text);
try {
// Allow 1 seconds for every text.
Thread.sleep(Constants.STATUS_BAR_UPDATER_TIME);
} catch (InterruptedException ex) {
Log.e(TAG, "", ex);
}
}
}
});
}
Now, I would like to have the same behavior in app widget. I was wondering, is using Executor being recommended in app widget environment? If not, what class I should use to achieve the similar objective?
I do have experience in using HandlerThread + AlarmManager in app widget. It works good so far. However, the operation done by the runnable is one time. It doesn't sleep and wait.
The following is the code which I use to update stock price in fixed interval.
// This code is trigger by AlarmManager periodically.
if (holder.updateStockPriceHandlerThread == null) {
holder.updateStockPriceHandlerThread = new HandlerThread("updateStockPriceHandlerThread" + appWidgetId);
holder.updateStockPriceHandlerThread.start();
holder.updateStockPriceWorkerQueue = new Handler(holder.updateStockPriceHandlerThread.getLooper());
holder.updateStockPriceWorkerQueue.post(getUpdateStockPriceRunnable(...
}
However, I have a feeling that, for use case "display multiple texts sequentially, with sleep time of N seconds for each display interval", AlarmManager might not be a good solution. Imagine I have 100 texts. Having to set 100 alarms for 100 texts doesn't sound good...
An AppWidgetProvider is a subclass of BroadcastReceiver. Once your callback (e.g., onUpdate()) returns, your process can be terminated at any point.
If that is not a problem — if you fail to finish the semi-animation that you are doing, that's OK — using an Executor from onUpdate() could work.
If you want to make sure that the text changes go to completion, delegate the app widget updating to a Service, where you use your Executor. Call stopSelf() on the Service when you are done, so it can go away and not artificially keep your process around.
Well the singleThread instance work creates an Executor that uses a single worker thread. meaning only thread to process your operation. But in you case use at least two. Your operations sounds expensive.
To conclude your question stick with the executor service as it thread safe.
What I want to do:
I am wanting to use a worker-thread to regularly update a textfield in the UI Thread. Let's say, every 2 seconds for 30 seconds. I need the 30 second countdown to happen even if the app is not on the foreground. For now, I am evaluating the merits of two different approaches (both using worker-threads) in implementing this. I won't post the full code here to simplify things and also because I am not asking to find any problem in my code. Both solutions work fine.
Solution #1 - use Thread.sleep() inside a for loop
for (int i = 30; i > 0; i-=2) {
Message msg = mHandler.obtainMessage(MSG_ID, i, 0);
msg.sendToTarget();
try {
Thread.sleep(2000);
} catch(Throwable t) {
// catch error
}
}
Solution #2 - use CountDownTimer
Looper.prepare()
new CountDownTimer(30000, 2000) {
public void onTick(long millUntilFinish) {
int seconds = (int)(millUntilFinish);
Message msg = mHandler.obtainMessage(MSG_ID, seconds, 0);
msg.sendToTarget();
}
public void onFinish() {
// left blank for now
}
}.start();
Looper.loop();
My Question
While both work, I am wanting to know if there is a "better" or a "preferred" way to do it for whatever reason. I am thinking there may be areas particularly in battery life but also in performance, accuracy or code design where one solution is better than the other.
What I have done so far to answer this question
My own evaluation so far from reading this SO question and CountDownTimer's documentation are that since both are executed on the worker-thread, both have no ANR possibility. Both solutions will also gaurantee that one "update" will happen only after the previous update has finished. Unfortunately, this is all I have and hoping if anyone can help or guide me to an insightful and/or similar SO question I may have overlooked or was unsuccessful in finding.
I write this question a bit cautiously as I don't have a problematic code which requires debugging but I think this falls within SO's category of a "specific programming problem", which hasn't been answered, and not included in the list of off-topic answers.
1.Calling Thread.sleep pauses the thread execution for a while where as countdown timer actually uses callbacks to notify timer expiry events and is asynchronous in nature.
2.If the thread execution pauses, you will not be able to use that specific thread for any other operation until the sleep timeout hence it is not recommended to use Thread.sleep approach. Obviously there is a load on cpu if it has to resume the thread execution and pause it.Where as in the case of countdown timer the thread continue to be in execution/idle state and as when events occur it fires to the respective listeners.
call Thread.sleep() method is not good idea beacuse ii sleep the UI Thread and disadvantage of CountDownTimer is, It Will stop when ur screen is off hence instead of this two try Handler for that like this
Handler handler;
Runnable runnable;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handler = new Handler();
Runnable runnable = new Runnable() {
#Override
public void run()
{
if (dataReceived)
{
cancelHandler();
}
}
};
handler.postDelayed(runnable, 100);
}
public void cancelHandler()
{
handler.removeCallbacks(runnable);
}
I have a service on the app which needs to run indefinitely - even when app is closed. It's going to ping a network source, if a state changes then the service must trigger a notification. The loop triggering the pings in the service is user chosen, with the smallest value of 5000ms (5 Seconds). I have the pings on a separate thread (off the UI thread) with calls to a handler thread to post toasts (temporarily while programming) to the UI thread.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast successMessage = Toast.makeText(this, "Service Started", Toast.LENGTH_SHORT);
successMessage.show();
//sendToastOnUIThread(1000);
new Thread(new Runnable(){
public void run() {
while(true) {
try {
Thread.sleep(GLOBAL_PING_TIMER);
} catch (InterruptedException e) {
e.printStackTrace();
}
sendToastOnUIThread();
//Code for pings here...
}
}
}).start();
return START_STICKY;
}
Above you can see my onStartCommand from the service - when testing this, I only used the code above and left out my code to ping the network source etc.
Incase you wonder whats in 'sendToastOnUIThread();'
public void sendToastOnUIThread(){
Handler h = new Handler(AutoPingServerService.this.getMainLooper());
h.post(new Runnable() {
#Override
public void run() {
Toast.makeText(AutoPingServerService.this,"Servers Pinged",Toast.LENGTH_SHORT).show();
}
});
}
So when this service is running, I get the toasts every 5 seconds, but the service memory just keeps stacking up (seems to cap at 8.5mb) but starts off around 1mb and just builds up around 0.1mb per loop. Am I making too many threads somehow? There should only be the UI thread, the new thread to handle the pings and the handler thread to post toasts when I need them (this will be replaces with notifications once it works)
Open to ideas - fairly new to android development, I wouldn't be surprised if i'm using all the wrong thread types. Possibly this is normal?
EDIT: Spelling.
Okay update for anyone curious:
The memory does get wiped after a while (pweh) as you'll reach a terminal capacity. Not sure if this is ideal but hey - I'm not going to sell it for millions, if the app crashes, I'll update this post. Don't fix what's not broken eh?
Anyway - #Deev kindly said I should move to an IntentService, I did not. I possibly will in the future, but this method works (Although it does look simpler to use a IntentService).
Is it fine to do following if we think about efficiency?
new Runnable() {
#Override
public void run() {
try {
final Runnable uitask = new Runnable() {
public void run() {
//sth that modifies UI
}
};
for (...) {
context.runOnUiThread(uitask);
Thread.sleep(...);
}
} catch (Throwable t) {
}
}
}
I'm most concerned about that runOnUi might create new thread each time, which would be very bad? Am I right or it smarter like ThreadPool?
Well, runOnUiThread doesn't create new threads, it is starting your runnable on the existing UI thread.
but instead of your code you could just do
void onCreate(..) {
...
mHandler = new Handler();
}
for (...) {
mHandler.postDelayed(uitask, DELAY * i++);
}
I'm most concerned about that runOnUi might create new thread each
time, which would be very bad?
Well. It depends what you want to achieve. In Android, native threads are not much efficient. There are more effective ways how to do background work (SDK provides them).
If you want to do some periodical work you can use Handler to achieve your goal. Just create only one Runnable and then you can send request for periodical callbacks. Another solution is to use Services which run in background. They're directly designated for long-running tasks and provide very handy way for background processing.
Sometimes you need to inform user with some information about current progress in your tasks so in this case you can simply use mentioned Handler or AsyncTask.
I think your solution is not clean and efficient. If you'll create for example 40 Threads, your work won't be faster or more efficient at all. Your GB will scream and application will take the greater part of CPU and high battery consumption is something you shouldn't allow.
I need to write a helper method which I can use in various places in the app to essentially make it 'sleep' for N milliseconds.It looks like Handler.postAtTime may be one way to do it, but I'd like any code snippets if available.
You did not say why you need your app to "sleep".
Assuming you need to run a task after some time:
Handler h = new Handler();
h.postDelayed(new Runnable() {
public void run() {
// do something here
}
}, 1000); // 1000 ms delay
If you don't mind blocking the thread, an alternative to Thread.sleep() is SystemClock.sleep().
Benefit is that it's a one-liner, as it ignores the
InterruptedException so you don't need to handle it.
More info on http://developer.android.com/reference/android/os/SystemClock.html.
As already stated, you should avoid calling this on the main UI thread as it will cause your app to become unresponsive and potentially show the dreaded dialog we all hate to see (please wait or force close.)
Are you looking for something like this?
try {
//Put the thread to sleep for the desired amount of time (milliseconds)
Thread.currentThread().sleep(1000);
}
catch(InterruptedException ie){
}
This will put the thread you are calling it from to sleep for the amount of time you specify.