I am new to android (and not so hot with it, but trying to learn).
I am creating an application that has a number of various buttons that start countdown timers when they are clicked.
On the activity that has these buttons the following code is used to start the timer:
//Button 1 Start On Click
final CountDown buttonOneTimer = new CountDown(15000,1000);
buttonOne.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
buttonOneTimer.start();
}
});
//Button 2 Start On Click
final CountDown buttonTwoTimer = new CountDown(15000,1000);
buttonTwo.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
buttonTwoTimer.start();
}
});
my CountDown class looks like this:
public class CountDown extends CountDownTimer {
public CountDown (long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onFinish() {
System.out.println("Timer Completed.");
****NAMEOFTHEBUTTONCLICKED****.setText("Timer Completed.");
}
#Override
public void onTick(long millisUntilFinished) {
****NAMEOFTHEBUTTONCLICKED****.setText((millisUntilFinished/1000)+"");
System.out.println("Timer : " + (millisUntilFinished/1000));
}
}
I am trying to get the name of the button pressed into the class so I can set the text on the button to countdown.
I'm sure I am doing all sorts of things wrong or there may be better ways to do it - so if you see areas where I could improve - feel free to critique me!
I read over the tutorial here however it has an 'inner class' (I believe that is what it is called?) inside the current class. A friend of mine said that's very rarely done and to just create a separate class such as CountDown. If I do it the same way as in the tutorial I can get the timer to work (by hardcoding the buttons name where it says *NAMEOFTHEBUTTONCLICKED* above, which means it only works for that button) - but I still need to figure out how to pass that class the buttons name so I don't have to write a separate class for each timer.
Would that be done through Extras? I have had a hard time finding any more info to my specific issue. Any help is appreciated!!
Try passing off the button instance to the Timer:
public class CountDown extends CountDownTimer {
Button button;
public CountDown (long millisInFuture, long countDownInterval, Button button) {
super(millisInFuture, countDownInterval);
this.button = button;
}
#Override
public void onFinish() {
System.out.println("Timer Completed.");
button.setText("Timer Completed.");
}
#Override
public void onTick(long millisUntilFinished) {
button.setText((millisUntilFinished/1000)+"");
System.out.println("Timer : " + (millisUntilFinished/1000));
}
}
Then call like this:
//Button 1 Start On Click
final CountDown buttonOneTimer = new CountDown(15000,1000,buttonOne);
buttonOne.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
buttonOneTimer.start();
}
});
Related
I making an app and I would run in to a problem that I can't fix.
I am using Android Studio and I need to make a Button that I have already made. Do more then it already does. I want it to after display a text also close the app. Do you know how I should program that. It would be very helpful. Thanks in advance.
Here is the Java code:
package test.myapplication;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void buttonOnClick(View v) {
Button button=(Button) v;
((Button) v).setText("Correct");
}
public void buttonAnClick(View q) {
Button button=(Button) q;
((Button) q).setText("Niet goed");
}
}
So I have already made the button in XML and told it:
android:onClick="buttonOnClick"
Hope you can help me out!
If you're looking to have something happen afterwards what you're looking for is this:
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
//What you want to happen later
}
}, 1500); //1500 = 1.5 seconds, time in milli before it happens.
Put that in your button's method.
If you want to close your app you should call
finish();
Finish closes out the current activity. If you have other activities on the stack you'd return to them but since you likely only have 1 it should take you out.
Try this.
public void buttonOnClick(View v) {
Button button=(Button) v;
((Button) v).setText("Correct");
new android.os.Handler().postDelayed(new Runnable() {
#Override
public void run() {
finish();
}
},1000); // milliseconds: 1 seg.
}
Check out CountDownTimer
CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
mTextField.setText("done!");
}
}.start();
If you are trying to get something done with a delay when a button is pressed then do it something like this:
public void buttonOnClick(View v) {
Button button=(Button) v;
button.setText("Correct");
button.postDelayed(new Runnable(){
public void run() {
//runs after 1 second delay on UI thread
}
}, 1000L);
}
If you want to pause then use java.util.concurrent.TimeUnit.
For example:
TimeUnit.SECONDS.sleep(1);
Just put method into your button click function
public void buttonOnClick(View v) {
//call method here
}
If you want to use RxJava
Disposable di = Observable.timer(2, TimeUnit.SECONDS)
.subscribe(timer->{
//next action after 2 seconds
},throwable->{
// throw exception
});
To destroy disposable use, di.dispose();
if Use Runnable and Handler
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
//next action after 2 seconds
}
}, 2*1000);
to stop the handler use, handler.removeCallbacksAndMessages(null);
I'm making simple android app which should have counter which counts from 60 seconds down to 0 seconds. I have one idea how to do it, but I'm not sure if it is the smartest way to do it. And I'm not sure how to make it work in the code.
Idea:
In the .xml file I have added textView. I would make MyService class that extends Service which will be called by the .java file inside OnCreate function (because I want that counting starts immediately). MyService will change content of textView every second (I will have int counter which will be decreased every second and then text of textView will be changed).
Is there any better way to do it?
Here is MyService class:
public class MyService extends Service {
//for timer:
int counter = 0;
static final int UPDATE_INTERVAL = 1000;
private Timer timer = new Timer();
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
doSomethingRepeatedly();
return START_STICKY;
}
private void doSomethingRepeatedly() {
timer.scheduleAtFixedRate( new TimerTask() {
public void run() {
//code for changing the content
}
}, 0, UPDATE_INTERVAL);
}
#Override
public void onDestroy() {
super.onDestroy();
//za timer
if (timer != null){
timer.cancel();
}
}
}
Do I have to put this code in separate .java file?
I'm not sure how to write code for changing the content of textView, because I'm not sure if I can call id of textView because it is in the separated file?
These would be functions for starting the Services:
public void startService(View view) {
startService(new Intent(getBaseContext(), MyService.class));
}
public void stopService(View view) {
stopService(new Intent(getBaseContext(), MyService.class));
}
Where do I have to put them?
Use a CountDownTimer.
Schedule a countdown until a time in the future, with regular
notifications on intervals along the way. Example of showing a 30
second countdown in a text field:
new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
mTextField.setText("done!");
}
}.start();
The calls to onTick(long) are synchronized to this object so that one
call to onTick(long) won't ever occur before the previous callback is
complete. This is only relevant when the implementation of
onTick(long) takes an amount of time to execute that is significant
compared to the countdown interval.
I want to stop CountDownTimer and to restart it, with time when it stopped. I have this code in class CountDownTimer
public class MyDownTimer extends CountDownTimer{
long mills;
public MyDownTimer(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
this.mills=millisInFuture;
}
#Override
public void onFinish() {
GameScreen.showWindow("Time is over","Sorry, time is Over, you lose");
}
#Override
public void onTick(long millisUntilFinished) {
mills=millisUntilFinished/1000;
GameManager.time= millisUntilFinished/1000;
}
}
and Dialog class, he must to showing, when user click in button 'pause'.
Dialog code, as you can see, i start new CountDownTimer in this code
public static void showWindowPause(final MyDownTimer dTime){
final Dialog wdialog= new Dialog(context);
wdialog.setContentView(R.layout.dialog_window);
wdialog.setTitle("title");
TextView text=(TextView)wdialog.findViewById(R.id.txtFirstWord);
text.setText("mainText");
Button dialogButton=(Button)wdialog.findViewById(R.id.button1);
dialogButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
wdialog.dismiss();
dTime.start();
}
});
wdialog.show();
}
and method, where I stoping CountDownTimer and show Dialog window.
long stime =dTime.mills;
dTime.cancel();
dTime=null;
dTime= new MyDownTimer(stime,1000);
GameScreen.showWindowPause(dTime);
when i click button in Dialog window, i see new Dialog, which created in method
MyDownTimer.onFinish()
But if I change line
long stime =dTime.mills;
on
long stime =5000;
CountDownTimer restarts,and all normal.
where i made mistake?
Your question is really confusing , but I THINK I found something that doesn't make sense.
public void onTick(long millisUntilFinished) {
mills=millisUntilFinished/1000;
GameManager.time= millisUntilFinished/1000;
}
I think it should be
mills=millisUntilFinished - 1000;
edit: If you are actually converting millseconds to seconds, then you'll need to do
long stime =dTime.mills*1000;
I have two simple activities MainActivity and ThreadActivity. I call ThreadActivity from MainActivity.
The code ofMainActivity:
public class MainActivity extends Activity {
private Button btn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button)findViewById(R.id.btn2);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, ThreadActivity.class);
startActivity(intent);
}
});
}
}
And the code of ThreadActivity:
public class ThreadActivity extends Activity{
private Thread myThread=null;
Button btn;
int i = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.custom);
btn = (Button)findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
runThread();
}
});
}
void runThread(){
myThread = new Thread() {
public void run() {
while (i++ < 1000) {
try {
runOnUiThread(new Runnable() {
#Override
public void run() {
btn.setText("#" + i);
Log.d("Thread", "I am running " + i);
}
});
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
return;
}
}
}
};
myThread.start();
}
}
When I start ThreadActivity I run a simple thread and change button text.
My Problem
When I loose focus from application, i.e when application becomes partially visible, and I come back I am redirected to ThreadActivity and the thread is still running.
When I leave application running and open a new application, and then come back, I am again redirected to ThreadActivity.
The problem is when I press back button, I am being redirected to first activity MainActivity. But instead when back button is being pressed I want my application to exit. In a few words MainActivity should not exist in the stack.
I tried setting android:noHistory="true" for MainActivity but I could not keep the behavior explained in bullet points working. I mean when I pause the application and restore it back, it redirected me to MainActivity instead of ThreadActivity.
Just call finish() when starting the ThreadActivity:
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, ThreadActivity.class);
startActivity(intent);
finish();
}
});
BUT there is a problem with your app. Use a Timer to set the text of the Button! By using a Thread like you do you are creating a memory leak and that is very bad. Try this:
private int i = 0;
private Timer timer;
private final TimerTask timerTask = new TimerTask() {
#Override
public void run() {
btn.post(new Runnable() {
#Override
public void run() {
btn.setText("#" + i++);
}
});
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.custom);
btn = (Button)findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
timer = new Timer();
timer.schedule(timerTask, 300, 300);
}
});
}
#Override
public void onPause() {
super.onPause();
if(timer != null) {
timer.cancel();
}
}
From your comments to other peoples' answers, it seems like you want the ThreadActivity to always be resumed instead of the MainActivity when your thread is running.
Do the thread in a Service - the service will mean your application's VM is likely to be kept alive longer. An app with no foreground activities can be killed off quite quickly (even if it has background threads running).
You need to persist that the thread is running, and the progress (if, in the real code that is applicable). Currently you could persist the value of i in your while loop.
Your application's default launcher activity (MainActivity) will launch when you click on it from your launcher. Check if the persisted value has been set, and act as though the user started the ThreadActivity in onCreate, if you finish() in onCreate, the user won't see any UI from the MainActivity
Depending on what you're actually trying to do, you might be able to resume the thread depending on the progress persisted - in this example, you could start from the persisted value of i (instead of 0).
What I had to is set android:noHistory="true" for MainActivity and in the ThreadActivity I had to add the solution mention by #NeTeInStEiN in this quesiotn
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
moveTaskToBack(true);
return true;
}
return super.onKeyDown(keyCode, event);
}
I'm trying to make a stopwatch for android as part of a score board app the problem is I'm not sure how to use the chronometer to start, stop, then resume from the time it stopped at or reset to 0. The only problem is that I'm not sure how to use the setBase() and getBase() methods properly.
public class MainActivity extends Activity {
int homecount, awaycount, minutes, seconds;
TextView home, away;
Button stop, start, reset, addhome, subhome, addaway, subaway;
TextView time;
public boolean running;
Chronometer MyChronometer;
long startTime, stopTime;
running = false;
stopTime = 0;
MyChronometer = (Chronometer) findViewById(R.id.timer);
start.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
((Chronometer) findViewById(R.id.timer)).start();
startTime=System.currentTimeMillis();
running = true;
}
});
stop.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
((Chronometer) findViewById(R.id.timer)).stop();
stopTime=System.currentTimeMillis();
running = false;
}
});
reset.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
}
});
You have the variable MyChronometer. Use that every time you want to start or stop.
Also, right after initialization you should run MyChronometer.setBase(SystemClock.elapsedRealtime());. For more details read the documentation: Chronometer and SystemClock.