I'm making an app in Android Java, using Android Studio.
Every 0.1 seconds I want to update the text within a certain TextView.
I already managed to use a Handler to execute a method every 0.1 seconds (100 ms), but it doesn't automatically update the TextView.
It only updates the TextView to what I want when the user interacts with the app. It only updates it when, for example, the user slides the SeekBar or presses a button. It doesn't update when the user clicks on the screen, and not automatically without input either.
How can I make it such that it will update the value automatically, without user input?
Thanks in advance.
P.S: I'm new to Android and Java, and I'm using threads to get the value, in xml format, from a website.
Should I post any code, and if so, what exactly?
you can try updating the value of text view on the UI thread.
runOnUiThread(new Runnable() {
#Override
public void run() {
//update TextView here
}
});
Thread t = new Thread() {
#Override
public void run() {
try {
while (!isInterrupted()) {
Thread.sleep(100);
runOnUiThread(new Runnable() {
#Override
public void run() {
// update TextView here!
}
});
}
} catch (InterruptedException e) {
}
}
};
t.start();
You can update your textview using thread also, like this.
int prStatus = 0;
new Thread(new Runnable() {
public void run() {
while (prStatus < 100) {
prStatus += 1;
handler.post(new Runnable() {
public void run() {
tv.setText(prStatus + "/");
}
});
try {
Thread.sleep(150);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(prStatus == 100)
prStatus = 0;
}
}
}).start();
Related
I want to display some words(Strings) in sequence , each for some time, I am using this code but after all the words are shown, the app crashes, i want it to return to previous page after all words have been shown, please help, thanks in advance.
final TextView textView=(TextView)findViewById(R.id.textid);
Thread t=new Thread(){
#Override
public void run(){
while(!isInterrupted()){
try {
Thread.sleep(1000); //1000ms = 1 sec
runOnUiThread(new Runnable() {
#Override
public void run() {
count++;
textView.setText(words[count]);
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
You are not checking to see if count is within the bounds of words.
You need to change
count++;
textView.setText(words[count]);
To
count++
if (count < words.length){
textView.setText(words[count]);
}else{
// Assuming you are inside an activity called MyActivity
MyActivity.this.finish();
}
I am new to android programming. I have made a simple screen flasher using multiple colors.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myView = findViewById(R.id.my_view);
myView.setBackgroundColor(color);// set initial colour
new Thread(new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(INTERVAL);
}
catch (InterruptedException e) {
e.printStackTrace();
}
updateColor();
whichColor = !whichColor;
}
}
}).start();
}
private void updateColor() {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (whichColor)
myView.setBackgroundColor(Color.YELLOW);
else
myView.setBackgroundColor(Color.BLACK);
}
});
}
I would like to install this on multiple device and sync the flash. What i want is to sync the flash colors on all the devices. Yellow should be displayed on all device and change to Black on all devices at the same time. Is it possible? Maybe get the local time of the device and start the method at 'x' seconds(local time) ?
Create functions for different flashings. Call your functions inside this method.
import java.util.Calendar
String CurrentTime = Calendar.getInstance().getTime().toString().trim();
String YourTime = "Enter Your Expected Time here";
int x = 3000; //Start method time in miliseconds
if(CurrentTime.equals("YourTime")){
try {
sleep(x);
} catch (InterruptedException e) {
e.printStackTrace();
}
//Run Your Colour Change function or method here. like
//colorchange(); or myView.setBackgroundColor(Color.YELLOW);
}
In the below code I am trying to run a thread when a button is clicked. In the button listener I create a new thread and run it...but at run time, when the button is pressed, the button itself freezes and the app does not respond and I receive ANR dialog. Moreover, when the socket is connected successfully even the TexView
mtvStatus.setText("RFC-SOCKET CONNECTED");
displays nothing.
Please let me know why this is happening.
button listener:
this.mbtnConnect.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
BluetoothSocket rfcSocket = mSPPCtrl.rfcConnect();
if (rfcSocket.isConnected()) {
mtvStatus.setText("RFC-SOCKET CONNECTED");
Thread rx = new Thread(new RxRun(rfcSocket));
rx.run();
} else {
mtvStatus.setText("RFC-SOCKET NOT CONNECTED");
}
}
});
runnable class
private class RxRun implements Runnable {
private BluetoothSocket mRFCSocket = null;
private OutputStream mRFCOS = null;
private InputStream mRFCIS = null;
public RxRun(BluetoothSocket rfcSocket) {
this.mRFCSocket = rfcSocket;
try {
this.mRFCOS = rfcSocket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
try {
this.mRFCIS = rfcSocket.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void run() {
try {
this.mRFCOS.write(DIRON.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
while (this.mRFCSocket.isConnected()) {
try {
int readBytes = this.mRFCIS.read(new byte[5120]);
Log.d(TAG, CSubTag.bullet("RxRun", "readBytes:" + readBytes));
//mtvRx.setText(""+readBytes);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
...when the button is pressed, the button itself freezes and the app does not respond and I receive ANR dialog. Moreover, when the socket is connected successfully even the TexView displays nothing.
It's expected, because you haven't actually started the rx thread. Here is what is going on:
mSPPCtrl gets connected,
mtvStatus's text is set to "RFC-SOCKET CONNECTED", but you cannot visually see it because
run() method of the RxRun instance is called manually where the loop while (this.mRFCSocket.isConnected()) may last as long as the socket is connected.
All the above said is invoked on UI-thread and that's the reason of ANR.
You should not call run() manually. Start the rx thread with
rx.start();
Also I highly recommend to move all the rfcSocket logic inside of the thread and notify the UI-thread on success/failure of connection.
EDIT
Here is one the option mentioned in my comment.
Start the rx thread on a button click
this.mbtnConnect.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new Thread(new RxRun(rfcSocket)).start();
}
});
Move your logic inside of the run() method:
public void run() {
BluetoothSocket rfcSocket = mSPPCtrl.rfcConnect();
if (rfcSocket.isConnected()) {
mtvStatus.post(new Runnable() {
#Override
public void run() {
mtvStatus.setText("RFC-SOCKET CONNECTED");
}
});
} else {
mtvStatus.post(new Runnable() {
#Override
public void run() {
mtvStatus.setText("RFC-SOCKET NOT CONNECTED");
}
});
return;
}
// the rest of your logic
}
Some links that might help:
Android documentation on Threads
SO question Android basics: running code in the UI thread
another SO post on Update UI from Thread
The error here is really simple - do not use run() on the Thread instance, as this will actually run it's Runnable on the current Thread! Use start() and it will work fine :-)
I'm trying to make a simple little program that will increment a number once a second. In this case, I'm implementing a thread that should loop once per second and add 1 to "potato" each time it loops. This works fine until it gets back to the display method potatoDisp(). For some reason this causes my app to crash. Removing potatoDisp() from run() fixes the problem, but the display is not updated as "potato" increases.
public int potato = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
potatoDisp();
start();
}
public void potatoDisp() {
TextView text = (TextView) findViewById(R.id.textView1);
text.setText("You currently have " + potato + " potatoes");
}
public void start() {
Thread thread = new Thread(this);
thread.start();
}
#Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
return;
}
potato++;
potatoDisp();
}
}
I'm doing this for an Android app, if that helps. I've tried searching for an answer but I'm pretty lost when it comes to the proper way to work threads.
You need a runnable / handler like this:
private Runnable potatoRun = new Runnable() {
#Override
public void run () {
potatoDisp();
}
};
then change
potatoDisp();
to:
runOnUiThread(potatoRun);
You can't update the views when you're not on the UI thread.
You are probably getting an exception for updating the UI in the background. Since, potatoDisp(); is called from a background Thread but that function updates the UI it will give you problems. You need to call it with runOnUiThread().
#Override
public void run() {
while (true) {
try
{
Thread.sleep(1000);
} catch (InterruptedException e) {
return;
}
potato++;
runOnUiThread(new Runnable()
{
#Override
public void run()
{
potatoDisp();
}
});
}
}
Something like this should work.
The issue is that you are trying to update the UI (calling text.setText(...)) on a thread other than the main UI thread.
While I would suggest using a TimerTask instead of calling Thread.sleep(...), there are two main ways to edit your current code to work as expected.
-- Use a Handler
Define a Handler class that will accept messages and update your UI as needed. For example:
private final String POTATO_COUNT = "num_potatoes";
Handler handler = new Handler() {
public void handleMessage(Message msg) {
int numPotatoes = msg.getData.getInt(POTATO_COUNT);
mText.setText("You currently have " + numPotatoes + " potatoes");
}
}
Then in your code where you want to call your handler to update your text view, whether or not you are on the main UI thread, do the following:
Bundle bundle = new Bundle();
bundle.putInt(POTATO_COUNT, potato);
Message msg = new Message();
msg.setData(bundle);
handler.sendMessage(msg);
-- Call runOnUiThread(...)
#Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
return;
}
potato++;
runOnUiThread(new Runnable()
{
public void run()
{
potatoDisp();
}
}
}
}
I think you should be using Async Task to update the UI from a thread: http://developer.android.com/reference/android/os/AsyncTask.html
I defined a splashscreen the following way:
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ExceptionHandler.register(this);
setFullscreen();
splashScreen();
}
private void splashScreen() {
runOnUiThread(new Runnable() {
#Override
public void run() {
setContentView(R.layout.splashscreen);
splash = (ImageView) findViewById(R.id.splashscreenLayer);
startSplashTime = new Date();
}
});
new LoadingThread().start();
}
private class LoadingThread extends Thread {
#Override
public void run() {
checkNetwork();
}
}
Somewhere at specific conditions in the checkNetwork() method, the stopSplash method is called:
public void stopSplash() {
Message msg = new Message();
msg.what = STOPSPLASH;
Date endSplashTime = new Date();
long time = endSplashTime.getTime() - startSplashTime.getTime();
System.out.println("Time Splashscreen was displayed: " + time);
if (time < SPLASH_MIN_TIME) {
long delay = SPLASH_MIN_TIME - time;
System.out.println("Delay Splashscreen for: " + delay);
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
e.printStackTrace();
}
splashHandler.sendMessage(msg);
} else {
System.out.print("Show Splashscreen now");
splashHandler.sendMessage(msg);
}
}
private Handler splashHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case STOPSPLASH:
splash.setVisibility(View.GONE);
break;
}
super.handleMessage(msg);
}
};
The problem is, sometimes (maybe 1 of 10) if I started the app directly from Eclipse, the Splashscreen isn't showed, but instead just a black screen.
Other problem: if i restart the app, e.g. after onDestroy() was called after clicking the back button on the device, the Splashscreen is almost never shown.
Any hints why?
My assumption: could it be, that the LoadingThread starts "faster" than the Runnable, and so the network staff is done before the Splashscreen is set?
You might try using a CountdownTimer in your implementation. On your first activity, start a CountdownTimer that checks in onTick() every so often for a synchronized boolean finishedLoading with some kind of timeout in onFinish() (15 seconds or something), while your loading is done in another thread that sets finishedLoading to true when it is finished.
Maybe the splash screen isnt being terminated before the v=next activity starts.. just a thought..