Let say I want to pass some configuration data before I start a thread so it can run with it right away how do I do that? Here is a simple code:
Here I'm trying to configure the sleep delay, but it requires me to declare data inside? How can I let the thread know?
public void startAniHandlerThread(){
int sleeptime;
Thread thread1 = new Thread(){
public void run(){
try {
sleep(sleeptime); Log.d("TEST", " Test ");
} catch (Exception e) {
e.printStackTrace();
Log.d("TEST", " "+e);
}
}
};
thread1.start();
}
You can declare sleeptime as
final int sleeptime = <value>;
That way you'll be able to access it from inside the Runnable.
Related
I have this problem. I'm trying to update my TextView from another thread and it's not letting me.
I have tried a bunch of different solutions and none of those didn't seem to help. In my while loop code is printing that "Started new loop" all the time but it's not continuing from that runOnUiThread.
Can anyone help me figure out how to update TextView from another thread?
//second thread
protected void startKakkosThread() {
Thread t2 = new Thread() {
public void run() {
while (true) {
System.out.println("Started new loop");
runOnUiThread(new Runnable() {
#Override
public void run() {
try {
if(rullaavaNumero >= 0) {
rullaavaNumero--;
System.out.println(rullaavaNumero);
pelaajanPisteetTeksi.setText("" + rullaavaNumero);
sleep(1000);
}else{
rullaavaNumero = 9;
System.out.println(rullaavaNumero);
pelaajanPisteetTeksi.setText("" + rullaavaNumero);
sleep(1000);
}
}catch (InterruptedException e){
e.printStackTrace();
}
}
});
}
}
};
t2.start();
}
Here is a quick fix, you have an infinite loop that runs faster than a thread can have a chance (time) to start. So even thus you have a sleep in side your thread with if statement, if the thread never starts then sleep have no effect.
And your sleep inside a Thread won't work like this. You want to delay your infinite while loop, therefore you need to move sleep on out of the thread in your while loop.
It is still possible to delay your thread by adding extra sleep in it, but all that depends on what you want to achieve.
Your final code would look like this:
protected void startKakkosThread() {
Thread t2 = new Thread() {
public void run() {
while (true) {
System.out.println("Started new loop");
runOnUiThread(new Runnable() {
#Override
public void run() {
if (rullaavaNumero >= 0) {
rullaavaNumero--;
System.out.println(rullaavaNumero);
pelaajanPisteetTeksi.setText("" + rullaavaNumero);
// no need for sleep here
// sleep(1000);
} else {
rullaavaNumero = 9;
System.out.println(rullaavaNumero);
pelaajanPisteetTeksi.setText("" + rullaavaNumero);
// no need for sleep here
// sleep(1000);
}
}
});
// add this part
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t2.start();
}
I have test it and it works, you could also go what #cricket has suggest.
My eye saw another issue, which is not a part of your question, but good to mention. I assume you want to count from 9 to 0, if that is the case, you need to correct following line by removing = otherwise you get counts till -1, so your code line would look like this:
if(rullaavaNumero > 0) {...
My USB Host is receiving sensor data and it is getting updated every 200ms. I would like to read this data in my android app every 200ms. I am able to read it using bufferreader, It reads the data for sometime and then hangs. It is not consistent. I am new to this and may be I am not doing it the correct way. Below please find my code and let me know your suggestions. Thanks in advance.
public void startProcessOne()
{
new CountDownTimer(110,100)
{
#Override
public void onTick(long millisUntilFinished)
{
StringBuilder text = new StringBuilder();
line = "";
try {
FileReader in = new FileReader("/mnt/udisk/TEST.TXT");
BufferedReader br = new BufferedReader(in);
int i=0;
char[] buf = new char[10000];
while((i = br.read(buf,i,100))!= -1)
{
String h = new String(buf);
text.append(h);
text.append('\n');
}
br.close();
}
catch (IOException e) {
//You'll need to add proper error handling here
}
TxtRead.setText(text.toString());
}
#Override
public void onFinish()
{
startProcessOne();
}
}.start();
}
TxtRead.setText(text.toString());
This line is causing the problem. You can't touch UI elements from a background thread. You should instead run those codes in the UI/Main thread.
In your case, I'd personally prefer using Java threads. So, create a background thread to keep running periodically. If you would need to run UI methods from that background thread. You probably need a handler attached to the main thread.
// Instantiate a handler in UI thread
final Handler handler = new Handler();
new Thread(new Runnable(){
// Once you're done and want to break the loop, just set this boolean
private boolean stopped = false;
#Override
public void run(){
while(!stopped) {
// Read from the file
// Whenever you need to update an UI element,
// you should wrap it inside this runnable object
handler.post(new Runnable(){
#Override
public void run(){
// Update UI
TxtRead.setText("new_text");
}
})
try {
// This thread will sleep for 9 seconds
Thread.Sleep(9000);
} catch(Exception e){}
}
}
}).start();
I wants to create a custome Input Method with word suggestions from a webservice in an asynchronous way. If it is not asysnchronouse , phone get stuck while connecting to internet. If I use Thread it cause an excpetion "ui can be touch only by the tread created ". I don't know runOnUIthread can be used or how. I understood that runOnUiThread activity method. Anybody please help. I used android Example app softkeybord.
I'm not sure I understand,
If the definition of the Thread is inside the Activity,
You can just call:
new Thread() {
public void run() {
while (i++ < 1000) {
try {
runOnUiThread(new Runnable() {
#Override
public void run() {
btn.setText("#" + i);
}
});
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
I am referring to http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/app/AlarmService_Service.html
There the runnable of the thread looks like this
Runnable mTask = new Runnable()
{
public void run()
{
Log.v("service", "thread is running after 5 min");
// Normally we would do some work here... for our sample, we will
// just sleep for 30 seconds.
long endTime = System.currentTimeMillis() + 15*1000;
while (System.currentTimeMillis() < endTime)
{
synchronized (mBinder)
{
try
{
mBinder.wait(endTime - System.currentTimeMillis());
}
catch (Exception e)
{
}
}
} // Done with our work... stop the service!
AlarmService_Service.this.stopSelf();
}
}
I admit that I have some problems with the concept of synchronized... The thread runs the while loop to wait 15s, within that loop I have wait for 15s. So how would the runnable look like if I just want to write a log entry e.g. Log.v(TAG,TEXT);? What would change if I want to write a new entry into my own database table?
Thanks, A.
If you just want a log statement then the following will work fine
Runnable mTask = new Runnable()
{
public void run()
{
Log.v("TAG", "Some verbose log message");
}
}
Whether you need to use synchronized on an object depends on whether object is thread-safe or not. If it is not thread-safe, then you will need to ensure that only one thread access the object at a time by using a synchronized block. In your example mBinder is not thread-safe, so in order to call the wait method of the binder you need to ensure that you are the only thread accessing it.
A runnable is most often used to execute code in a different thread, so that long running operations (such as IO, but in this case just waiting) do not block the UI thread.
Simply replace
try
{
mBinder.wait(endTime - System.currentTimeMillis());
}
catch (Exception e)
{
}
...with the code you want to execute?
Synchronized is just to assert that only one process accesses the thread at one time.
I have a service that monitors a socket connection. When the connection is lost it needs to display a Toast informing the user that it is reconnecting. This works fine the first time. After that I see the enqueueToast in the log but the toast is not displayed. Any ideas are appreciated. I thought this was going to be an easy thing to add, but I must be missing something.
Log entry
INFO/NotificationService(118): enqueueToast pkg=com.abc
callback=android.app.ITransientNotification$Stub$Proxy#43f7b100
duration=1
Code that calls the Toast
public class ConnectionService extends Service
{ .....
public void restartConnection()
{
try
{
Log.i(this.toString(), "Attempting to reconnect...");
// increase the wait between each retry until the max is reached
int sleepTime = reconnectCounter * MIN_RECON_WAIT;
if (sleepTime > MAX_RECON_WAIT)
{
sleepTime = MAX_RECON_WAIT;
}
String msg = "The connection has been lost. Restart attempt will start in: " + sleepTime/1000 + " seconds";
Log.i(this.toString(), msg);
Toast.makeText(getApplicationContext(), msg , Toast.LENGTH_LONG).show();
Thread.sleep(sleepTime);
// increment the counter
reconnectCounter++;
this.startConnectionThread();
}
catch (Exception e)
{
Log.e(this.toString(), "Exception: " + e.toString());
e.printStackTrace();
}
}// end retartConnection
Yeah, you could go with the runOnUiThread, that's a legit way.
Also, you could try the Handler alternative. Either way it should work.
Here is some code from the top of my head. I don't have the SDK now to test it but I think it should give you a general idea.
public class ConnectionService extends Service {
private Handler handler = new Handler();
public void restartConnection(){
int sleepTime = reconnectCounter * MIN_RECON_WAIT;
if (sleepTime > MAX_RECON_WAIT)
{
sleepTime = MAX_RECON_WAIT;
}
String msg = "The connection has been lost. Restart attempt will start in: " + sleepTime/1000 + " seconds";
(new Timer()).schedule(
new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), "msg", Toast.LENGTH_LONG).show();
reconnectCounter++;
this.startConnectionThread()
}
});
}
}, sleepTime);
}//end restartConnection
}//end ConnectionService
here is the solution
http://www.jjoe64.com/2011/09/show-toast-notification-from-service.html
you have to create a Handler in the onStartCommand method. And in the onHandleIntent method you can then create and show a toast notification