android studio activity starts before finishing prev one - java

I m calling prog() function in the Mainactivity which performs loading page using progress bar and I call just after the prog function LoginActivity. BUT, it calls login activity before exciting prog function, I am new at the android studio and need your help. here is my code
public class MainActivity extends AppCompatActivity {
ProgressBar pb;
int counter = 0;
TextView textView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.textView);
prog();//loading page
Intent intentLoginPage = new Intent(MainActivity.this,LoginActivity.class);
startActivity(intentLoginPage);
}
public boolean prog(){// to dispay progress bar as loading bar in loading page
pb = findViewById(R.id.progressBar);
final Timer t = new Timer();
TimerTask tt = new TimerTask() {
#Override
public void run(){
counter++;
textView.setText(counter + "%");//0 to 100%
pb.setProgress(counter);
if(counter == 100)
t.cancel();
}
};
t.schedule(tt,0,60);
return true;
}
}

May be you need call startActivity in run()?:
TimerTask tt = new TimerTask() {
#Override
public void run(){
counter++;
textView.setText(counter + "%");//0 to 100%
pb.setProgress(counter);
if(counter == 100) {
t.cancel();
Intent intentLoginPage = new Intent(MainActivity.this,LoginActivity.class);
startActivity(intentLoginPage);
}
}
};

Related

Timer.schedule runs once even with period

I'm a student trying to create an app for my miniproject for one of my modules and I'm trying to create an app that grabs data from a server every few seconds so it's updated. I tried using java timer and timerTask to run the code repeatedly but the program only run once and the get-button doesn't work as intended (suppose to grab data instantly) after implementing the timer. Android Emulator
public class MainActivity extends AppCompatActivity implements OnClickListener{
private Button speed;
private TextView result;
Timer timer;
TimerTask timerTask;
private TextView sSpeed;
final StringBuilder builder = new StringBuilder();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
result = (TextView) findViewById(R.id.result);
sSpeed = (TextView) findViewById(R.id.sSpeed);
speed = (Button) findViewById(R.id.get_button);
speed.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view) {
getWebsite();
}
});
View aboutButton = this.findViewById(R.id.about_button);
aboutButton.setOnClickListener(this);
View exitButton = this.findViewById(R.id.exit_button);
exitButton.setOnClickListener(this);
}
public void onClick(View v) {
switch (v.getId()){
case R.id.get_button:
getWebsite();
break;
case R.id.about_button:
Intent i = new Intent(this, About.class);
startActivity(i);
break;
case R.id.exit_button:
finish();
break;
}
}
private void getWebsite(){
new Thread(new Runnable() {
#Override
public void run() {
try{
Document doc = Jsoup.connect("http://10.0.2.2:8080/Start_Stop_buttons_UTF8.html").get();
// Elements element = doc.getElementsByTag("p");
Elements element = doc.select("p");
//String title = doc.title();
builder.append(title).append("\n");
for (Element tag : element){
builder.append("\n\n").append(tag.text());
}
}catch(IOException e){
//e.printStackTrace();
builder.append("Error : ").append(e.getMessage()).append("\n");
}
runOnUiThread(new Runnable() {
#Override
public void run() {
String a = builder.toString(); // parse data from html into new string
a = a.substring(a.indexOf(":")+1, a.indexOf("Control")).trim();//trim string content
String b = builder.toString();
b = b.substring(11,b.indexOf(":")+1).trim();
double speed = Double.parseDouble(a);//convert string into double
if (speed<1000)
Log.i("HTML text","too slow");
else if((speed> 1500))Log.i("HTML text","too fast!");
result.setText(a);
sSpeed.setText(b);
}
});
}
}).start();
}
protected void onResume() {
super.onResume();
startTimer();
}
public void startTimer(){
timer = new Timer();
timerTask = new TimerTask() {
#Override
public void run() {
getWebsite();
}
};
timer.schedule(timerTask,1500,3000);
}
public void stopTimer(){
if(timer != null){
timer.cancel();
timer.purge();
}
}
}
Am I implementing the timer correctly to run getwebsite() repeatedly and able to get an instant update when get-button is clicked like it should have? Or is there a better way to implement these features using different method?
You are never calling the startTimer method in your ClickListener. You make one call to getWebsite. Change your call to startTimer.
speed.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view) {
startTimer();
}
});
You also might want to check if the timer is already running before you start a new one. To do that assign a null value on your stopTimer method e.g.
public void stopTimer(){
if(timer != null){
timer.cancel();
timer.purge();
timer = null;
}
}
And your startTimer would look like this
public void startTimer(){
if(timer != null) return; // don't start multiple timers
timer = new Timer();
timerTask = new TimerTask() {
#Override
public void run() {
getWebsite();
}
};
timer.schedule(timerTask,1500,3000);
}

