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
Related
I need to update a TextView frequently with a specific time delay in the android studio. The code is below. Thank you.
Edit: I also need to end the loop with a button click or with an "if" control.
//INFLATION CALCULATION !!!
/**
* This method calculates Inflation value.
*/
public void calculateInflation() {
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
inflation = (cpi-cpiIni)/cpiIni*100;
displayInflation();
cpiIni = cpi;
}
}, delay*12);
}
Call the same method inside the runnable in order to keep the loop going
Use a flag in order to be able to stop the loop: shouldCalculate
private boolean shouldCalculate = true; // set to false when you want to end the loop
public void calculateInflation() {
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
if (shouldCalculate) {
inflation = (cpi-cpiIni)/cpiIni*100;
displayInflation();
cpiIni = cpi;
calculateInflation();
}
}
}, delay*12);
}
private Runnable updateTimerThread = new Runnable() {
public void run() {
inflation = (cpi-cpiIni)/cpiIni*100;
displayInflation();
cpiIni = cpi;
customHandler.postDelayed(this, 0);
}
};
public void startTimer() {
//timer
startTime = SystemClock.uptimeMillis();
customHandler.postDelayed(updateTimerThread, 0);
}
public void stopTimer() {
//timer stops
customHandler.removeCallbacks(updateTimerThread);
//timer ends
}
make a reference of runnable thread , start it using startTimer() and remove thread using stopTimer() as you said on a button click or up on a specific conditions .Also you can change the postDelayed milliseconds as ur wish
Try below code. This will do the trick. If you find any problem please let me know.
public void calculateInflation() {
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
inflation = (cpi-cpiIni)/cpiIni*100;
displayInflation();
cpiIni = cpi;
if(shouldRepeat)
calculateInflation();
}
}, delay*12);
}
And second approach can be CountDownTimer. Make a method as shown in below code
public void timerTask(final int loopTime){
//Loop time is the actual time for repeatation
new CountDownTimer(loopTime, 1000) {
public void onTick(long millisUntilFinished) {
//this tells you one second is passed
}
public void onFinish() {
//here on time finish you need to define your task
inflation = (cpi-cpiIni)/cpiIni*100;
displayInflation();
cpiIni = cpi;
//call the same method again for looping
timerTask(loopTime);
}
}.start();
}
Simplest way. Here updateRunnable calls itself with delay. Make updateRunnable as global variable to access from anywhere.
Runnable updateRunnable = new Runnable() {
#Override
public void run() {
inflation = (cpi-cpiIni)/cpiIni*100;
displayInflation();
cpiIni = cpi;
handler.postDelayed(this, UPDATE_TIME);
}
};
Start handler. Here we start handler immediately without delay.
handler.postDelayed(updateRunnable, 0)
Stop handler
handler.removeCallbacks(updateRunnable)
By the way don't forget to stop handler on onDestroy()
How to make a picture that would be updated every 30 seconds ?
ImageView imageView = (ImageView) findViewById(R.id.imageView);
Picasso.with(this).load("http://i.imgur.com/DvpvklR.png").memoryPolicy(MemoryPolicy.NO_CACHE).networkPolicy(NetworkPolicy.NO_CACHE).into(imageView);
You are going to want to use something like a thread to do this.
For example, below your image view:
Runnable imageUpdater = new Runnable() {
#Override
public void run() {
while (true) {
try {
sleep(30000); // 30 seconds in milliseconds
} catch(InterruptedException e) {
// Someone called thread.interrupt() and tried
// to stop the thread executing
return;
}
// Here load the image in the same way as above:
// But you will need to go onto the UI thread first.
image.post(new Runnable() {
public void run() {
Picasso.with(YourActivity.this).load( "http://i.imgur.com/DvpvklR.png").memoryPolicy(MemoryPolicy.NO_CACHE).networkPolicy(NetworkPolicy.NO_CACHE).into(imageView);
}
});
}
}
};
Then you just start the runnable:
Handler handler = new Handler();
handler.post(imageUpdater);
String[] imageLink = {http://i.imgur.com/DvpvklR.png,
http://i.imgur.com/DvpvklR.png, http://i.imgur.com/DvpvklR.png};
int position = 0;
new Timer().scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
runOnUiThread(runnable);
}
}, 30 * 1000, 30*1000);
Runnable runnable = new Runnable() {
#Override
public void run() {
Picasso.with(this).load(imageLink[position%imageLink.length]).memoryPolicy(MemoryPolicy.NO_CACHE).networkPolicy(NetworkPolicy.NO_CACHE).into(imageView);
position++;
}
};
Hope the above code will help you :)
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();
}
}
});
}}
I have a textview which i want to change with a thread and do it again and again (Like a digital clock). But i'm having problems with setting time between 2 changes. Here, the code:
display1 = (TextView) findViewById(R.id.textView1);
Thread timer2 = new Thread(){
#Override
public void run() {
synchronized (this){
runOnUiThread(new Runnable() {
#Override
public void run() {
int i = 0;
display1.setText("" + i);
try {
sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
display1.setText("" + (i+1));
}
});
}
}
};
timer2.start();
This sleep(2000); function makes textview invisible for the given time but i want it stand still till the next change. How can i do that?
But i'm having problems with setting time between 2 changes
Do NOT do sleep() on your UI thread. If you want to chain some actions with the delay, split your code into two runnables and the first one should set display1 and then post second runnable with the delay using postDelayed()
EDIT
want one of them to increase 3 per sec, and the other 5 per sec until they reach 1000 for instance
You can make your Runnable post itself until some criteria are met (i.e. time, counter value etc). Just at the end your Runnable check your conditions and if not met, call postDelayed(this, delay); and you are good.
You should use a Handler instead and dispatch your changes to the UI thread.
Handler mHandler = new Handler();
mHandler.post(new Runnable() {
#Override
public void run() {
// Code to be run right away
}
});
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
// Code to be run after 2 seconds
}
}, 2000);
Maybe split up what you need to do into separate methods. Here you have a UI method and a sleep method split up. Hope it helps
private void myMethod() {
new Thread() {
#Override
public void run() {
int i = 0;
doWorkOnUI(String.valueOf(i));
pause(2000);
doWorkOnUI(String.valueOf(i++));
}
}.start();
}
private void pause(int pauseTime) {
try {
Thread.sleep(pauseTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void doWorkOnUI(final String string) {
runOnUiThread(new Runnable() {
#Override
public void run() {
display1.setText(string);
}
});
}
I am trying to make a clock, using a TextView :)
Someone here told me that I couldn't use normal threads to change the UI, but Handler or AsyncTask. I managed to get it working a few days ago, but was not a consistent thread.
Now what I want is a consistent thread that is always changing the text of my Textview. I tried using this, but didn't work, any help?
private void startClock() {
new Handler().postDelayed(new Runnable(){
#Override
public void run() {
while (true) {
final long millis = System.currentTimeMillis() - MainActivity.startedAt;
clock.setText("" + millis);
runOnUiThread (new Runnable() {
#Override
public void run() {
clock.setText("" + millis);
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}, 2000);
}
you should get rid of:
while(true) {
....
sleep(1000);
...
}
because this get your thread stuck forever. your program should work like this:
private Handler mHandler = new Handler();
#Override
public void onResume() {
super.onResume();
mHandler.removeCallbacks(mUpdateClockTask);
mHandler.postDelayed(mUpdateCLockTask, 100);
}
#Override
public void onPause() {
super.onPause();
mHandler.removeCallbacks(mUpdateClockTask);
}
private Runnable mUpdateClockTask = new Runnable() {
public void run() {
updateClock();
mHandler.postDelayed(mUpdateClockTask, 2000);
}
};
and inside updateClock() you do all your UI updates.
Look here for an example https://stackoverflow.com/a/11140429/808940
Also note that you have a duplicate line in your code:
clock.setText(""+millis);
It appears both in the runOnUiThread and in the main handler, it should only appear in the runOnUiThread runnable