Using Android studio, I am trying to make an app that gets data from a web-service and display the data and updates the view every 5 sec or when the data on the web-service changes. With this I am trying to change the colours on some button based on an int, the int changes and the color on the button changes when I apply buttons(); to another button and then presses it but I want it to update by itself.
When I used a while loop the app gets stuck
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
buttons();
}
});
The runOnUiThread is placed in the onCreate.
using run on UI thread will cause your UI to freeze , try using a timer task instead .
example :
#Override
public void StopTimerTask() {
if (timer != null) {
timer.cancel();
timer = null;
}
}
public void StartTimer() {
timer = new Timer();
initializeTimerTask();
int UpdateTime = Integer.valueOf(UserSettings.getString("Update", "60000"));
timer.schedule(doAsynchronousTask, 0, YOURTIME);
}
public void initializeTimerTask() {
doAsynchronousTask = new TimerTask() {
#Override
public void run() {
myHandler.post(new Runnable() {
public void run() {
YOUR LOGIC HERE
}
});
}
};
}
doing this where u just put another class into main activity was succesful only problem is that it have to be in my main class
public class updategui extends TimerTask {
Activity context;
Timer timer;
public updategui(Activity context, int seconds) {
this.context = context;
timer = new Timer();
timer.schedule(this,
seconds * 1000, // initial delay
seconds * 1000); // subsequent rate
}
#Override
public void run() {
if(context == null || context.isFinishing()) {
this.cancel();
return;
}
context.runOnUiThread(new Runnable() {
#Override
public void run() {
try {
buttons();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}}
Related
I want to create an android widget with switching image with time delay. I have no idea about how to do this. Should I create Thread in methood onUpdate?
this example of my layout.xml file:
<ImageButton
android:id="#+id/imageViewWGT"
android:background="#drawable/dog" />
and this is what I want to known how to do correct:
public class MainActivity extends AppWidgetProvider {
private int counter = 0;
private ImageView wgt_img;
wgt_img = wgt_img.findViewById(R.id.imageViewWGT);
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (counter%2 == 0){
wgt_img.setImageResource(R.drawable.dog);
}else
wgt_img.setImageResource(R.drawable.cat);
}
});
counter++;
try {
Thread.sleep(1000); // sleep 1 sec
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
You can use postDelayed method of Handler class like
// Initialisation
Handler handler = new Handler();
int counter = 0;
long switchDelay = 1000L;
// Function for switch images
public void switchImage(){
handler.postDelayed(new Runnable() {
#Override
public void run() {
if (counter%2 == 0){
wgt_img.setImageResource(R.drawable.dog);
}else {
wgt_img.setImageResource(R.drawable.cat);
}
counter++;
// Recall method
switchImage();
}
}, 1000);
}
when you need to run a block of code in schedule at time you can use Timer.
look at this sample code :
new Timer().scheduleAtFixedRate(new TimerTask()
{
#Override
public void run()
{
//you'r code
}
} , DELAY , PERIOD);
add you'r code in run method and replace your delay and period of execute time instead of DELAY and PERIOD .
DELAY and PERIOD are millisecond
also if you want run your block code one time with delay you can use Handler.
new Handler().postDelayed(new Runnable()
{
#Override
public void run()
{
//you'r code
}
} , DEALY_MILLIS);
The android has a default methood to update widget in timeline
<appwidget-provider
...
...
...
...
android:updatePeriodMillis="1000000">
</appwidget-provider>
But it works if you update the widget at least 30 minutes
I have a code that plays 5 sounds with 1 second delay between the sounds and I want this part of code to be executed every 5 seconds (so it will run in a row so far as a boolean variable is true, and when it becomes false the tread run stopped - I have a button to both start and stop this executions). Everything works perfectly, but the issue is that I can't get rid of the 5 seconds delay in the first time I click the button, so when I first click, the sounds beggins only after 5 seconds. How can I make it start right away and only after the first time start taking the delays?
Here is the button onClick code:
public void clickHandlerStartTempo(final View view) {
if (!tempoOn) {
Toast toast = Toast.makeText(getApplicationContext(), "Start Tempo!", Toast
.LENGTH_SHORT);
toast.show();
tempoOn = true;
final Handler handler = new Handler();
final int delay = 5000; //milliseconds
handler.postDelayed(new Runnable() {
public void run() {
if (tempoOn) {
runCode(view);
handler.postDelayed(this, delay);
}
}
}, delay);
} else {
Toast toast = Toast.makeText(getApplicationContext(), "Stop Tempo!", Toast
.LENGTH_SHORT);
toast.show();
tempoOn = false;
}
}
And here is the runCode method:
public void runCode(View view) {
Runnable runnable = new Runnable() {
#Override
public void run() {
playSound(0);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 4; i++) {
if (tempoOn) {
playSound(1);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
return;
}
}
}
};
Thread thread = new Thread(runnable);
Log.i(TAG, "runCode: Thread id = " + thread.getId());
thread.start();
}
I'm new to android development and any help would be very much appreciated.
Thanks.
First you need to playsound without thread after that you will execute your reaming 5 second logic stop thread after 4 count.
public void onStartPress(){
playSound();
someMethod();
}
public void someMethod(){
Handler uiHandler = new Handler(Looper.getMainLooper());
uiHandler.postDelayed(new Runnable() {
#Override
public void run() {
playSound();
someMethod();
}
},1000);
}
Don't use actual Threads unless you really want to do something off the Ui thread. Most of the time you do want to keep things on the Ui thread.
For simple repeating tasks, you can easily repurpose the CountDownTimer class. Often with an (almost) infinite run time or Long.MAX_VALUE (292 million years). The fist onTick happens immediately after starting.
private CountDownTimer mTimer;
private void start() {
if (mTimer == null) {
mTimer = new CountDownTimer(Long.MAX_VALUE, 5000) {
#Override
public void onTick(long millisUntilFinished) {
// start a beeping countdown
new CountDownTimer(5000, 1000) {
private int state = 1;
#Override
public void onTick(long millisUntilFinished) {
playSound(state);
state = state + 1 % 2;
}
#Override
public void onFinish() {
playSound(0);
}
}.start();
}
#Override
public void onFinish() { /* ignore, never happens */ }
};
mTimer.start();
}
}
private void stop() {
if (mTimer != null) {
mTimer.cancel();
mTimer = null;
}
}
Hi my app needs a realtime data from database and I'm posting it on my TextView and I can't update the TextView as the database updates. I tried using Timer but its still the same.
Here is my code,
public void startTimer() {
//set a new Timer
timer = new Timer();
//initialize the TimerTask's job
initializeTimerTask();
timer.schedule(timerTask, 0, 5000);
}
private void stopTimerTask() {
//stop the timer, if it's not already null
if (timer != null) {
timer.cancel();
timer = null;
}
}
public void initializeTimerTask() {
timerTask = new TimerTask() {
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
final AcceptCars Cars = (AcceptCars) getIntent().getSerializableExtra("cars");
renterLat.setText(Cars.renterLat);
renterLng.setText(Cars.renterLng);
Log.d(TAG,renterLat.getText().toString());
Log.d(TAG,renterLng.getText().toString());
}
});
}
};
}
And here is where I get the Cars.renterLat and Cars.renterLng,
public class AcceptCars implements Serializable {
#SerializedName("renterLat")
public String renterLat;
#SerializedName("renterLng")
public String renterLng;
}
This is the logic you should be following. I used a Handler instead of a Timer. Inside the run method you need to call your webservice and get the updated value from the db. Use runOnUiThread to update the value to the UI from a Thread.
See the code below,
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Handler taskHandler = new Handler();
taskHandler.postDelayed(myTask, 0);
}
private Runnable myTask = new Runnable(){
public void run() {
queryDb();
// repeat the task
taskHandler.postDelayed(this, 1000);
}
};
private void queryDb(){
new Thread(new Runnable() {
#Override
public void run() {
// call you webservice
String data = callWebservice();
// parse the data in to AcceptCars pojo class
AcceptCars Cars = parseData(data);
//update the UI
runOnUiThread(new Runnable() {
#Override
public void run() {
renterLat.setText(Cars.renterLat);
renterLng.setText(Cars.renterLng);
}
});
}
}).start();
}
You can even use countdown timer.
Here is the link https://developer.android.com/reference/android/os/CountDownTimer.html
TimerTasks are really hard to deal with IMO. You should use a Handler and call postDelayed to do something after a certain amount of time.
Alternatively, you can try out this timer class I wrote:
import android.os.Handler;
public class Timer {
private Handler handler;
private boolean paused;
private int interval;
private Runnable task = new Runnable () {
#Override
public void run() {
if (!paused) {
runnable.run ();
Timer.this.handler.postDelayed (this, interval);
}
}
};
private Runnable runnable;
public int getInterval() {
return interval;
}
public void setInterval(int interval) {
this.interval = interval;
}
public void startTimer () {
paused = false;
handler.postDelayed (task, interval);
}
public void stopTimer () {
paused = true;
}
public Timer (Runnable runnable, int interval, boolean started) {
handler = new Handler ();
this.runnable = runnable;
this.interval = interval;
if (started)
startTimer ();
}
}
It is really simple to use.
You can use it like this:
Timer timer = new Timer(new Runnable() {
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
final AcceptCars Cars = (AcceptCars) getIntent().getSerializableExtra("cars");
renterLat.setText(Cars.renterLat);
renterLng.setText(Cars.renterLng);
Log.d(TAG,renterLat.getText().toString());
Log.d(TAG,renterLng.getText().toString());
}
}
}
}, 5000, true);
i want to run asynk task in every 5 seconds till 5 minuts, how can i do this ?
i am able to run asynk task in every 5 seconds but can no limit 5 minuts
public void callAsynchronousTask() {
final Handler handler = new Handler();
Timer timer = new Timer();
TimerTask doAsynchronousTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
try {
new CheckTxnStatusSTResult().execute(final_verification_card);
Log.d("dinesh","execute in every five seconds"+ final_verification_card);
} catch (Exception e) {
}
}
});
}
};
timer.schedule(doAsynchronousTask, 0, 15000);
}
Just you can do like this
public void FunctionName() {
new CountDownTimer(Total_time, 1000) {
#Override
public void onTick(long millisUntilFinished) {
MyUtils.Log("execute in every one seconds");
// Display Data by Every Ten Second
}
#Override
public void onFinish() {
// Call Other function on Function
}
}.start();
}
This question already has answers here:
Updating Android UI using threads
(4 answers)
Android toast message from a separate thread class
(1 answer)
Closed 9 years ago.
I'm having some trouble trying to update automaticaly a view in my android activity.
The application display some message like a chat. Im using a ListView to put the message with a ArrayAdapter.
I use this metod to update the ListView
public void loadMessages() {
ArrayList<String> messages = this.dbHelper.getMessages();
conversationArrayAdapter.clear();
conversationArrayAdapter.addAll(messages);
conversationArrayAdapter.notifyDataSetChanged();
}
My idea is to put a thread that call that metod, but when i try to do this i have the following error.
Only the original thread that created a view hierarchy can touch its view.
because you are trying to access or update UI elements from Thread . to avoid this error you will meed to use runOnUiThread for updating UI from Thread as :
Your_Current_Activity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
// Update UI here
loadMessages();
}
});
and second solution is use AsyncTask instead of thread
Use this code.
public class MainActivity extends Activity
{
private Timer autoUpdate;
#Override
public void onResume()
{
super.onResume();
autoUpdate = new Timer();
autoUpdate.schedule(new TimerTask()
{
#Override
public void run()
{
runOnUiThread(new Runnable()
{
public void run()
{
updateScore();
}
});
}
}, 0, 5000); // updates each 5 seconds
}
#Override
public void onPause()
{
autoUpdate.cancel();
super.onPause();
}
#Override
public void onCreate(Bundle savedInstanceState)
{
// initialize view layout
super.onCreate(savedInstanceState);
setContentView(R.layout.cleanermain);
super.onResume();
}
private void updateScore()
{
// decide output
// update cricket score
}
}
UI should be updated only from the UI (Main) thread.
Here is a solution using AsyncTask.
public void asyncCallWithSchedule() {
final Handler handler = new Handler();
Timer timer = new Timer();
TimerTask doAsynchronousTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
try {
new SearchAsync().execute(txtSearch.getText().toString());
}
});
}
};
timer.schedule(doAsynchronousTask, 0, 2000);
}
}
AsyncTask class:
private class SearchAsync extends
AsyncTask < String, Object, List < Users >> {
#Override
protected List < Users > doInBackground(String...params) {
// Call DB here
return null;
}
#Override
protected void onPostExecute(List < Users > result) {
super.onPostExecute(result);
// Update UI here
}
}
Simple:
public void loadMessages() {
ArrayList<String> messages = this.dbHelper.getMessages();
conversationArrayAdapter.clear();
conversationArrayAdapter.addAll(messages);
new Handler(Looper.getMainLooper()).post(new Runnable() {
public void run() {
conversationArrayAdapter.notifyDataSetChanged();
}
});
}