Timer Issue on Android Studio

I am having a problem with the Timer in my quiz Game. Essentially it's a multiple choice game and the player is timed on each question. I have the timer starting when the application starts and the player sees the first question. My issue is that if the player answers the question correctly or Incorrectly the timers starts giving random values, even though I reset the timer to 30 seconds on the onclick method. How do I get the timer to start at 30 seconds and countdown normally.
public class MainActivity extends AppCompatActivity {
//Views
TextView questionTextView;
TextView mscoreTextView;
TextView mtimerTextView;
Button mchoice1;
Button mchoice2;
Button mchoice3;
Button mchoice4;
//Constructors
private questions Question = new questions();
private Answers cAnswers = new Answers();
private choices Choices = new choices();
//Variables
private int questionNumber = 0;
private int mScore = 0;
private String correctAnswer;
public void onClick(View view) {
Button answer1 = (Button) view;
if(answer1.getText() == correctAnswer) {
mScore = mScore + 1;
Toast.makeText(getApplicationContext(), "CORRECT!!", Toast.LENGTH_SHORT).show();
mtimerTextView.setText("30s");
runTimer();
} else {
Toast.makeText(getApplicationContext(), "WRONG!!", Toast.LENGTH_SHORT).show();
mtimerTextView.setText("30s");
runTimer();
}
updateScore(mScore);
updateUI();
}
private void updateScore(int points) {
mscoreTextView.setText("" + points + "/" + Question.getLength());
}
public void runTimer() {
new CountDownTimer(30100, 1000) {
#Override
public void onTick(long millisUntilFinished) {
String tick = String.valueOf(millisUntilFinished/1000 + "s");
mtimerTextView.setText(tick);
}
#Override
public void onFinish() {
Toast.makeText(getApplicationContext(), "TIME RAN OUT!!", Toast.LENGTH_LONG).show();
mtimerTextView.setText("0s");
updateUI();
}
}.start();
}
private void updateUI () {
if (questionNumber < Question.getLength()) {
questionTextView.setText(Question.getQuestion(questionNumber));
mchoice1.setText(Choices.getChoices(questionNumber, 1));
mchoice2.setText(Choices.getChoices(questionNumber, 2));
mchoice3.setText(Choices.getChoices(questionNumber, 3));
mchoice4.setText(Choices.getChoices(questionNumber, 4));
correctAnswer = cAnswers.getAnswer(questionNumber);
questionNumber ++;
} else {
Toast.makeText(getApplicationContext(), "This is the last question", Toast.LENGTH_LONG).show();
//Intent intent = new Intent(MainActivity.this, HighScoreActivity.class);
//intent.putExtra("Score", mScore);
//startActivity(intent);
}
runTimer();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
questionTextView = (TextView) findViewById(R.id.questionTextView);
mchoice1 = (Button) findViewById(R.id.choice1);
mchoice2 = (Button) findViewById(R.id.choice2);
mchoice3 = (Button) findViewById(R.id.choice3);
mchoice4 = (Button) findViewById(R.id.choice4);
mtimerTextView = (TextView) findViewById(R.id.timerTextView);
mscoreTextView = (TextView) findViewById(R.id.scoreTextView);
updateScore(mScore);
updateUI();
}
}
The thing is, you never really cancel a timer you've launched. Along with this, for every time you need a timer - you create a new one, which is not essential. The following must solve your problem:
You need to store CountDownTimer in a class field:
private CountDownTimer timer;
Then you can create it once on the start of app:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
timer = createTimer();
...
}
CreateTimer function:
public void createTimer() {
timer = new CountDownTimer(30100, 1000) {
#Override
public void onTick(long millisUntilFinished) {
...
}
#Override
public void onFinish() {
...
}
}
}
So when you need to run timer you just call:
timer.start();
And when user gives an answer, you need to cancel timer first, then start it again:
public void onClick(View view) {
...
timer.cancel();
timer.start();
...
}
Also: you have some duplicated code in your OnClick() method. Regardless of user's answer correctness you need to run timer and set a value to mtimerTextView, so basically you want to do it outside of if-else construction.
You have to define a variable inside a CountDownTimer class.
public void runTimer() {
new CountDownTimer(30100, 1000) {
private int time = 30;
#Override
public void onTick(long millisUntilFinished) {
mtimerTextView.setText(time--+"s");
}
#Override
public void onFinish() {
Toast.makeText(getApplicationContext(), "TIME RAN OUT!!", Toast.LENGTH_LONG).show();
mtimerTextView.setText("0s");
updateUI();
}
}.start();
}
Cancelable Timer
If you want your Timer cancelable you have to define it as a global variable.
private CountDownTimer timer; // global variable
start the timer by calling the below runTimer() method.
public void runTimer() {
timer = new CountDownTimer(30100, 1000) {
private int time = 30;
#Override
public void onTick(long millisUntilFinished) {
mtimerTextView.setText(time--+"s");
}
#Override
public void onFinish() {
Toast.makeText(getApplicationContext(), "TIME RAN OUT!!", Toast.LENGTH_LONG).show();
mtimerTextView.setText("0s");
updateUI();
}
}.start();
}
You can cancel the timer by calling the below method.
public void stopTimer(){
if(timer != null){
timer.cancel();
}
}
Hope this will help

