Handler runnable breaks application - android

I have timer which schedules each 1 sec, and as we can't toast in timertask I used handler.post(). But this code breaks my app:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
String text = (String) msg.obj;
sec_view.setText(text);
}
};
MyTimerTask myTask = new MyTimerTask();
timer = new Timer();
timer.schedule(myTask, 1000, 1000);
}
Runnable makeToast = new Runnable() {
public void run() {
Toast.makeText(null, "qwerty", Toast.LENGTH_LONG).show();
}
};
class MyTimerTask extends TimerTask {
public void run(){
if(0 == --sec){
handler.post(makeToast); //breaks there
timer.cancel();
}
Message msg = new Message();
msg.obj = sec+" sekund";
handler.sendMessage(msg);
}
}
Can I use anything else to toast from timertask?

currently you are passing null as Context in Toast.makeText.just pass context instead of null to show toast
Toast.makeText(Your_Activity.this, "qwerty", Toast.LENGTH_LONG).show();
and to show Toast or access UI elements from timertask run method use runOnUiThread() as
public void run() {
Current_Activity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
//show your toast here
}
});
}

change toast to
Toast.makeText(getApplicationContext(), "qwerty", Toast.LENGTH_LONG).show();
then add
#override annotation above void run in handler

Related

Not updating TextView value with thread,Why?

TextView output;
int i;
Random random=new Random();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
output=findViewById(R.id.textView);
new Thread(new mythread()).start();
}
class mythread implements Runnable{
#Override
public void run() {
try {
while(true) {
i = random.nextInt(100);
output.setText(i + "");
Thread.sleep(500);
}
}catch (Exception e){}
}
}
}
it just showing one number in text view
but requirement is ,it should generate random number and keep updating textview after 500ms
Thank You!
The main problem, in your code, is that you can update UI only in the main thread and you are using a custom thread.
The second problem is that you are using Thread.sleep that is a very bad practise.
I suggest you to use Handler
Handler handler = new Handler();
Runnable runnable = new Runnable() {
#Override
public void run() {
Log.d("Handler", "Running Handler");
handler.postDelayed(this, 500);
}
}
handler.postDelayed(runnable, 0);
and here the kotlin version
var handler = Handler()
var runnable = object : Runnable {
override fun run() {
Log.d("Handler", "Running Handler");
handler.postDelayed(this, 500)
}
}
handler.postDelayed(runnable, 500)
Try this, I think it will solved your problem.
public class MainActivity extends AppCompatActivity {
private Random random;
private Handler handler;
private TextView textView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.tv_number);
displayRandomNumber();
}
/**
* Display random number in text view
*/
private void displayRandomNumber()
{
random = new Random();
handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
int value = random.nextInt();
textView.setText(String.valueOf(value));
handler.postDelayed(this,2000);
}
}, 2000);
}
}

Android studio update textview every 5 seconds

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);

Implementing Timer Task makes the application to crash

I am developing an application in which I want to implement timer task to print a toast message every 5 seconds. The problem is my application crashes after 5 seconds when i run it.Below is part of my code please tell me where I am making mistakes and how can I overcome it.
public class main_activity extends Activity implements BluetoothLeUart.Callback{
public ImageButton fabbutton;
Activity activity;
Timer time;
TimerTask timetask;
Handler handle;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_activity);
fabbutton = (ImageButton) findViewById(R.id.fabbutton);
startTimer(); //this is where I start my timer task
fabbutton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
scanLeDevice(false);
Intent intent = new Intent(getApplicationContext(), ScanList.class);
startActivity(intent);
}
});
}
public void startTimer(){
time = new Timer();
initializeTimerTask();
time.schedule(timetask, 5000, 10000);
}
public void initializeTimerTask(){
timetask = new TimerTask() {
#Override
public void run() {
handle.post(new Runnable() {
#Override
public void run() {
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(getApplicationContext(),"Timer...", duration);
toast.show();
}
});
}
};
}
public void stoptimertask() {
//stop the timer, if it's not already null
if (time != null) {
time.cancel();
time = null;
}
}
}
you forgot to initialize handler,
Just add below line in oncreate or startTimer();
handle = new Handler();
Or even in your case you can use,
runOnUiThread(new Runnable(){
#Override
public void run() {
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(getApplicationContext(),"Timer...", duration);
toast.show();
}
});

