I'm making one application where user needs to do some task while time is passing. How I was thinking of doing it is:
show task to user -> start counting seconds -> if task is not solved within certain seconds, application writes: "You failed".
I have only one solution in my head, since I didn't come across same till now -
show task to used and start thread with counting seconds and waiting, something like:
sleep(1000);
secondsCounter++;
if (secondsCounter => LIMIT){
write("You failed!");
}
Still, something tells me that this is not proper way of solving it. Is there other (better) way?
Use a handler for this:
// set this to true if user succeeds before time runs out.
boolean userSucceeded = false;
new Handler().postDelayed(new Runnable() {
public void run() {
if (!userSucceeded) {
// write("you failed")
}
}
}, 1000L); // 1 second
Related
I am following https://android.googlesource.com/platform/development/+/master/samples/WiFiDirectDemo.
Due to my own requirements ,I just want to run this following code multiple times.
When we click on the search button (cicled in red),The app starts searching for the available wifi peers as shown in the below image
I just want to automate this process every 2 seconds whether it has found some peer or not.
In the code of this Activity:
case R.id.atn_direct_discover:
if (!isWifiP2pEnabled) {
Toast.makeText(WiFiDirectActivity.this, R.string.p2p_off_warning,
Toast.LENGTH_SHORT).show();
return true;
}
final DeviceListFragment fragment = (DeviceListFragment) getFragmentManager()
.findFragmentById(R.id.frag_list);
fragment.onInitiateDiscovery();
manager.discoverPeers(channel, new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
Toast.makeText(WiFiDirectActivity.this, "Discovery Initiated",
Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(int reasonCode) {
Toast.makeText(WiFiDirectActivity.this, "Discovery Failed : " + reasonCode,
Toast.LENGTH_SHORT).show();
}
});
return true;
This is the code.
One thing I tried is put everthing in a while(true) loop but i always crash the app.
Then I used a stop button and a flag.This button sets flag to false but it still is not working.
I tried the solution of this :How to automatically Click a Button in Android after a 5 second delay
It does not crash the app but the button only works when i manually click it.
Any suggestions Please ??
What I understood from your problem is you want the task to run without any user intervention to detect new peers and update your UI accordingly.
Run a Handler every 5 seconds when your app is in foreground to start a bound service for searching any new peer, the service will communicate the information back to the activity if it has found anything new or not. When you get the message on your Activity, stop the service and unbind it.
Please see the details about bound service here - https://developer.android.com/guide/components/bound-services.html
You can use Timer class & schedule it to run every 5 seconds. The idea is the timer task doesn't simulate button pressed, but it should does exactly same thing as when the button is pressed.
Assume your Activity class is named MyActivity. Place this in onCreate() of MyActivity class.
Timer myTimer = new Timer();
// schedule to run every 5000 milli seconds
myTimer.schedule(new TimerTask() {
#Override
public void run() {
MyActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
// any code that update UI goes here
// Eg: displaying progress indicator, show "finding Peers" text
....
}
});
// the rest of "discover" logic goes here
}
}, 0, 5000);
I've a TextView where I want to set a message according to time ( hour of day). To achieve this I'm using-
Thread t2 = new Thread() {
#Override
public void run() {
try {
while (!isInterrupted()) {
Thread.sleep(3600000);
handler.post(new Runnable() {
#Override
public void run() {
int hour=Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
update(hour);
}
});
}
} catch (InterruptedException e) {
}
}
};
t2.start();
where update(hour) is used to update the message.
This works fine, however, the updating is done depending on the launching time. For example, the message should update at time 20:00. But if the app is launched at 19:59, the updating takes place at 20:59.
If I use Thread.sleep(1000) it works just as expected. But I feel like wasting resource by running the thread every second just to look for a 1 hour event. Is there any better way to do this?
Surely you need to check the current time, get the minutes past the hour, then work out from there when the next hour 00 will come. Then, just sleep time for those minutes, then for all the hours after that sleep for the full hour.
Take a look at AlarmManager.
The Alarm Manager is intended for cases where you want to have your application code run at a specific time, even if your application is not currently running.
I want to achieve the following task:
if (already wait for 3 seconds) {
// do the task
} else {
// keep waiting ...
if (user tap the UI widget) {
return; // do nothing
}
}
At first, I want to use handler, use sendMessageDelayed (Message msg, long delayMillis) to enqueue a message into the message queue after all pending messages before (current time + delayMillis). when the user taps, I removeMessages(int what). But it does not work.
Does anybody know how to achieve this? Thanks.
========================================================
Thanks all.
I found this solution works well, I was too careless to use the wrong Handler reference to removeMessages, so, it did not work.
I prefer to use the plain old Java API ScheduledExecutorService and ScheduledFuture:
// This schedule a runnable task in 3 seconds:
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
ScheduledFuture scheduledFuture = scheduledExecutorService.schedule(new Runnable() {
public void run() {
doSomethingUseful();
}
}, 3, TimeUnit.SECONDS);
... ...
// some times later if user tap the screen:
if (user tap the UI widget) {
if (!scheduledFuture.isDone())
scheduledFuture.cancel(true);
}
Hope this helps.
You could set a flag when the user taps, and when the handler message is received, check that flag.
You could also use a Timer, schedule a TimerTask, and cancel the task when the user taps.
I have following code snippet in my application activity.
If user is landing on activity for the first time then only thing that will happen is changing the boolean variable shouldSleep to true.
Thereafter, else part will be executed which contains generation of notification at every 60 seconds.
But the main problem is if I execute this code, the activity NEVER gets displayed as it keeps looping in else part and hence go on sleeping.
What I want is remaining application should run normally while every 60 seconds, else part of this method should be executed.I guess it has got something to do with AsyncTask but I don't have much idea about it.
Any idea how to do this? Thanks in advance for your help.
boolean shouldSleep=false;
private void ShowNotification()
{
//DO SOME TASK
if (shouldSleep)
{
Thread.sleep(60000);
//DO SOME TASK
}
else
{
shouldSleep = true;
}
/** Calling the method recursively so that it always runs. */
ShowNotification();
}
Maybe you can use a Timer object :
new Timer().schedule(new TimerTask() {
#Override
public void run() {
//This code is run all 60seconds
myBooleanVar = true;
//If you want to operate UI modifications, you must run ui stuff on UiThread.
Activity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Activity.this.changeUiStuff();
}
});
}
}, 60000);
Just use a Timer. Instead of a thread approach, you could run your task every 60s:
new Timer().schedule(task, delay, period);
with period = 60*1000
I have a function, AppHelper.isOnline(Context context), I call in various parts of my application to check that a session didn't timeout before making an HTTP request.
public void onClick(View v) {
Intent intent = null;
switch (v.getId()) {
case R.id.buttonPagamenti:
if (AppHelper.isOnline(this))
{
//here AppHelper.isOnline should have finished it's async task
intent = new Intent(this, OrdineCreaActivity.class);
this.startActivityForResult(intent, R.id.buttonPagamenti);
}
break;
...
Inside AppHelper.isOnline(), I am executing an AsyncTask that logs in, thus making a network request, which can't be run on UI because otherwise I get an exception. I need to wait for it to finish BEFORE resuming with the code inside the if. How can I do this ?
Problem is the activity starts firsts, then the AsyncTask executes, so when the activity expects a valid logged in session, it breaks.
You have two options:
Either use the AsyncTask's method get(long timeout, TimeUnit unit) like that:
task.get(1000, TimeUnit.MILLISECONDS);
This will make your main thread wait for the result of the AsyncTask at most 1000 milliseconds (as per #user1028741 comment: actually there is also infinetly waiting method - AsyncTask#get() which might also do the work for you in some cases).
Alternatively you can show a progress dialog in the async task until it finishes. See this thread (No need for me to copy past the code). Basically a progress dialog is shown while the async task runs and is hidden when it finishes.
You have even third option:" if Thread is sufficient for your needs you can just use its join method. However, if the task is taking a long while you will still need to show a progress dialog, otherwise you will get an exception because of the main thread being inactive for too long.
try using
if (AppHelper.isOnline(this))
{
while(!task.isCancelled()){
// waiting until finished protected String[] doInBackground(Void... params)
}
intent = new Intent(this, OrdineCreaActivity.class);
this.startActivityForResult(intent, R.id.buttonPagamenti);
}
For more information read http://developer.android.com/reference/android/os/AsyncTask.html
Rafiq's response did not work for me - the app hung. I think the reason has to do with the nature of isCancelled(): "Returns true if this task was cancelled before it completed normally." If the task completes normally (i.e. is not cancelled) then while(!task.isCancelled()) { } will loop forever.
To solve this create a Boolean flag that you instatiate to false and then flip to true in task.onPostExecute(). Then do while(!flag) { } before switching Activities. Additionally, if you'd like to give the main thread a 'break' to let the AsyncTask process a little faster, you can do try this:
while (!flag) {
try { Thread.sleep(100); }
catch (InterruptedException e) { e.printStackTrace(); }
}
It seems to be working well for me.
intent = new Intent(this, OrdineCreaActivity.class);
context.startActivityForResult(intent, R.id.buttonPagamenti);
Write the above lines in onPostExecute() of you AysncTask. Because if we are using AsyncTask it wont wait there until the task complete.