TextView not showing text in a particular listener

I am trying to have a textview display a message for 5 seconds and then disappear.
public class MainActivity extends AppCompatActivity {
public Date start;
public Date end;
Handler handle = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button startButton = (Button) findViewById(R.id.startButton);
Button endButton = (Button) findViewById(R.id.stopButton);
// other variables
final TextView errTextView = (TextView) findViewById(R.id.errorTextView);
final DateFormat df = new SimpleDateFormat("MM/dd/yy");
final Thread t = new Thread(new Runnable() {
#Override
public void run() {
//call function in MainActivity class
handle.postDelayed(this, 100);
}
});
final Thread errt = new Thread(new Runnable() {
#Override
public void run() {
errTextView.setText("");
}
});
startButton.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
if (start != null)
errTextView.setText("Timer Reset");
handler.postDelayed(errt, 5000);
start = new Date();
dateEditText.setText(df.format(start));
hoursEditText.setText("");
errTextView.setText("");
handle.post(t);
}
});
endButton.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
if (start == null) {
errTextView.setText("Timer must be started before pressing Stop. Press Start.");
}
else {
start = null;
}
if(handle != null)
handle.removeCallbacksAndMessages(null);
}
});
If the user presses the start button, start will get the current time and save it. So, if the user presses the start button again, the start button should not be null. If the user presses the twice, the condition should hold, errTextView should display "Timer reset", and the handler should tell the main thread to set errTextView = "" after 5 seconds. errTextView properly shows text in the stop button listener, but not in the start listener.
You call
errTextView.setText("");
Every time startButton is pressed immediately. Therefore errTextView will always be empty once startButton is clicked

Updating android ui with timer

i am new to android programming, i searched through all the answers about this topic but still i am not able to implement what i want to do. My problem is: i want to update the picture at imageview with another picture in given periods. The imageview is needed to be updated with different pictures every time, total of 15-20 times. Here is what i have done so far but it is not working at all.
public class IlkMasal extends Activity {
MediaPlayer sound;
private Handler m_handler;
private ImageView image;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.firsttale);
m_handler = new Handler();
Button menu = (Button)findViewById(R.id.Button01);
Button startbutton = (Button)findViewById(R.id.button1);
sound = MediaPlayer.create(this, R.raw.music4);
sound.start();
image = (ImageView)findViewById(R.id.imageView1);
image.setImageResource(R.drawable.picture2);
startbutton.setOnClickListener(new OnClickListener(){
public void onClick(View v){
m_handler.removeCallbacks(m_statusChecker);
m_handler.postDelayed(m_statusChecker, 2000);
}
});
menu.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Intent main= new Intent("android.intent.action.MAIN");
startActivity(main);
}
});
}
Runnable m_statusChecker = new Runnable()
{
public void run(){
image.setImageResource(R.drawable.picture3);
m_handler.removeCallbacks(m_statusChecker);
m_handler.postDelayed(m_statusChecker, 2000);
}
};
}
After i click startbutton i want to update the ui with different pictures every time. I will appreciate your help.
Yo can set this runnable to run on your onClic and you will still need a method to get the next picture you want to show.
final int delay = 5000;
final int period = 1000;
final Runnable r = new Runnable() {
public void run() {
image.setImageResource(getNextPicture());
postDelayed(this, period);
}
};
postDelayed(r, delay);
Regards.
use runOnUiThread for Updating UI Elements from NON Ui Thread as:
Current_Activity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
image.setImageResource(R.drawable.picture3); //Update UI elements here
}
});

