In my program, it is needed to receive user latitude and longitude as soon as GPS is Enabled... I'm using onGpsStatusChanged to constantly check GPS Status and the checking works... The only problem is that it tries to retrieve user location instantly, and it returns latitude 0.0 and longitude 0.0 cause it takes some seconds to get those informations... If I try to retrieve some seconds later using clickListener on a button it works perfectly...
Then I thought: If I could make the device wait some seconds after GPS is Enabled and only then retrieve the coordinates it would work...
But: If I use another Thread or AsyncTask (already tried both), it keeps returning 0.0 for coordinates, cause the real coordinates are cached into the Map's Main Activity Thread...
So, how to make android wait in the main Thread? I've tried 'wait(long)' and the app crashes. I'm trying to solve this for weeks and my time is running out... Some holy soul help me please
you can achieve that by using handler
int time=3000 // in milliseconds
Handler h=new Handler();
h.postDelayed(new Runnable() {
#Override
public void run() {
//here you can do the job
}
},time);
if you want to update the UI from the handler you will end up with an error but you can userunOnUiThread
runOnUiThread(new Runnable() {
#Override
public void run() {
//code to update the ui
}
});
good luck
i not recommend you handler,you can use Interface here.
where you get all values use pass it to your activity and use that one.
Here i have posted example just try to follow and use this way.
You can pass interval here according to your need.
public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 30000
and one more thing you can pass fastest interval that is also help you.
Thanks
I have been creating a simple Waiter class for it. It is really easy to understand and does the job very well. I post it for those who need it. just copy Waiter class and WaitListener interface and use it like I show.
Here is the Class:
import android.os.Handler;
import android.os.Looper;
public class Waiter {
WaitListener waitListener;
int waitTime = 0;
Handler handler;
int waitStep = 1000;
int maxWaitTime = 5000;
boolean condition = false;
public Waiter(Looper looper, final int waitStep, final int maxWaitTime){
handler = new Handler(looper);
this.waitStep = waitStep;
this.maxWaitTime = maxWaitTime;
}
public void start(){
handler.post(new Runnable() {
#Override
public void run() {
waitListener.checkCondition();
if (condition) {
waitListener.onConditionSuccess();
} else {
if (waitTime <= maxWaitTime) {
waitTime += waitStep;
handler.postDelayed(this, waitStep);
} else {
waitListener.onWaitEnd();
}
}
}
});
}
public void setConditionState(boolean condition){
this.condition = condition;
}
public void setWaitListener(WaitListener waitListener){
this.waitListener = waitListener;
}
}
And here is the Interface :
public interface WaitListener {
public void checkCondition();
public void onWaitEnd();
public void onConditionSuccess();
}
You can for example use it like that for a connection check:
ConnectivityManager mConnMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
final int result = mConnMgr.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, "enableMMS");
final Waiter waiter = new Waiter(getMainLooper(), 1000, 5000);
waiter.setWaitListener(new WaitListener() {
#Override
public void checkCondition() {
Log.i("Connection", "Checking connection...");
NetworkInfo networkInfo = mConnMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_MMS);
waiter.setConditionState(networkInfo.isConnected());
}
#Override
public void onWaitEnd() {
Log.i("Connection", "No connection for sending");
//DO
}
#Override
public void onConditionSuccess() {
Log.i("Connection", "Connection success, sending...");
//DO
}
});
waiter.start();
Related
I am currently building an app that plays music on a wifi speaker. The app can connect to multiple speakers, and each speaker plays different music.
Due to frequent loss in receiving the song playing progress sent by the speakers to the app, I have to run one timer for each speaker that is playing a music in order to keep track of the song progress continuously. So that every time I receive a song progress, I will just update the timer, and then the timer will start counting from the updated song progress.
This is the code that runs a timer.
public class SongTimer
{
Timer mTimer;
int count;
long duration;
int groupAddress;
SongTimerListener listener;
boolean timer;
private Handler mHandler = new Handler();
public interface SongTimerListener
{
public void onPositionCounted(int position);
public void onFinishCounting();
}
public SongTimer(int position, long duration, int groupAddress, SongTimerListener listener)
{
this.listener = listener;
this.count = position;
this.duration = duration;
this.groupAddress = groupAddress;
timer = true;
}
public void startTimer()
{
mTimer = new Timer();
mTimer.schedule(new TimerTask()
{
#Override
public void run()
{
if (timer)
{
if(count<=(duration/1000))
{
mHandler.post(new Runnable()
{
public void run(){
if (DataHolder.PlayProgress.containsKey(DataHolder.tSpeaker.mAddress))
{
long progress = DataHolder.PlayProgress.get(DataHolder.tSpeaker.mAddress);
count=(int)progress;
}
}
});
}
else
{
mHandler.post(new Runnable()
{
public void run()
{
count = 0;
}
});
}
}
else
{
mHandler.post(new Runnable()
{
public void run()
{
mTimer.cancel();
mTimer = null;
if(SongTimer.this.listener != null)
{
SongTimer.this.listener.onFinishCounting();
}
}
});
}
count++;
if(SongTimer.this.listener != null)
{
SongTimer.this.listener.onPositionCounted(count);
}
}
}, 1000, 1000);
}
public void stopTimer()
{
timer = false;
DataHolder.PlayProgress.put(this.groupAddress, (long)count);
}
}
The user chooses a speaker and then one timer will be started when user plays a music with the speaker. When the user switches to another speaker and plays a song with it, a new timer will be started again. All the timers that were started will be stored in a HashMap using the groupAddress as the key for the object, timer.
When user taps pause, timer will be fetch from the HashMap and then terminate it, but the last position counted will be remembered.
When user taps resume time will be started again (new Timer()) and then starts counting from the last position stored.
Here comes the problem:
When multiple timers start to run, they work fine. But when the user taps pause, one timer will be fetch from the HashMap and then terminate it. But unfortunately all timers were terminated at the same time. I checked the Log for the object ID of the timers, they were all different. So I don't understand what is wrong here.
Please help. Many Thanks!
try this one
public class SongTimer{
int count;
long duration;
int groupAddress;
SongTimerListener listener;
boolean timer,run;
View user; //the view who this is going to be attached to
public interface SongTimerListener {
public void onPositionCounted(int position);
public void onFinishCounting();
}
//your constructor
public SongTimer(int position, long duration, int groupAddress,
SongTimerListener listener, View viewToAttach){ //added new parameter
this.listener = listener;
this.count = position;
this.duration = duration;
this.groupAddress = groupAddress;
timer = run = true;
user = viewToAttach;
new Thread(new Runnable() { // your timer
#Override
public void run() {
while(run){
if(!timer)
continue;
//now add your implementation here, (its too late here)
//put your code that you already have here, but minor changes
//if you need to call a Ui method use the user.post(runnable); it
// the same as handler.post(runnable), also with this you have
// reference to your view to which you want to alter, so all you
// to do is do what you want to do easily without actually needing
// your interface call. and all Views that they rely on the music
//mechanism that you talked about will each have an instance of this
//class. your pausing mechanism has already being implemented so
//maintain your old pausing mechanism. Also if you are done and want
// totally stop the thread or kill this class set the boolean run
//variable to false.
}
}).start();
}
hope it helps
For a side project of mine, I'm devoloping an android app with java. I don't know java a lot but i'm trying ^^.
The project is to have an Alarm at a random time in a certain range. The problem is that my chronometer and button freeze, but everything still works! Does anyone has maybe another solution for the thread.sleep ??
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void StartChrono(View view) {
final Chronometer chrono = (Chronometer)findViewById(R.id.chronometer1);
chrono.setBase(SystemClock.elapsedRealtime());
chrono.start();
//Tick();
}
public int RandomTime(int min, int max)
{
int random = max - min;
Random rand= new Random();
random = rand.nextInt(random)+min;
return random;
}
public boolean CheckUp(int randomtime,int chronotime)
{
boolean check = false;
if(randomtime== chronotime)
{
check = true;
}
return check;
}
public void Tick()
{
boolean check = false;
int randomtime = RandomTime(20,150);
int time=1;
do
{
check = CheckUp(randomtime,time);
time = time +1;
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
AlertDialog alertDialog;
alertDialog = new AlertDialog.Builder(this).create();
alertDialog.setTitle("Error - 000");
alertDialog.setMessage("Could not check!");
alertDialog.show();
}
}while(check == false);
if(check == true)
{
AlertDialog alertDialog;
alertDialog = new AlertDialog.Builder(this).create();
alertDialog.setTitle("Yuy");
alertDialog.setMessage("Switch!");
alertDialog.show();
}
}
}
I wouldn't use Thread.sleep(), I would use a Timer.
You can set a time and the Timer automatically calls the associated task.
In Android it would work something like this:
http://android.okhelp.cz/timer-simple-timertask-java-android-example/
I used it once myself, but that is some time ago.
Btw.:
You don't have to write a method to check for a boolean value.
This also works:
boolean check = 5>3;
System.out.println("check: " + check);//"check true"
I'd definately use a Handler for this task: http://developer.android.com/reference/android/os/Handler.html
A basic example would be this:
long timeDelay = 1000; // Set this to your random number.
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
// Do whatever you need to do after a specified interval.
}
}, timeDelay);
Instantiate the Handler inside your onCreate and keep the reference around so you can call it inside your method.
Just to clarify, why you can't use Thread.sleep() for "sleeping" a specific amount of time, is this: when you call Thread.sleep() you call it on the UI thread, so every component running on the UI thread (buttons, textfields and so on) will "sleep" for the given amount of time and hence you basically halt the whole application.
Also see the documentation for Thread.sleep:
Causes the thread which sent this message to sleep for the given
interval of time (given in milliseconds).
int delay = 1000; // delay for 1 sec.
int period = 10000; // repeat every 10 sec.
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask()
{
public void run()
{
displayData(); // display the data
}
}, delay, period);
And other:
while(needToDisplayData)
{
displayData(); // display the data
Thread.sleep(10000); // sleep for 10 seconds
}
Both of them doesn't work (application is force closed). What other options I can try?
You code is failed because you perform sleep in background thread but display data must be performed in UI thread.
You have to run displayData from runOnUiThread(Runnable) or define handler and send message to it.
for example:
(new Thread(new Runnable()
{
#Override
public void run()
{
while (!Thread.interrupted())
try
{
Thread.sleep(1000);
runOnUiThread(new Runnable() // start actions in UI thread
{
#Override
public void run()
{
displayData(); // this action have to be in UI thread
}
});
}
catch (InterruptedException e)
{
// ooops
}
}
})).start(); // the while thread will start in BG thread
Use onPostDelayed() accessed from any of your View or a Handler. You save memory by not creating a Timer or new Thread.
private final Handler mHandler = new Handler();
private final Runnable mUpdateUI = new Runnable() {
public void run() {
displayData();
mHandler.postDelayed(mUpdateUI, 1000); // 1 second
}
}
};
mHandler.post(mUpdateUI);
Try this :
#Override
public void run() {
TextView tv1 = (TextView) findViewById(R.id.tv);
while(true){
showTime(tv1);
try {
Thread.sleep(1000);
}catch (Exception e) {
tv1.setText(e.toString());
}
}
}
U can also try this
There is an another way also that you can use to update the UI on specific time interval. Above two options are correct but depends on the situation you can use alternate ways to update the UI on specific time interval.
First declare one global varialbe for Handler to update the UI control from Thread, like below
Handler mHandler = new Handler();
Now create one Thread and use while loop to periodically perform the task using the sleep method of the thread.
new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
while (true) {
try {
Thread.sleep(10000);
mHandler.post(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
// Write your code here to update the UI.
}
});
} catch (Exception e) {
// TODO: handle exception
}
}
}
}).start();
There several mistakes you have done:
You should never invoke Thread.sleep() on the main thread (and you should never block it for a long time as well). Once main thread is blocked for more then 5 seconds, an ANR (application not responding) happens and it is force closed.
You should avoid using Timer in android. Try Handler instead. Good thing about handler is that it is created on the main thread -> can access Views (unlike Timer, which is executed on its own thread, which cannot access Views).
class MyActivity extends Activity {
private static final int DISPLAY_DATA = 1;
// this handler will receive a delayed message
private Handler mHandler = new Handler() {
#Override
void handleMessage(Message msg) {
if (msg.what == DISPLAY_DATA) displayData();
}
};
#Override
void onCreate(Bundle b) {
//this will post a message to the mHandler, which mHandler will get
//after 5 seconds
mHandler.postEmptyMessageDelayed(DISPLAY_DATA, 5000);
}
}
I came across this thread when i tried to get around the problem that you can't hide seconds in DigitalClock widget for Android. DigitalClock is deprecated now and the recommended widget to use now is TextClock. That don't work on old APIs tho... Therefore i had to write my own 24 hour clock. I don't know if this is a good implementation but it seems to work (and it is updated every second):
import java.util.Calendar;
import android.os.Handler;
import android.view.View;
import android.widget.TextView;
/**
* A 24 hour digital clock represented by a TextView
* that can be updated each second. Reads the current
* wall clock time.
*/
public class DigitalClock24h {
private TextView mClockTextView; // The textview representing the 24h clock
private boolean mShouldRun = false; // If the Runnable should keep on running
private final Handler mHandler = new Handler();
// This runnable will schedule itself to run at 1 second intervals
// if mShouldRun is set true.
private final Runnable mUpdateClock = new Runnable() {
public void run() {
if(mShouldRun) {
updateClockDisplay(); // Call the method to actually update the clock
mHandler.postDelayed(mUpdateClock, 1000); // 1 second
}
}
};
/**
* Creates a 24h Digital Clock given a TextView.
* #param clockTextView
*/
public DigitalClock24h(View clockTextView) {
mClockTextView = (TextView) clockTextView;
}
/**
* Start updating the clock every second.
* Don't forget to call stopUpdater() when you
* don't need to update the clock anymore.
*/
public void startUpdater() {
mShouldRun = true;
mHandler.post(mUpdateClock);
}
/**
* Stop updating the clock.
*/
public void stopUpdater() {
mShouldRun = false;
}
/**
* Update the textview associated with this
* digital clock.
*/
private void updateClockDisplay() {
Calendar c = Calendar.getInstance();
int hour = c.get(Calendar.HOUR_OF_DAY); // 24 hour
int min = c.get(Calendar.MINUTE);
String sHour;
String sMin;
if(hour < 10) {
sHour = "0" + hour;
} else sHour = "" + hour;
if(min < 10) {
sMin = "0" + min;
} else sMin = "" + min;
mClockTextView.setText(sHour + ":" + sMin);
}
}
Thankyou biegleux for pointing me in the, i suppose, correct direction!
Halo, the first i want to know the idle time at my android application. after that, i will do something if it is a idle time mode.
I follow this link.
Application idle time
my program work properly, but suddenly the problem show up. I can't move to the other page (for example to the login page) or pop up a message using alertdialog because its in a thread. Do you have any solutions?
public class ControlActivity extends Activity {
private static final String TAG=ControlActivity.class.getName();
/**
* Gets reference to global Application
* #return must always be type of ControlApplication! See AndroidManifest.xml
*/
public ControlApplication getApp()
{
return (ControlApplication )this.getApplication();
}
#Override
public void onUserInteraction()
{
super.onUserInteraction();
getApp().touch();
Log.d(TAG, "User interaction to "+this.toString());
}
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}}
here is my ControlApplication.java
public class ControlApplication extends Application {
private static final String TAG=ControlApplication.class.getName();
private Waiter waiter;
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "Starting application"+this.toString());
//setContentView(R.layout.activity_main);
waiter=new Waiter(5*60*1000); //5 mins
waiter.start();
Toast.makeText(ControlApplication.this, "start", Toast.LENGTH_LONG).show();
}
public void touch()
{
waiter.touch();
Toast.makeText(ControlApplication.this, "touch", Toast.LENGTH_LONG).show();
} }
here is the Waiter.java
public class Waiter extends Thread implements Runnable{
private static final String TAG=Waiter.class.getName();
private long lastUsed;
private long period;
private boolean stop;
Context activity;
public Waiter(long period)
{
this.period=period;
stop=false;
}
#SuppressLint("ParserError")
public void run()
{
long idle=0;
this.touch();
do
{
idle=System.currentTimeMillis()-lastUsed;
Log.d(TAG, "Application is idle for "+idle +" ms");
try
{
Thread.sleep(5000); //check every 5 seconds
}
catch (InterruptedException e)
{
Log.d(TAG, "Waiter interrupted!");
}
if(idle > period)
{
idle=0;
//do something here - e.g. call popup or so
//Toast.makeText(activity, "Hello", Toast.LENGTH_LONG).show();
stopCounter();
}
}
while(!stop);
Log.d(TAG, "Finishing Waiter thread");
}
public synchronized void touch()
{
lastUsed=System.currentTimeMillis();
}
public synchronized void forceInterrupt()
{
this.interrupt();
}
//soft stopping of thread
public synchronized void stopCounter()
{
stop=true;
}
public synchronized void setPeriod(long period)
{
this.period=period;
}}
I tried to create a new class and call a method to intent. Its also fail. tried to pop up a message from that method its also fail.
do you guys have any other solutions for idle time? thanks.
Regards,
Alfred Angkasa
In you active activity, instead of this thread, do:
public class Graph extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
while(idle = 0) {
idle = System.currentTimeMillis()-lastUsed;
if(idle != period) {
Intent goNextActivity = new Intent(com.package.theactivity);
else {
idle == 0;
}
}
}
}
I just found by myself the answer by search on google and try for 5 hours.. :D
I hope my answer will help you too.
First, I mix the ControlApplication and Waiter with ControlActivity. Thats mean I don't need both files. My ControlActivity will extends the activity (its use for me to intent to the other page if in idle mode), and i will implements runnable(its use for me to run the thread).
after that i have a method called onUserInteraction(), this method help me to get the user interaction, whenever the user touch or click something.
in the onCreate, i initiate all the variable including lastUsed, period, and stop.
why should I initiate that? because you need to know how many seconds to know that your apps is on idle mode or not. that was period use. Stop variable is use for me to iterate and searching every 5 seconds(you can also make it every second to check idle or not) my apps is idle or not. I initiate lastUsed by calling method touch. I copied touch method from ControlApplication into my ControlActivity. By calling touch method, I can know when is my lastused. After that I start my thread.
in my run method, i set idle = 0. and do some looping to check. i check every 5 seconds to know my apps is on idle mode or not.
idle = System.System.currentTimeMillis()-lastUsed -> i used this to know if the idle is already suite with the period or not using if method.
if the idle is greater than period, my apps must be in idle mode. after that i stop the iteration and using handler to manage it.
i set handler.sendEmptyMessage(0), and create Handler. At handler i move to the other page.
this is my full code.
public class MainActivity extends Activity implements Runnable {
private static final String TAG= MainActivity.class.getName();
private long lastUsed;
private int period;
private boolean stop;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
period = 10000;
stop=false;
touch();
Thread currentThread = new Thread(this);
currentThread.start();
Toast.makeText(getApplicationContext(), "Start", Toast.LENGTH_SHORT).show();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
#Override
public void onUserInteraction()
{
super.onUserInteraction();
touch();
Log.d(TAG, "User interaction to "+this.toString());
}
public synchronized void touch()
{
lastUsed=System.currentTimeMillis();
Toast.makeText(getApplicationContext(), "touch", Toast.LENGTH_SHORT).show();
}
public void moveIntent() {
Intent intent = new Intent(this, AfterIdle.class);
startActivity(intent);
}
public void validate(View view) {
switch (view.getId()) {
case R.id.button1 :
Intent intent = new Intent(this, AfterIdle.class);
startActivity(intent);
break;
}
}
#Override
public void run() {
// TODO Auto-generated method stub
long idle;
while (!stop) {
idle=System.currentTimeMillis()-lastUsed;
try
{
Thread.sleep(5000); //check every 5 seconds
}
catch (InterruptedException e)
{
Log.d(TAG, "Waiter interrupted!");
}
if (idle > period) {
idle = 0;
stop = true;
}
}
handler.sendEmptyMessage(0);
}
public Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
moveIntent();
}
};}
I hope this code will help another people if they have the same problem that i faced last time. I wish someone would correct the answer for me if my answer is wrong.
thanks.
Regards,
Alfred Angkasa
I'm trying to make a countdown timer in android for use in a small android app. The app will countdown from some number of seconds to 0, upon which it will do some action. I'm using the coundowntimer supplied by android.os.countdowntimer. Here is my code:
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.quizlayout);
new CountDownTimer(30000, 1000) {
TextView tx = (TextView) findViewById(R.id.textView2);
public void onTick(long millisUntilFinished) {
tx.setText("seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
tx.setText("done!");
}
}.start();
}
However, this countdown timer is really slow. It takes like 3 real-time seconds for the timer to countdown by one second. I wonder what's going on? The code I have above is more or less copied straight from google (CountDownTimer)
Can anyone help me as per why my timer is so slow, and offer a way to speed it up a bit?
(EDIT): I am running this on an emulator, the intel atom x86. I am emulating an android 2.3.3 environment.
According to Android documentation for countdown timer
The calls to onTick(long) are synchronized to this object so that one call to onTick(long) won't ever occur before the previous callback is complete. This is only relevant when the implementation of onTick(long) takes an amount of time to execute that is significant compared to the countdown interval.
Take a look at this example for countdown timer
Countdown timer example
Alternately you can spawn a new thread and just get that thread to sleep for the interval you want and take actions when it wakes or vice versa.
You can also timertask
use a handler that will post the same runnable . this will remove the need for extra threads :
Handler handler=new Handler();
handler.postRunnable(... , 1000) ;
in the runnable , call the postRunnable again for the same handler (and add a condition for when to stop) .
CountDownTimer is not efficient regardless to ui updating performances. For a flawless ui update, it is better to create a custom countdown. I did my own so here it is. It is flawless on my app.
public abstract class CountDown {
int totalTime = 0;
int tickTime = 0;
Thread thread;
boolean canceled = false;
public CountDown(int totalTime,int tickTime){
this.totalTime = totalTime;
this.tickTime = tickTime;
}
public abstract void onTick();
public abstract void onFinish();
public void start(){
thread = new Thread(new Runnable() {
#Override
public void run() {
// Do in thread
canceled = false;
for (int elapsedTime = 0; elapsedTime < totalTime; elapsedTime += tickTime) {
if(!canceled){
onTick();
try {
thread.sleep(tickTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
break;
}
}
if(!canceled){
onFinish();
}
}
});
thread.start();
}
public void cancel(){
canceled = true;
}
}
Remember that every time you have to update your ui, call a runOnUiThread, or else you will have an exception, you are not in a handler and not on ui thread.
Here is how to use it in your code, it is identical to CountDownTimer, so you could just rename lines in your code :
CountDown cDown = new CountDown(10000, 20) {
public void onTick() {
// Do something
}
public void onFinish() {
runOnUiThread(new Runnable() {
#Override
public void run() {
myButton.setImageDrawable(drawable);
}
});
}
};