I have written a piece of code in my fragment which will display a Toast
message at a specific time selected by a user on a Time Picker
. The time delay is calculated by subtracting the current time in milliseconds from the time picker time in milliseconds.
However the toast message is not being displayed and I am not getting any errors either in the logcat.
Here is the code snippet:
public class ManualControlsFragment extends Fragment {
private TimePicker tp;
private Calendar calendar;
Handler mHandler;
private Runnable scheduledTask;
long pickedTimeInMillis=0;
//some fragment methods
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
tp = (TimePicker) view.findViewById(R.id.lightTimePickerStart);
tp.setIs24HourView(true);
calendar = Calendar.getInstance();
//get time picked in milliseconds
tp.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() {
@Override
public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
calendar.set(Calendar.HOUR_OF_DAY, hourOfDay);
calendar.set(Calendar.MINUTE, minute);
pickedTimeInMillis= calendar.getTimeInMillis();
}
});
//Calendar instance to get current time
Calendar cal = Calendar.getInstance();
//get the difference to get the delay
long timeDifference = pickedTimeInMillis - cal.getTimeInMillis();
mHandler = new Handler();
mHandler.postDelayed(scheduledTask, timeDifference);
scheduledTask = new Runnable() {
String text= "Bulb is now on";
@Override
public void run() {
Toast.makeText(
getActivity(), text, Toast.LENGTH_LONG).show();
}
};
return view;
}
After reading the comments and an answer here, I edited the code to this:
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
new Handler().postDelayed(new Runnable() {
String text= "Bulb is now on";
@Override
public void run() {
//Do something after 1 second
Toast.makeText(getActivity().getApplicationContext(), text, Toast.LENGTH_LONG).show();
}
}, timeDifference);
}
});
However, this makes the toast display only when I launch the application(the time on the time picker when I launch it is at the current time which is why I suppose it then displays that toast). When I set a time on the time picker while application is running, the toast is not displayed.
As I said in my comment you need to change the order in your code to make it execute as you want.
First, initialize the scheduledTask before you use it in the Handler's postDelayed() method otherwise all you do is post a null Runnable. Your code should be:
scheduledTask = new Runnable() {
String text= "Bulb is now on";
@Override
public void run() {
Toast.makeText(
getActivity(), text, Toast.LENGTH_LONG).show();
}
};
mHandler.postDelayed(scheduledTask, timeDifference);
Secondly, the code below(inside of the onCreateView() method):
Calendar cal = Calendar.getInstance();
//get the difference to get the delay
long timeDifference = pickedTimeInMillis - cal.getTimeInMillis();
will trigger a Toast right away because pickedTimeInMillis will be 0 so the time difference will be negative, which will get rounded up to 0(so execute right away). If you want this, leave this part of the code otherwise remove it from onCreateView().
Thirdly, you need to post the Runnable as the user changes the time and the OnTimeChangedListener listener gets called. So the code in the listener should be:
@Override
public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
calendar.set(Calendar.HOUR_OF_DAY, hourOfDay);
calendar.set(Calendar.MINUTE, minute);
pickedTimeInMillis= calendar.getTimeInMillis();
// at this point get the current time
Calendar cal = Calendar.getInstance();
// now calculate the difference as the user actually selected a time
long timeDifference = pickedTimeInMillis - cal.getTimeInMillis();
// register the Runnable to run
mHandler.postDelayed(scheduledTask, timeDifference);
}
Also, runOnUiThread() is not needed because the Handler, as you declared it, will run on the main thread.