I was trying to create an android app that should get time in minutes from a seek bar then it should begin to play a sound file until the countdown timer ends.
Things are mostly fine with the countdown timer BUT my question is how should I call some methods of the countdown timer instance when a button is pressed.
In the code below, I want to call onFinish() whenever the stop button pressed.
Here is my code:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SeekBar sb = (SeekBar) findViewById(R.id.seekBar);
Button bt_stop = (Button) findViewById(R.id.btn1);
final TextView tv = (TextView)findViewById(R.id.textView);
sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
int millisec_time = (i*60)/1000;
new CountDownTimer(millisec_time, 1000) {
public void onTick(long millisUntilFinished) {
tv.setText("seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
tv.setText("done!");
}
}.start();
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
// Toast.makeText(getApplicationContext(),"GOT",Toast.LENGTH_LONG).show();
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
// Toast.makeText(getApplicationContext(),"OFF",Toast.LENGTH_LONG).show();
}
});
bt_stop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
}
});
}
}
First, I'd recommend you only start your CountdownTimer in onStopTrackingTouch - reason being that currently you're creating a brand new timer every time the progress changes on your seekbar (which could be happening a lot).
Secondly, you'll need to retain a reference to your timer in order to cancel it. So:
public class MainActivity extends AppCompatActivity {
private CountdownTimer timer = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final SeekBar sb = (SeekBar) findViewById(R.id.seekBar);
sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
restartTimer(seekBar);
}
}
final Button bt_stop = (Button) findViewById(R.id.btn1);
bt_stop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(timer != null) {
timer.cancel();
}
}
});
}
private void restartTimer(SeekBar sb) {
if(timer!=null) {
timer.cancel();
}
final long millis = TimeUnit.SECONDS.toMillis(sb.getProgress());
final long interval = TimeUnit.SECONDS.toMillis(1);
timer = new CountdownTimer(millis, interval) {
#Override
public void onTick(long millisUntilFinished) {
tv.setText(String.format("Seconds Remaining: %d", TimeUnit.MILLIS.toSeconds(millisUntilFinished));
}
#Override
public void onFinish() {
tv.setText("done!");
}
}
timer.start();
}
}
Related
I have 12 seekbars in an activity. Each seekbar needs a listener. At the moment I am manually setting a listener for each seekbar, this doesnt seem particularly efficient.
Can anyone recommend a more efficient practice to set the seekbars???
Try something like this:
public class MainActivity extends AppCompatActivity {
SeekBar seekBar1;
SeekBar seekBar2;
SeekBar.OnSeekBarChangeListener mlistener;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
seekBar1 = findViewById(R.id.seekBar_1);
seekBar2 = findViewById(R.id.seekBar_2);
mlistener = new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
switch (seekBar.getId()) {
case R.id.seekBar_1:
//do something
break;
case R.id.seekBar_2:
//do something else
break;
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
};
seekBar1.setOnSeekBarChangeListener(mlistener);
seekBar2.setOnSeekBarChangeListener(mlistener);
}
If your SeekBars all require different interaction logic then obviously you will need to provide unique code to each of the objects. However, you can re-use listeners if each SeekBar is doing the same thing. For example:
public class SeekBarTest extends Activity{
private Context myContext;
public SeekBarTest(Context c){
myContext = c;
}
private void initialize(){
SeekBar seekbar1 = new SeekBar(myContext);
SeekBar seekbar2 = new SeekBar(myContext);
SeekBar seekbar3 = new SeekBar(myContext);
SeekBar.OnSeekBarChangeListener myListener = new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
//logic
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
//logic
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
//logic
}
};
seekbar1.setOnSeekBarChangeListener(myListener);
seekbar2.setOnSeekBarChangeListener(myListener);
seekbar3.setOnSeekBarChangeListener(myListener);
}
}
Instead of creating switch in onProgressChanged method you can send variables to SeekBar initiating method.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_options);
SeekBar volBar = initiateSeekBar(R.id.volume,R.id.volumeValue,0,1,"%");
SeekBar playSpeedBar = initiateSeekBar(R.id.autoPlay,R.id.autoPlayValue,100, 100,"ms");
}
private SeekBar initiateSeekBar(int barId, int textId, final int min, final int step, final String unit) {
SeekBar bar = findViewById(barId);
final TextView text = findViewById(textId);
bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
int value = min + progress * step;
text.setText(value + " " + unit);
autoPlayDelayTime = value;
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
return bar;
}
You can just make a reference equality, like this:
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
seekBar?. let {
if (this.seekBar1 === it) {
...
}
if (this.seekBar2 === it) {
...
}}
...
}
and call outside:
seekBar1.setOnSeekBarChangeListener(this)
seekBar2.setOnSeekBarChangeListener(this)
I'm trying to use OOP in my Java/Android code, but I don't understand why OnSeekBarChangeListener is not working in my new class.
Is it prohibited to use a OnSeekBarChangeListener outside main activity?
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mp = new MediaPlayer();
timescroller = (SeekBar) findViewById(R.id.seekBar);
TimeScroller Tm = new TimeScroller();
Tm.mp = mp;
Tm.ts = timescroller;
Tm.mTimeScroller();
timescroller.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
if(b){
mp.seekTo(i);
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
mp.setVolume(0,0);
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
mp.setVolume(1,1);
}
});
}
And here is my class
package com.phillipvm.gridlayout;
import android.media.MediaPlayer;
import android.widget.SeekBar;
public class TimeScroller {
MediaPlayer mp;
SeekBar ts;
public void mTimeScroller(MediaPlayer _mp,SeekBar _ts){
mp =_mp;
ts = _ts;
ts.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
if(b){
mp.seekTo(i);
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
mp.setVolume(0,0);
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
mp.setVolume(1,1);
}
});
}
}
i can't see the code where you are using the class!
you are calling Tm.mTimeScroller(); but in your class the method takes 2 parameters !
Try to implement a CountDownTimer which should be displayed on a button. It works fine as long as I do not turn the smartphon. After turning the smartphone the button only shows the initial value text even though the cowndowntimer is still running. Does somebody know why the myButton.setText() method do not work in the onTick() method after turning the smartphone?
public class MainActivity extends AppCompatActivity {
private TextView mTextMessage;
private TextView myTextView;
private Button myButton;
private CountDownTimer countDownTimer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextMessage = (TextView) findViewById(R.id.message);
myTextView= (TextView) findViewById(R.id.textView);
myButton= (Button) findViewById(R.id.button);
myTextView.setText("Set new text");
myButton.setText("Set Button text");
myButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myButton.setText("Button clicked");
countDownTimer = new CountDownTimer(60 * 1000, 1000) {
#Override
public void onTick(long millisUntilFinished) {
//After turning the Smartphone the follow both methods do not work anymore
myButton.setText( "Calc: " + millisUntilFinished / 1000);
myTextView.setText("Calc: " + millisUntilFinished / 1000);
}
#Override
public void onFinish() {
}
};
//timer started
countDownTimer.start();
}
});
}
}
Here is my code example...
Notice that I added the "DONE" text in the onFinish() method, so you can set the text for all UI Components you want... and also I added an if statement in the case that the app is running in the background in the case that you want to save some information before the app runs in the background
#Override
protected void onCreate(Bundle savedInstanceState) {
...
myButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myButton.setText("Button clicked");
countDownTimer = new CountDownTimer( 3000, 1000) {
#Override
public void onTick(long millisUntilFinished) {
//After turning the Smartphone the follow both methods do not work anymore
if (!runningBackground) {
myButton.setText("Calc: " + millisUntilFinished / 1000);
myTextView.setText("Calc: " + millisUntilFinished / 1000);
} else {
//Do something
}
}
#Override
public void onFinish() {
if (!runningBackground) {
//Do something
}
mTextMessage.setText("DONE");
runningBackground = false;
running = false;
}
};
//timer started
countDownTimer.start();
running = true;
}
});
}
#Override
protected void onResume() {
super.onResume();
runningBackground = false;
}
#Override
protected void onPause() {
runningBackground = true;
super.onPause();
}
I have a Runnable on a UIThread updating a SeekBar while a MediaPlayer is playing. Yet, when I switch to another activity my application crashes with an exception cause the Runnable keeps on forever even after the MediaPlayer has been destroyed.
This is my code:
public class Guide extends AppCompatActivity implements MediaPlayer.OnPreparedListener {
Button back;
private MediaPlayer m_audio_player;
private Handler m_handler_seek_bar = new Handler();
private SeekBar m_seek_bar;
private Runnable m_seek_bar_runnable;
private void set_up_audio(){
m_audio_player = MediaPlayer.create(this, g_audio[NativeLib.get_active_landmark()] );
m_audio_player.setOnPreparedListener(this);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_guide);
implement_back_button();
set_up_audio();
}
#Override
protected void onStart() {
super.onStart();
set_up_seek_bar();
}
private void set_up_seek_bar() {
m_seek_bar = (SeekBar) findViewById(R.id.seek_bar);
m_seek_bar.setMax(m_audio_player.getDuration());
m_seek_bar_runnable = new Runnable() {
#Override
public void run() {
if(m_audio_player != null ){
m_seek_bar.setProgress(m_audio_player.getCurrentPosition());
}
m_handler_seek_bar.postDelayed(this, 1000);
}
};
// update Seekbar on UI thread
Guide.this.runOnUiThread(m_seek_bar_runnable);
m_seek_bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onStopTrackingTouch(SeekBar seekBar) { }
#Override
public void onStartTrackingTouch(SeekBar seekBar) {}
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if(m_audio_player != null && fromUser){
m_audio_player.seekTo(progress);
}
}
});
}
#Override
protected void onStop() {
if (debug_mode) Log.d(TAG, "onStop");
if (m_audio_player.isPlaying()) {
m_audio_player.stop();
}
m_audio_player.release();
super.onStop();
findViewById(R.id.activity_guide).removeCallbacks(m_seek_bar_runnable);
}
// return button
private void implement_back_button() {
final Intent intent = new Intent(/* pointing at some other activity */);
back = (Button) findViewById(R.id.back_button);
back.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(intent);
}
});
}
}
You need to use:
m_handler_seek_bar.removeCallbacks(m_seek_bar_runnable);
to remove the runnable from handler
#Override
protected void onStop() {
if (debug_mode) Log.d(TAG, "onStop");
if (m_audio_player.isPlaying()) {
m_audio_player.stop();
}
m_audio_player.release();
m_handler_seek_bar.removeCallbacks(m_seek_bar_runnable);
super.onStop();
}
Alternatively you can override the onPause() method of the activity:
#Override
protected void onPause() {
m_handler_seek_bar.removeCallbacks(m_seek_bar_runnable);
super.onPause();
}
Remove all the callbacks from the Handler in onStop using handler.removeCallbacks
Hello I have a timer which I want to restart 4 times in a row always as soon as it ends.
I want to use a for Loop like this: for(int i = 0; i<=3; i++)
My problem is, that I don´t know how to use the loop in my code.
I don´t know where to add the i variable.
(I also added a mediaplayer which Plays an Audio at several times. You might notice, that I use 2 cntdowntimers. It´s an Intervalltimer which starts off with 30 secs, automatically Switches to the second timer which starts 15 seconds, after that the programmes should start again like I said erlier)
Here are the methods I used:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnStart = (Button)findViewById(R.id.btnStart);
btnStop = (Button)findViewById(R.id.btnStop);
textViewTime = (TextView)findViewById(R.id.textViewTime);
textViewTime.setText("00:00:00");
mp = MediaPlayer.create(this, R.raw.vuvuneu);
btnStart = (Button)this.findViewById(R.id.btnStart);
counter=new CountDownTimer(15000, 1000) {
#Override
public void onTick(long millisUntilFinished) {
...
}
#Override
public void onFinish() {
textViewTime.setText("Done");
mp.start();
}
};
final CounterClass timer = new CounterClass(30000,1000);
btnStart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
timer.start();
mp.start();
}
});
btnStop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
timer.cancel();
}
});
}
#TargetApi(Build.VERSION_CODES.GINGERBREAD)
#SuppressLint("NewApi")
public class CounterClass extends CountDownTimer {
public CounterClass(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onFinish() {
counter.start();
mp.start();
}
Thank´s in advance. :)
Full code:
public class MainActivity extends ActionBarActivity {
CountDownTimer counter;
MediaPlayer mp;
Button btnStart, btnStop;
TextView textViewTime;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnStart = (Button)findViewById(R.id.btnStart);
btnStop = (Button)findViewById(R.id.btnStop);
textViewTime = (TextView)findViewById(R.id.textViewTime);
textViewTime.setText("00:00:00");
mp = MediaPlayer.create(this, R.raw.vuvuneu);
btnStart = (Button)this.findViewById(R.id.btnStart);
counter=new CountDownTimer(15000, 1000) {
#Override
public void onTick(long millisUntilFinished) {
long millis = millisUntilFinished;
String hms = String.format("%02d:%02d:%02d", TimeUnit.MILLISECONDS.toHours(millis),
TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)),
TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));
System.out.println(hms);
textViewTime.setText(hms);
}
#Override
public void onFinish() {
textViewTime.setText("Done");
mp.start();
}
};
final CounterClass timer = new CounterClass(30000,1000);
btnStart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
timer.start();
mp.start();
}
});
btnStop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
timer.cancel();
}
});
}
#TargetApi(Build.VERSION_CODES.GINGERBREAD)
#SuppressLint("NewApi")
public class CounterClass extends CountDownTimer {
public CounterClass(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onFinish() {
counter.start();
mp.start();
}
#SuppressLint("NewApi")
#TargetApi(Build.VERSION_CODES.GINGERBREAD)
#Override
public void onTick(long millisUntilFinished) {
textViewTime.setText("seconds remaining: " + millisUntilFinished / 1000);
long millis = millisUntilFinished;
String hms = String.format("%02d:%02d:%02d", TimeUnit.MILLISECONDS.toHours(millis),
TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)),
TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));
System.out.println(hms);
textViewTime.setText(hms);
}
}
}
Try this simple way not need of for loop
public class MainActivity extends Activity {
CountDownTimer workoutTimer;
CountDownTimer restTimer;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnStart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startWorkoutTimer(0);
}
});
btnStop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (workoutTimer!=null ){
workoutTimer.cancel();
}
if (restTimer!=null ){
restTimer.cancel();
}
}
});
}
public void startWorkoutTimer(final int count ){
workoutTimer=new CountDownTimer(30000, 1000) {
#Override
public void onTick(long millisUntilFinished) {
}
#Override
public void onFinish() {
if(count!=3){
startRestTimer(count);
}
}
};
workoutTimer.start();
}
public void startRestTimer(final int count ){
restTimer=new CountDownTimer(15000, 1000) {
#Override
public void onTick(long millisUntilFinished) {
}
#Override
public void onFinish() {
if(count!=3){
startWorkoutTimer(count+1);
}
}
};
restTimer.start();
}
}