I am new to Android. Can anyone tell me how to execute a message every 5 seconds. I have tried this code, but it's not showing anything on my emulator. What should I be doing instead?
while(true) {
Toast.makeText(this, "hi", Toast.LENGTH_SHORT).show();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
You should not call Thread.sleep() from the GUI thread. Never do this. Use a handler for such thing.
private Handler handler = new Handler();
private Runnable runnable = new Runnable() {
public void run() {
doStuff();
/*
* Now register it for running next time
*/
handler.postDelayed(this, 1000);
}
};
I prefer this way to using timers because the Timer class introduces a new thread and it is now fair to do this.
Is that the sum of your code? What are you setting your activity view to? Android implements an alarm/scheduling service which will be much more friendly to battery life than trying to implement your own.
Related
I need to call the speak method every 5 minutes, then i want to run in background the async method called callspeak, that calls back the speak method(a public method of a different class). It has to loop every 5 minutes
class callSpeak extends AsyncTask<String, Void, String> {
activityAudio a = new activityAudio();
#Override
protected String doInBackground(String... strings) {
try
{
while (true){
a.speak();
Thread.sleep(300000);
}
}
catch (InterruptedException e)
{e.getMessage();}
return null;
}
}
If you want to run the method only when the app is open, you can simply use TimerTask.
Timer myTimer = new Timer ();
TimerTask myTask = new TimerTask () {
#Override
public void run () {
// your code
callSpeak().execute() // Your method
}
};
myTimer.scheduleAtFixedRate(myTask , 0l, 5 * (60*1000)); // Runs every 5 mins
If you want to run it in background even if app is not running, you can use AlarmManager and repeat the task every 5 mins.
Hope it helps
You can do like this:
Handler mHandler = new Handler();
Runnable mRunnableTask = new Runnable()
{
#Override
public void run() {
doSomething();
// this will repeat this task again at specified time interval
mHandler.postDelayed(this, yourDesiredInterval);
}
};
// Call this to start the task first time
mHandler.postDelayed(mRunnableTask, yourDesiredInterval);
Don't forget to remove the callbacks from handler when you no longer need it.
The latest and the most efficient way to perform this, even if you come out of the activitiy or close the app is to implement the WorkManager from the AndroidX Architecture.
You can find more details here from the official documentation: Schedule tasks with WorkManager
This is my function who run a code every 2.5 seconds and check if a value seted to the true my progress will gone and ...
mHandler = new Handler();
continue_or_stop = true;
new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
while (continue_or_stop) {
try {
Thread.sleep(2500); // every 2.5 seconds
mHandler.post(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
if (sp.getFromPreferences("state_update").equals("true")) {
progress_main.setVisibility(View.GONE);
layout_main.setVisibility(View.VISIBLE);
btn_save_send.setVisibility(View.GONE);
getOutputs();
MDToast.makeText(getActivity(), "وضعیت دستگاه با موفقیت بروزرسانی شد", Toast.LENGTH_LONG, MDToast.TYPE_SUCCESS).show();
sp.saveToPreferences("state_update", "false");
Intent intent = new Intent(getContext(), MainActivity.class);
startActivity(intent);
}
// you can set continue_or_stop to false, for stop
}
});
} catch (Exception e) {
// TODO: handle exception
}
}
}
}).start();
now i want a time out for this method if the value not seted to true after a (for example 12 seconds) progress should gone and Toast it to user that something goes wrong and try again
You can check for the timeout based on the number of trials. Also using thread and Thread.sleep for running a periodic task is not a good practice.
To run a periodic task, you can post a Runnable to a Handler with some delay using postDelayed method.
private Handler mHandler = new Handler();
private int mTrials = 0;
private Runnable mPeriodicTask = new Runnable() {
public void run() {
// Do the check
mTrials += 1;
if (mTrials == /* timeout number */) {
// timeout
} else {
mHandler.postDelayed(this, 2500);
}
}
}
To run the task:
mHandler.postDelayed(mPeriodicTask, 2500);
Apparently this is more Android oriented, but I'll answer in general terms. And the other answer seems lacking the "12 seconds" timeout.
Well, you cannot really terminate a Thread immediatly, or forcely. Consider a Thread like a person, you need to kindly request him to terminate what he's doing. If he is able to do that, he will terminate, if not he will continue with its task.
As you're building the implementation of the task, you can check if someone asked you to terminate, with a special flag
Thread#isInterrupted()
Now, for this kind of thing using an ExecutorService is the better option, as it returns a Future<T> which can be canceled. E.g.
final ExecutorService executorService = ExecutorService.newSingleThreadExecutor();
final Future<?> future = executorService.submit(runnable);
You can then say to the Future "I want the result (which in your case is nothing), but with a timeout"
try {
future.get(12, TimeUnit.SECONDS);
} catch (final TimeoutException e) {
future.cancel(true);
}
The cancel(true) method call will set the interrupted flag of the Thread.
Now, maintaining the code you already have, you might simply want to replace
while (continue_or_stop)
with
while (!Thread.currentThread().isInterrupted())
Adjust to your needs.
I am making a news update app. For this it needs to be able to get updates on given periods of times. In this i have created a timer to run the callable plugin on given periods of time. Here i used a FixedThreadPool(executor).
For this what i want is to know when the future has finished its job so i can call the updateHeadlines method. but when i use finished.get() it blocks the gui. is there a way to know without blocking when the job has been finished to i can update the GUI after that.
for (Callable curplugin : plugin) {
new Timer(((NewsPlugin) curplugin).getUpdateFrequency(), new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Future<?> finished = executor.submit(curplugin);
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
try {
ArrayList<Headline> news = (ArrayList) finished.get();
updateHeadlines();
} catch (InterruptedException ex) {
Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
} catch (ExecutionException ex) {
Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
}).start();
}
There should be no need to combine Timer and ExecutorService, or to use a callback. Instead, schedule a Runnable that invokes the plugin, and schedules an invokeLater to display the result:
for (NewsPlugin plugin : plugins) {
Runnable task = () -> {
List<Headline> news;
try {
news = plugin.call(); /* There's really no need for plugin to be `Callable` */
} catch (Exception ex) {
ex.printStackTrace();
}
java.awt.EventQueue.invokeLater(this::updateHeadlines);
};
int period = plugin.getUpdateFrequency();
executor.scheduleAtFixedRate(task, period, period, TimeUnit.MILLISECONDS);
}
If you are using Java 8. There is a completeable future, In which you can register a callback, which will be called when task is completed. I think that will be helpful to you.
May be this will help you Callback with CompletableFuture
From Java 8 onward you could use a CompletableFutureto get a callback on completion for one shot tasks. Before Java 8 you could use Guava's ListenableFuture, which has similar functionality.
For recurrent tasks use an observable pattern, which is the counterpart to futures for handling multiple items returned from a recurring task. Java does not seem to offer a good OOTB solution here though.
I need to set a timeout for a block of code which will call an method in jar file.
I am using the following code
final Runnable stuffToDo = new Runnable() {
#Override
public void run() {
/* Do stuff here. */
jarclass.run();
}
};
final ExecutorService executor = Executors.newFixedThreadPool(1);
final Future future = executor.submit(stuffToDo);
//executor.shutdown(); // This does not cancel the already-scheduled task.
try {
future.get(1, TimeUnit.SECONDS);
}
catch (InterruptedException ie) {
/* Handle the interruption. Or ignore it. */
}
catch (ExecutionException ee) {
/* Handle the error. Or ignore it. */
}
catch (TimeoutException te) {
/* Handle the timeout. Or ignore it. */
}
if (!executor.isTerminated()){
executor.shutdownNow();
}
However the jarclass.run() somehow start another thread which keep running and show all the printout with pool-2-thread-1.
How can I completely shutdown the jarclass.run()??
Update:
I changed new Thread() to new Runnable. It still doesn't work.
What I am confusing is I don't know where jarclass start another thread and cannot handle it. When the code goes to executor.shutdownNow(), it does jump out and run the following code. But the jarclass.run() are still running.
I am not very good at English. Hope I made this clear.
Update:
Problem solved by this code:
Future<String> future = new FutureTask<String>(new Callable<String>() {
public String call() throws Exception {
jarclass.run();
return null;
}
});
try {
future.get(1, TimeUnit.SECONDS);
} catch (Exception e) {
e.printStackTrace();
}
Don't know why the former code fail......If anyone knows, we can still discuss.
Thanks for all the kindly replies. Really appreciate it.
You should not instantiate a Thread when using ExecutorService. Use Runnable instead:
final Runnable stuffToDo = new Runnable() { /* as it is now */ };
When you create a thread directly, it's not managed by the executor service you create later and that's why all the logs.
It's not safe kill thread directly, see Thread.stop() deprecated
Recomended way it to use a flag that can notify to thread that is time to stop.
If you can access to jar and modify code you can create a method named stop() in your jarclass using flag so when you need to kill process you can call jarclass.stop().
For example:
public class jarclass{
private boolean keepAlive = true;
public void run(){
keepAlive = true;
while(keepAlive){
//do work
}
}
public void stop(){
keepAlive = false;
}
}
I have a program where I am loading a file while at the same time I am displaying a window to inform the user that the file is being loaded. I decided to make a FileLoader class that was a SwingWorker which actually handled loading the file and a ProgressWindow that implements PropertyChangeListener to inform the user about the status of the SwingWorker that was passed into it.
My code currently looks like this:
FileLoader loader = new FileLoader(filePath);
new ProgressWindow(loader, "Loading File", "Loading File");
//ProgressWindow's constructor calls loader.execute() inherited from SwingWorker
doc = loader.get(); //GUI Freezes when called
The problem is that whenever I call loader.get(), it freezes the GUI, thus the progress bar in the Progress Window doesn't run and the whole thing is pointless. As far as I can tell, this is because the thread controlling the GUI is the same thread that calls loader.get(), which goes on hold while loader.execute() is running.
So far, I've tried creating a new thread for either the loader.get() command or the loader.execute() method, and calling SwingUtilities.invokeLater() on the thread, but then the whole program freezes.
I've considered creating a ChangeListener for when SwingWorker.isDone() and then running loader.get(), but this would require some reworking of my code that I would rather not do.
Could anyone tell me what the best way is to get this to work?
get() is like join() in that it will block until called, and will wait for the SwingWorker to finish before being called. Using it wrongly can completely nullify all the advantages of using a SwingWorker in the first place.
Solution: Don't call get() until you know that the SwingWorker is done with its processing, by either calling it in the SwingWorker's done() method, or if you need to call it from the calling code, then in a PropertyChangeListener that has been added to the SwingWorker when the SwingWorker's "state" property is SwingWorker.StateValue.DONE.
Something like:
final FileLoader loader = new FileLoader(filePath);
loader.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
if ("state".equals(evt.getPropertyName())) {
// since DONE is enum, no need for equals(...) method
if (evt.getNewValue() == SwingWorker.StateValue.DONE) {
try {
loader.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
}
});
new ProgressWindow(loader, "Loading File", "Loading File");
Note: code not compiled nor tested
Edit: try/catch added.
So far, I've tried creating a new thread for either the loader.get() command or the loader.execute() method, and calling SwingUtilities.invokeLater() on the thread, but then the whole program freezes.
If you call SwingUtilities.invokeLater() on the thread that will execute the thread in the EDT which freezes the GUI. Instead, run the thread by calling it's start() method and only use SwingUtilities.invokeLater() when you need to update the progress bar in the PropertyChangeListener.
I have create a WorkerThread class which take care of Threads and GUI current/main thread .
i have put my GUI application in construct() method of WorkerThread when an event fire to start XXXServer then all threads are activate and GUI work smoothlly wihout freeze. have a look.
/**
* Action Event
*
* #see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*/
public void actionPerformed(ActionEvent ae) {
log.info("actionPerformed begin..." + ae.getActionCommand());
try {
if (ae.getActionCommand().equals(btnStart.getText())) {
final int portNumber = 9990;
try {
WorkerThread workerThread = new WorkerThread(){
public Object construct(){
log.info("Initializing the Server GUI...");
// initializing the Server
try {
xxxServer = new XXXServer(portNumber);
xxxServer.start();
btnStart.setEnabled(false);
} catch (IOException e) {
// TODO Auto-generated catch block
log.info("actionPerformed() Start button ERROR IOEXCEPTION..." + e.getMessage());
e.printStackTrace();
}
return null;
}
};workerThread.start();
} catch (Exception e) {
log.info("actionPerformed() Start button ERROR..." + e.getMessage());
e.printStackTrace();
}
} else if (ae.getActionCommand().equals(btnStop.getText())) {
log.info("Exit..." + btnStop.getText());
closeWindow();
}
} catch (Exception e) {
log
.info("Error in ServerGUI actionPerformed==="
+ e.getMessage());
}
}