ProgressBar doesn't display progress gradually on splashscreen

I have a splashscreen which lasts 5 seconds, and I want to represent the progress using a ProgressBar.
public class SplashActivity extends Activity {
private static final long SPLASHTIME = 5000;
private ProgressBar progressBar;
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.splash);
SplashHandler handlerSplash = new SplashHandler();
progressBar = (ProgressBar) findViewById(R.id.progression);
progressBar.setMax((int) ((SPLASHTIME) / 1000));
progressBar.setProgress(0);
Message msg = new Message();
msg.what = 0;
handlerSplash.sendMessageDelayed(msg, SPLASHTIME);
ThreadProgressBar threadProgress = new ThreadProgressBar();
threadProgress.start();
}
private class ThreadProgressBar extends Thread {
ProgressBarHandler handlerProgress = new ProgressBarHandler();
public void run() {
try {
while (progressBar.getProgress() <= progressBar.getMax()) {
Thread.sleep(1000);
handlerProgress.sendMessage(handlerProgress.obtainMessage());
}
} catch (java.lang.InterruptedException e) {
}
}
}
private class ProgressBarHandler extends Handler {
public void handleMessage(Message msg) {
progressBar
.incrementProgressBy((int) (SPLASHTIME / SPLASHTIME));
}
}
private class SplashHandler extends Handler {
public void handleMessage(Message msg) {
switch (msg.what) {
default:
case 0:
super.handleMessage(msg);
// new ProgressBarIncrease().execute();
Intent intent = new Intent();
intent.setClass(SplashActivity.this, RdvTab.class);
startActivity(intent);
}
}
}
I guess since SplashActivity itself is an activity, it is ok to block UI right? AsyncTask sometimes run not gradually, if you want the update to be displayed smoothly, how about changing to worker Thread and Handlder.
Create Handler inside SplashActivity
In the main Thread, display progressBar or splash or whatever you like
While make another Thread to run the countdown, once in every second sendEmptyMessage() to Handler. After 5 seconds, send a message to Handler to dismiss dialog and splash then the worker Thread ends.
UPDATED: Sorry for the slow feedback. How about this? I haven't tested it yet and it's not the best implementation though, you can use this logic
public class SplashActivity extends Activity {
private static final int SPLASHTIME = 5000;
// u can change the value here for smoother effect
private static final long UPDATEINTERVAL = 1000;
private ProgressBar progressBar;
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.splash);
progressBar = (ProgressBar) findViewById(R.id.progression);
new Thread(new Runnable(){
#Override
public void run(){
int progress = 0;
while(true){
// send current progress to handler
mHandler.sendEmptyMessage(progress);
// break from the loop after SPLASHSCREEN millis
if(progress > SPLASHSCREEN)
break;
// increase the progress
progress = (int) (progress + UPDATEINTERVAL);
// sleep the worker thread
Thread.sleep(UPDATEINTERVAL);
}
}
}).start();
}
private Handler mHandler = new Handler(){
#Override
public void handleMessage(Message message){
// get the current progress
int progress = message.what;
if(progress <= SPLASHTIME){
progressBar.setProgress(progress);
}
else{
// finish splashActivity here & do what u want do to after splashscreen, for example
finish();
Intent intent = new Intent(SpashActivity.this, MenuActivity.class);
startActivity(intent);
}
}
}
}
You should divide the splash screen time into equal amounts and send the progress update at those intervals.
For example:Lets say the total time is divided into 50 equal intervals as follows
protected void onPreExecute() {
progressbarStep = progressbarWidth/50;
timeStep = 5000/50;
progress = 0;
}
#Override
protected Void doInBackground(Void... params) {
try {
while(progress < progressbarWidth){
progress += progressbarStep;
publishProgress(progress);
SystemClock.sleep(timeStep);
}
return null;
} catch (Exception e) {
}
return null;
}
#Override
protected void onProgressUpdate(Integer... values) {
progressBar.setProgress(values[0]);
}

Categories