How to stop a timer after certain number of times

Trying to use a Timer to do run this 4 times with intervals of 10 seconds each.
I have tried stopping it with a loop, but it keeps crashing. Have tried using the schedule() with three parameters, but I didn't know where to implement a counter variable. Any ideas?
final Handler handler = new Handler();
Timer timer2 = new Timer();
TimerTask testing = new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
Toast.makeText(MainActivity.this, "test",
Toast.LENGTH_SHORT).show();
}
});
}
};
int DELAY = 10000;
for (int i = 0; i != 2 ;i++) {
timer2.schedule(testing, DELAY);
timer2.cancel();
timer2.purge();
}
private final static int DELAY = 10000;
private final Handler handler = new Handler();
private final Timer timer = new Timer();
private final TimerTask task = new TimerTask() {
private int counter = 0;
public void run() {
handler.post(new Runnable() {
public void run() {
Toast.makeText(MainActivity.this, "test", Toast.LENGTH_SHORT).show();
}
});
if(++counter == 4) {
timer.cancel();
}
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
timer.schedule(task, DELAY, DELAY);
}
Why not use an AsyncTask and just have it Thread.sleep(10000) and the publishProgress in a while loop? Here is what it would look like:
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
int i = 0;
while(i < 4) {
Thread.sleep(10000);
//Publish because onProgressUpdate runs on the UIThread
publishProgress();
i++;
}
// TODO Auto-generated method stub
return null;
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
//This is run on the UIThread and will actually Toast... Or update a View if you need it to!
Toast.makeText(MainActivity.this, "test", Toast.LENGTH_SHORT).show();
}
}.execute();
Also as a side note, for longer term repetitive tasks, consider using AlarmManager...
for(int i = 0 ;i<4 ; i++){
Runnable runnableforadd ;
Handler handlerforadd ;
handlerforadd = new Handler();
runnableforadd = new Runnable() {
#Override
public void run() {
//Your Code Here
handlerforadd.postDelayed(runnableforadd, 10000); }
};
handlerforadd.postDelayed(runnableforadd, i);
}

Android Service...application crashes when making a Toast

This is my Service class:
public class MySrv extends Service {
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
final Context c = getApplicationContext();
Timer t = new Timer("mytimer");
TimerTask task = new TimerTask() {
#Override
public void run() {
// TODO Auto-generated method stub
Toast.makeText(c, "Not a beautyfull day today...", Toast.LENGTH_SHORT).show();
}
};
t.schedule(task, 5000, 6000);
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
The application crashes at Toast.makeText()... So what am I doing wrong?
The TimerTask's run() method doesn't execute in the UI thread, so you can't do UI-related things like creating a Toast.
Investigate using a Handler or runOnUiThread() instead.
Example:
final Handler handler = new Handler ();
TimerTask task = new TimerTask() {
#Override
public void run() {
handler.post (new Runnable (){
#Override
public void run() {
Toast.makeText(c, "Not a beautyfull day today...", Toast.LENGTH_SHORT).show();
}
});
}
The problem here is that you are trying to update the UI in the timers thread, you should use a Handler for this.
Read How to display toast inside timer?
You cannot make a Toast in another Thread, you can use a Handler to do it or use the runOnUiThread.
public class YourActivity extends Activity {
private Handler toastTeller;
public void onCreate(Bundle savedInstance) {
super.onCreate(savedInstance);
toastTeller = new Handler() {
public void handleMessage(Message msg) {
if (msg.what == 2)
Toast.makeText(LibraryActivity.this, msg.obj.toString(),
Toast.LENGTH_LONG).show();
super.handleMessage(msg);
}
};
new Thread(new Runnable(){
public void run(){
Message msg = new Message();
msg.what = 2;
msg.obj = "Your item was downloaded.";
toastTeller.sendMessage(msg);
}
}).start();
}

Categories

Resources