im working through my first app right now and i have a problem concerning an update of an Arraylist object.
This is the code:
package com.example.stopwatchmulti;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.SystemClock;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Chronometer;
import android.widget.ListView;
import android.widget.TextView;
import java.util.ArrayList;
public class Main2Activity extends AppCompatActivity {
//Define Variables and Arrays
String ergebnis;
String stopTime;
int anzahl;
int hours;
int minutes;
int seconds;
Chronometer chronometer;
long pauseOffset;
boolean running;
int arrayelements = anzahl - 1;
long timeElapsed;
ListView customListview;
ArrayList<UserIDs> userList;
ArrayList<String> stoppedTime;
CustomListview adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
ergebnis = getIntent().getExtras().getString("Ergebnis");
anzahl = Integer.parseInt(ergebnis);
chronometer = findViewById(R.id.chronometer);
customListview = (ListView) findViewById(R.id.customListview);
userList = new ArrayList<>();
// Add Lines in favour of UserChoice in First activity
for (int i = 1; i <= anzahl; i++) {
UserIDs user = new UserIDs(String.valueOf(i), "Chronometer" + String.valueOf(i), stopTime);
userList.add(user);
}
stopTime = String.valueOf(hours)+":"+String.valueOf(minutes)+":"+String.valueOf(seconds);
// Run Custom ArrayAdapter
adapter = new CustomListview(this, R.layout.usertableobjects, userList);
customListview.setAdapter(adapter);
}
public void startChronometer(View v) {
if (!running) {
chronometer.setBase(SystemClock.elapsedRealtime());
chronometer.start();
running = true;
new Thread(new updateStoptime()).start();
}
}
public void pauseChronometer(View v) {
if (running) {
chronometer.stop();
running = false;
}
}
public void resetChronometer(View v) {
chronometer.setBase(SystemClock.elapsedRealtime());
}
class updateStoptime implements Runnable {
#Override
public void run() {
chronometer.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener() {
#Override
public void onChronometerTick(Chronometer chronometer) {
timeElapsed = SystemClock.elapsedRealtime() - chronometer.getBase();
hours = (int) (timeElapsed / 3600000);
minutes = (int) (timeElapsed - hours * 3600000 / 6000);
seconds = (int) (timeElapsed - hours * 3600000 - minutes * 60000) / 1000;
stopTime = String.valueOf(hours)+":"+String.valueOf(minutes)+":"+String.valueOf(seconds);
Log.i("Zeit:", String.valueOf(stopTime));
}
});
while(running == true){
for (int i = 1; i <= anzahl; i++) {
userList.get(arrayelements).setUserTime(stopTime);
Log.i("LoopNr:", String.valueOf(i));
}
}
}
}
}
The update of the arraylist in the while loop is the reason why the app is crashing when the user clicks the button. If I just loop through and print the number of the loop in the logs, everything is ok.
Is it too much dada? How can I fix it?
PS. Basically I just need the actual countdowntime, when the user clicks the button and then update the listview with the updated array. So if there's a better and smarter way to achieve this instead of using a while loop, i would appreciate a hint.
Thx in advance
Quick correction:
// Here anzahl is not initialized and is being referred to in the next line.
// Please initialize anzahl first;
int anzahl;
int arrayelements = anzahl - 1;
Then, change your while loop to something like this.
while(running == true){
for (int i = 1; i <= anzahl; i++) {
/* here, just call "i -1". this is basically equal to "arrayelements"
which is not properly referenced up in your code.*/
userList.get(i - 1).setUserTime(stopTime);
Log.i("LoopNr:", String.valueOf(i));
}
}
Related
Making a simple BrainTrain app, the updateAnswer method gives out random answers to the question but the issue comes up whenever i call the optionsPressed method and try getting any of the object, the arrayList gives out IndexOutOfBoundsException.
package com.example.nishantsaini.braintrain;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.CountDownTimer;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Random;
import static android.R.color.black;
import static android.R.color.holo_blue_bright;
import static android.R.color.holo_blue_dark;
import static android.R.color.holo_blue_light;
import static android.R.color.holo_green_light;
public class MainActivity extends AppCompatActivity {
Random rnd = new Random();
boolean gameisActive = false;
int count = 0;
CountDownTimer cd;
int var1,var2;
ArrayList<Button> options;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
cd = new CountDownTimer(30000, 1000) {
#Override
public void onTick(long l) {
Log.i("Time Left:", Long.toString(l / 1000));
TextView timer = (TextView) findViewById(R.id.timer);
timer.setText("0:" + String.format("%02d", (l / 1000)));
}
#Override
public void onFinish() {
TextView score = (TextView) findViewById(R.id.Score);
LinearLayout onFinishLayout = (LinearLayout) findViewById(R.id.onFinishLayout);
/*score.setText( "You got " + getScore() + "right!");
*/
}
};
options = new ArrayList<>();
options.add((Button) findViewById(R.id.option2));
options.add((Button) findViewById(R.id.option1));
options.add((Button) findViewById(R.id.option3));
options.add((Button) findViewById(R.id.option4));
}
public void start(View view) {
cd.start();
Button start = (Button) findViewById(R.id.start);
updateQuestion();
updateAnswers(options);
start.setText("Replay");
}
public void optionPressed(View view){
ColorDrawable blue_d = new ColorDrawable(getResources().getColor(R.color.blue_b));
ColorDrawable blue_l = new ColorDrawable(getResources().getColor(R.color.blue_l));
ColorDrawable blue_b = new ColorDrawable(getResources().getColor(R.color.blue_b));
ColorDrawable green = new ColorDrawable(getResources().getColor(R.color.green));
Drawable color = blue_b;
while(options.size() > 0) {
int index = rnd.nextInt(options.size());
Button b = options.get(index);
if (color == blue_b){
color = blue_d;
b.setBackground(color);
}
else if (color == blue_d){
color = green;
b.setBackground(color);
}
else if (color == green){
color = blue_l;
b.setBackground(color);
}
else if (color == blue_l)
{
color = blue_b;
b.setBackground(color);
}
options.remove(index);
}
updateQuestion();
updateScore();
updateAnswers(options);
}
public void updateQuestion(){
var1 = 5 + (int)(Math.random()*20);
var2 = 5 + (int)(Math.random()*20);
TextView question = (TextView) findViewById(R.id.question);
question.setText(Integer.toString(var1) +" + " + Integer.toString(var2) + " = ");
question.setPadding(0,50,0,0);
}
public void updateScore(){
count++;
int correct = 0;
TextView score = (TextView) findViewById(R.id.points);
score.setText(Integer.toString(correct) + "/" + Integer.toString(count));
}
public void updateAnswers(ArrayList<Button> arrayList ){
Button b;
int answer = var1 + var2;
int indexAtWhichRealAnswerGoes = 1+ (int) (Math.random()*3);
int id ;
Log.i("arraylist size",Integer.toString(options.size()));
b = arrayList.get(indexAtWhichRealAnswerGoes);
b.setText(Integer.toString(answer));
id = b.getId();
arrayList.remove(indexAtWhichRealAnswerGoes);
for (int i = 0; i < arrayList.size(); i++) {
int randomanswer = (answer-7) + (int)(Math.random()*(answer+7));
b = arrayList.get(i);
b.setText(Integer.toString(randomanswer));
}
arrayList.add((Button) findViewById(id));
Log.i("arraylist size",Integer.toString(arrayList.size()));
}
}
So, you call updateAnswers(options); using the list that you previously emptied
while(options.size() > 0) {
int index = rnd.nextInt(options.size());
...
options.remove(index);
}
...
updateAnswers(options);
At that point, the list is empty.
In the method, you safely used for (int i = 0; i < arrayList.size(); i++) { to prevent any error but before that we see
int indexAtWhichRealAnswerGoes = 1+ (int) (Math.random()*3);
...
b = arrayList.get(indexAtWhichRealAnswerGoes);
You get that random index without checking the size of the list. (List that is empty at that point).
If you want to keep the list with its value, but the logic can't be change so the remove is necessary, you need to do a copy of the list to work on that one, and pass the original to the method updateAnswers.
List<Button> copyOptions = new ArrayList<>(options);
It will share the same instance, but you can update the list copyOptions without having any impact on options
I'm making a simple quiz app that consist of 10 questions with 10sec countdown timer each questions, which means i have 10 activity for questions. The scoring works while each questions answer correctly multiply by remaining time on CountDownTimer method, so it will be: score = answer * timeLeft; And the total score will be printed on ResultActivity at the end of activity after activity 10. The problem is i cannot pass my score variable through each activity and when i click next button that intent from activity 10 to ResultActivity, the ResultActivity cannot be open or force close. Here is my code:
TestActivity1
package com.finalproject.logicaltest;
import android.content.Intent;
import android.os.CountDownTimer;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.RadioButton;
import android.widget.TextView;
import java.util.Timer;
import butterknife.ButterKnife;
import butterknife.Bind;
import static android.R.id.message;
import static android.R.string.cancel;
import static com.finalproject.logicaltest.R.id.rb1;
import static com.finalproject.logicaltest.R.id.rb2;
import static com.finalproject.logicaltest.R.id.rb3;
import static com.finalproject.logicaltest.R.id.rb4;
public class TestActivity1 extends AppCompatActivity {
#Bind(R.id.rb1) RadioButton rB1;
#Bind(R.id.rb2) RadioButton rB2;
#Bind(R.id.rb3) RadioButton rB3;
#Bind(R.id.rb4) RadioButton rB4;
#Bind(R.id.next) Button bNext;
#Bind(R.id.timer) TextView cDown;
public int answer = 0;
public int score = 0;
public long timeLeft = 0;
//The number of milliseconds in the future from
//the call to start() until the countdown is done
public long millisInFuture = 11000; //11 seconds
//The interval along the way to receive onTick(long) callbacks
long countDownInterval = 1000; //1 second
public long millisUntilFinished;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test1);
ButterKnife.bind(this);
setTimer();
}
public void setTimer() {
//Initialize a new CountDownTimer instance
final CountDownTimer timer = new CountDownTimer(millisInFuture,countDownInterval){
public void onTick(long millisUntilFinished){
//do something in every tick
//Display the remaining seconds to app interface
//1 second = 1000 milliseconds
cDown.setText("" + millisUntilFinished / 1000);
timeLeft = millisUntilFinished / 1000;
}
public void onFinish(){
//Do something when count down finished
cDown.setText("NEXT!");
Intent intent = new Intent(TestActivity1.this,TestActivity2.class);
intent.putExtra("score", score);
startActivity(intent);
finish();
timeLeft = 0;
}
}.start();
bNext.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
timer.cancel();
timeLeft = millisUntilFinished;
Intent intent = new Intent(TestActivity1.this,TestActivity2.class);
intent.putExtra("score", score);
startActivity(intent);
finish();
overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
}
});
}
public void onRadioButtonClicked (View v) {
boolean checked = ((RadioButton) v).isChecked();
switch (v.getId()) {
case rb1:
if (checked){
answer++;
break;
}
case rb2:
if (checked){
answer = 0;
break;
}
case rb3:
if (checked){
answer = 0;
break;
}
case rb4:
if (checked){
answer = 0;
break;
}
}
score = ((int)(timeLeft) * Integer.valueOf(answer));
}
}
It pass score with putExtra through TestActivity2 until TestActivity10 like this:
package com.finalproject.logicaltest;
/**
* Created by VICKY on 19-May-17.
*/
import android.app.Activity;
import android.content.Intent;
import android.os.CountDownTimer;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.View;
import android.widget.Button;
import android.widget.RadioButton;
import android.widget.TextView;
import butterknife.ButterKnife;
import butterknife.Bind;
import static com.finalproject.logicaltest.R.id.rb1;
import static com.finalproject.logicaltest.R.id.rb2;
import static com.finalproject.logicaltest.R.id.rb3;
import static com.finalproject.logicaltest.R.id.rb4;
import static com.finalproject.logicaltest.R.id.rb5;
public class TestActivity10 extends AppCompatActivity {
#Bind(rb1) RadioButton rB1;
#Bind(rb2) RadioButton rB2;
#Bind(rb3) RadioButton rB3;
#Bind(rb4) RadioButton rB4;
#Bind(rb5) RadioButton rB5;
#Bind(R.id.end) Button bEnd;
#Bind(R.id.timer) TextView cDown;
public int answer = 0;
public int score = 0;
public long timeLeft = 0;
//The number of milliseconds in the future from
//the call to start() until the countdown is done
public long millisInFuture = 11000; //11 seconds
//The interval along the way to receive onTick(long) callbacks
long countDownInterval = 1000; //1 second
public long millisUntilFinished;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test10);
ButterKnife.bind(this);
score = getIntent().getExtras().getInt("score");
setTimer();
}
public void setTimer() {
//Initialize a new CountDownTimer instance
final CountDownTimer timer = new CountDownTimer(millisInFuture,countDownInterval){
public void onTick(long millisUntilFinished){
//do something in every tick
//Display the remaining seconds to app interface
//1 second = 1000 milliseconds
cDown.setText("" + millisUntilFinished / 1000);
timeLeft = millisUntilFinished / 1000;
}
public void onFinish(){
//Do something when count down finished
cDown.setText("NEXT!");
Intent intent = new Intent(TestActivity10.this,ResultActivity.class);
intent.putExtra("score", score);
startActivity(intent);
finish();
timeLeft = 0;
}
}.start();
bEnd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
timer.cancel();
timeLeft = millisUntilFinished;
Intent intent = new Intent(TestActivity10.this,ResultActivity.class);
intent.putExtra("score", score);
startActivity(intent);
finish();
overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
}
});
}
public void onRadioButtonClicked (View v) {
boolean checked = ((RadioButton) v).isChecked();
switch (v.getId()) {
case rb1:
if (checked){
answer = 0;
break;
}
case rb2:
if (checked){
answer++;
break;
}
case rb3:
if (checked){
answer = 0;
break;
}
case rb4:
if (checked){
answer = 0;
break;
}
case rb5:
if (checked){
answer = 0;
break;
}
}
score += ((int)(timeLeft) * Integer.valueOf(answer));
}
}
And printed total score on ResultActivity:
package com.finalproject.logicaltest;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import static android.R.id.message;
public class ResultActivity extends AppCompatActivity {
public int score = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_result);
score = getIntent().getExtras().getInt("score");
TextView result = (TextView) findViewById(R.id.total_score);
result.setText(score);
}
}
What's wrong with my code?
Hello Try this code it may help,use according to your logic
Declarations and Initialization
SharedPreferences sharedpreferences;
sharedpreferences = getSharedPreferences("results", Context.MODE_PRIVATE);
storing your score for using in the other activities
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString("score", score);
editor.commit();
Retrieving the stored data
SharedPreferences prefs = this.getSharedPreferences("results", Context.MODE_PRIVATE);
String lanSettings = prefs.getString("score", null);
You can use Application class for that , save score value in Application class which can be accessible from any class you want.(as you only need to save score value.) for more info you can check here
Hope it helps..
IMO you are setting score to your TextView which is incorrect.
Either set it like this:
result.setText(String.valueOf(score));
or like this:
result.setText(" "+score);
See if this works.
I've been having this issue for about a month now and I made a different question about it here: https://stackoverflow.com/questions/38005624/activity-stops-after-certain-time?noredirect=1#comment63454873_38005624
The issue appears to be a problem with the UI thread. After a seemingly random time of running, the UI thread appears to stop doing work. Any 'Runnable' objects passed to it with '.post()' or 'runOnUIThead()' do not get run. Even a simple log message. onClickListener objects also do not fire when the issue occurs. I've had runs where it starts happening within 2 seconds of starting, I've had runs where I make it through the entire game with no issue; all on the same code.
Here is my code if you need it:
The Activity:
package edu.rit.jacob.timeturner;
import android.app.ActivityManager;
import android.app.Application;
import android.app.Dialog;
import android.content.Intent;
import android.os.Looper;
import android.provider.ContactsContract;
import android.provider.Settings;
import android.support.annotation.StringRes;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Layout;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.PopupWindow;
import android.widget.ProgressBar;
import android.widget.SeekBar;
import android.widget.TextView;
public class UniverseActivity extends AppCompatActivity {
public static final String TAG = UniverseActivity.class.getSimpleName();
private UniverseThread thread;
public UniverseThread getThread(){ return thread; }
public static int SECTORS_HEIGHT = 3;
public static int SECTORS_WIDTH = 3;
private Galaxy player;
public Galaxy getPlayer() {
return player;
}
//components:
private UniverseView surfaceView;
private ImageView playerSprite;
private ImageView otherSprite;
private TextView testText;
private SeekBar speedBar;
private ProgressBar timebar;
//Pop ups
private Dialog infoPopUp;
private Dialog startScreen;
//other Galaxies
Galaxy[] galaxies = new Galaxy[SECTORS_HEIGHT * SECTORS_WIDTH];
#Override
protected void onCreate(Bundle savedInstanceState) {
//Setup Activity
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.activity_universe);
Runnable init = new Runnable() {
#Override
public void run() {
initInfoPopUp();
initActivityComponents();
initPlayerAndSprites();
initOtherGalaxies();
initStartScreen();
}
};
runOnUiThread(init);
thread = new UniverseThread(surfaceView.getHolder(), surfaceView);
thread.setRunning(true);
thread.start();
startScreen.setTitle("The Beginning...");
startScreen.show();
Log.d(TAG, "App launched with " + ((ActivityManager)getSystemService(ACTIVITY_SERVICE)).getLargeMemoryClass() + "MB max");
}
#Override
protected void onDestroy() {
super.onDestroy();
boolean retry = true;
while(retry){
try{
thread.join();
retry = false;
}
catch (InterruptedException e){
//try again
}
}
}
private void initStartScreen(){
startScreen = new Dialog(this);
startScreen.setContentView(R.layout.new_game_start);
((TextView)startScreen.findViewById(R.id.textView4)).setText(getString(R.string.start_game_info));
startScreen.findViewById(R.id.buttonStart).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
player.setName("" + ((EditText)startScreen.findViewById(R.id.editText)).getText());
startScreen.dismiss();
}
});
}
private void initInfoPopUp(){
infoPopUp = new Dialog(this);
infoPopUp.setContentView(R.layout.info_popup);
Button infoOption1 = (Button) infoPopUp.findViewById(R.id.option1);
Button infoOption2 = (Button) infoPopUp.findViewById(R.id.option2);
infoOption1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d(TAG, "Option 1 clicked");
//player.incrementGas(galaxies[player.getSector() - 1].getGas());
player.merge(galaxies[player.getSector() - 1], true);
galaxies[player.getSector() - 1] = null;
infoPopUp.dismiss();
}
});
infoOption2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d(TAG, "Option 2 clicked");
//player.incrementGas(galaxies[player.getSector() - 1].getGas() / 2);
//galaxies[player.getSector() - 1].incrementGas(-galaxies[player.getSector() - 1].getGas() / 2);
player.merge(galaxies[player.getSector() - 1], false);
infoPopUp.dismiss();
}
});
}
private void initActivityComponents(){
surfaceView = (UniverseView) findViewById(R.id.surfaceView);
testText = (TextView) findViewById(R.id.testText);
speedBar = ((SeekBar)findViewById(R.id.seekBar));
timebar = ((ProgressBar)findViewById(R.id.progressBar));
}
private void initPlayerAndSprites(){
playerSprite = (ImageView) findViewById(R.id.playerGalaxy);
player = new Galaxy("Milky Way", true, new Velocity(), playerSprite, 25.0f, 1, this);
otherSprite = (ImageView) findViewById(R.id.otherGalaxy);
//Tapping on player galaxy
playerSprite.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d(TAG, "Player sprite clicked, stopping time and bringing up window...");
speedBar.setProgress(0);
infoPopUp.setTitle(player.getName());
infoPopUp.findViewById(R.id.infoPicture).setBackgroundResource(R.drawable.random_temp_galaxy_01);
infoPopUp.findViewById(R.id.option1).setVisibility(View.INVISIBLE);
infoPopUp.findViewById(R.id.option2).setVisibility(View.INVISIBLE);
((TextView)infoPopUp.findViewById(R.id.infoText)).setText(player.toString());
infoPopUp.show();
}
});
//Tapping on other galaxy
otherSprite.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(otherSprite.getVisibility() == View.VISIBLE){
Log.d(TAG, "Other sprite clicked, stopping time and bringing up window...");
speedBar.setProgress(0);
infoPopUp.setTitle(galaxies[player.getSector() - 1].getName());
infoPopUp.findViewById(R.id.infoPicture).setBackgroundResource(R.drawable.random_temp_galaxy_01);
infoPopUp.findViewById(R.id.option1).setVisibility(View.INVISIBLE);
infoPopUp.findViewById(R.id.option2).setVisibility(View.INVISIBLE);
((TextView)infoPopUp.findViewById(R.id.infoText)).setText(galaxies[player.getSector() - 1].toString());
infoPopUp.show();
}
}
});
}
private void initOtherGalaxies(){
for(Galaxy g: galaxies) g = null;
int i = 0, galaxiesNum = 0;
Log.d(TAG, "Populating the universe...");
while(i < galaxies.length){
double rand = Math.random();
if(rand <= 0.25){
galaxies[i] = new Galaxy("Random galaxy", new Velocity(0,0), otherSprite, 25.0f, i + 1, (Math.random()), this);
galaxiesNum += 1;
}
i += 1;
}
Log.d(TAG, "Universe populated with " + galaxiesNum + " galaxies.");
}
public int getSpeed(){
return speedBar.getProgress();
}
public void setTimeProgress(int progress){
try {
if (timebar.getProgress() != progress) {
switch (progress) {
case 10:
//((ProgressBar) findViewById(R.id.progressBar)).getProgress()
progress += 1;
//bring up new popup
break;
case 50:
//do stuff
break;
case 100:
//do end game stuff
boolean retry = true;
while (retry) {
try {
thread.join();
retry = false;
} catch (InterruptedException e) {
//try again
}
}
}
timebar.setProgress(progress);
}
}
catch (NullPointerException e){
Log.d(TAG, "Failed to grab progressBar");
e.printStackTrace();
}
}
public void changeBackground(){
Runnable changeBackground = new Runnable() {
#Override
public void run() {
//Set new background
Log.d(TAG, "Changing to background " + player.getSector());
//surfaceView.setBackgroundResource(R.drawable.background01 + (player.getSector() - 1));
testText.setText("Sector: " + player.getSector());
//Check for other galaxy
if(galaxies[player.getSector() - 1] != null){
otherSprite.setVisibility(View.VISIBLE);
}
else{
otherSprite.setVisibility(View.INVISIBLE);
}
synchronized (this) {
this.notify();
}
}
};
Log.d(TAG, "Passing background runnable to the UI thread");
synchronized (changeBackground){
runOnUiThread(changeBackground);
try {
changeBackground.wait();
}
catch (InterruptedException e){
e.printStackTrace();
}
}
}
public void checkForCollision(){
if(playerSprite.getX() + (playerSprite.getWidth() / 2) >= otherSprite.getX() &&
playerSprite.getX() + (playerSprite.getWidth() / 2) <= otherSprite.getX() + otherSprite.getWidth() &&
playerSprite.getY() + (playerSprite.getHeight() / 2) >= otherSprite.getY() &&
playerSprite.getY() + (playerSprite.getHeight() / 2) <= otherSprite.getY() + otherSprite.getHeight()){
if(otherSprite.getVisibility() == View.VISIBLE){
//switch (player.)
Runnable collide = new Runnable() {
#Override
public void run() {
speedBar.setProgress(0);
otherSprite.setVisibility(View.INVISIBLE);
((TextView)infoPopUp.findViewById(R.id.infoText)).setText("");
//infoPopUp.findViewById(R.id.infoPicture).setBackgroundResource(R.drawable.hubble_merger_01);
infoPopUp.findViewById(R.id.option1).setVisibility(View.VISIBLE);
infoPopUp.findViewById(R.id.option2).setVisibility(View.VISIBLE);
infoPopUp.setTitle("Incoming!");
infoPopUp.show();
}
};
runOnUiThread(collide);
}
}
//Set gauge
Runnable setGauge = new Runnable() {
#Override
public void run() {
((GaugeView)findViewById(R.id.gaugeView)).setTargetValue(player.getGas());
}
};
runOnUiThread(setGauge);
}
}
The Thread:
package edu.rit.jacob.timeturner;
import android.content.Context;
import android.graphics.Canvas;
import android.hardware.*;
import android.hardware.SensorManager;
import android.provider.Settings;
import android.util.Log;
import android.view.SurfaceHolder;
import android.widget.ImageView;
public class UniverseThread extends Thread {
public static final String TAG = UniverseThread.class.getSimpleName();
private double time;
public double getTime(){
return time;
}
private double speed;
public double getSpeed(){
return speed;
}
private boolean running;
public void setRunning(boolean running){
this.running = running;
}
public boolean isRunning(){
return running;
}
//Reference to the UniverseActivity
private SurfaceHolder surfaceHolder;
//Reference to the UniverseView that is the background
private UniverseView universeView;
public UniverseThread(SurfaceHolder surfaceHolder, UniverseView universeView){
super();
this.surfaceHolder = surfaceHolder;
this.universeView = universeView;
running = false;
time = 0;
}
public static float x = 0, y = 0, z = 0;
#Override
public void run(){
Log.d(TAG, "Starting Game Loop");
time = 0.0;
speed = 0.0;
//SensorManager gets SENSOR_SERVICE from android
//Accesses gravity sensor
SensorManager sm = (SensorManager) this.universeView.getContext().getSystemService(Context.SENSOR_SERVICE);
sm.registerListener(new SensorEventListener() {
#Override
public void onSensorChanged(SensorEvent event) {
x = event.values[0];
y = event.values[1];
z = event.values[2];
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}, sm.getDefaultSensor(Sensor.TYPE_GRAVITY), SensorManager.SENSOR_DELAY_GAME);
//save player, velocity, and sprite
Galaxy player = ((UniverseActivity)universeView.getContext()).getPlayer();
Velocity vel = player.getVel();
ImageView sprite = player.getSprite();
boolean changeBackground;
float timesRun = 0f;
while(running){
//every 16 milliseconds (~60 Hz)
timesRun += 1;
final String testStr = "Thread has run for " + (timesRun) + " frames.";
Runnable test = new Runnable() {
#Override
public void run() {
Log.d(TAG, testStr);
}
};
if(timesRun % 60 == 0) ((UniverseActivity) universeView.getContext()).runOnUiThread(test);
//increment the time
speed = ((UniverseActivity)universeView.getContext()).getSpeed();
time += (speed / 7200.0);
((UniverseActivity)universeView.getContext()).setTimeProgress((int) time);
//update player's velocity
((UniverseActivity)universeView.getContext()).getPlayer().getVel().incrementXV(-x / 9.81f);
((UniverseActivity)universeView.getContext()).getPlayer().getVel().incrementYV(y / 9.81f);
//update player's position
//move sprite
sprite.setX((float)(sprite.getX() + (vel.getxV() * speed / 400)));
sprite.setY((float)(sprite.getY() + (vel.getyV() * speed / 400)));
changeBackground = false;
//bottom -> top
if (sprite.getY() + (sprite.getHeight() / 2) > universeView.getHeight()) {
sprite.setY(0 - (sprite.getHeight() / 2));
sprite.setX(universeView.getWidth() / 2);
player.updateSector("BOTTOM");
changeBackground = true;
}
//right -> left
if (sprite.getX() + (sprite.getWidth() / 2) > universeView.getWidth()) {
sprite.setY(universeView.getHeight() / 2);
sprite.setX(0 - (sprite.getWidth() / 2));
player.updateSector("RIGHT");
changeBackground = true;
}
//top -> bottom
if (sprite.getY() + (sprite.getHeight() / 2) < 0) {
sprite.setY(universeView.getHeight() - (sprite.getHeight() / 2));
sprite.setX(universeView.getWidth() / 2);
player.updateSector("TOP");
changeBackground = true;
}
//left -> right
if (sprite.getX() + (sprite.getWidth() / 2) < 0) {
sprite.setY(universeView.getHeight() / 2);
sprite.setX(universeView.getWidth() - (sprite.getWidth() / 2));
player.updateSector("LEFT");
changeBackground = true;
}
if(changeBackground)
{((UniverseActivity)universeView.getContext()).changeBackground();}
((UniverseActivity)universeView.getContext()).checkForCollision();
try{
this.sleep(16L);
}
catch (InterruptedException e){
e.printStackTrace();
}
}
Log.d(TAG, "Game Loop terminated");
}
}
To be clear, no exceptions or errors are being thrown during runtime. The only messages in logcat are my own and the system messages for registering a click, for example. The application does not crash and the sprite is still perfectly controllable. The main things that do not work is the changing of backgrounds, checking for a collision, and the onClickListeners.
Has anyone run into something like this before? Any help would be appreciated.
So after having narrowed the problem down to the Runnable objects I was passing to the UI thread, I took steps to minimize the amount of time I called runOnUIThread() at first it didn't seem to have any effect but eventually I stopped having this problem and that's the only thing I can contribute it to. I might eventually do some more testing to be more concrete that that was the problem and respective solution.
So I'm trying to make a timer like a stopwatch but I'm a complete noob. I tried "combining" things from Here and Here.
The goal is to take user input for how long they want to set the timer for, then when the time is up it does stuff.
This is what I have so far:
package com.example.timer;
import android.app.Activity;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends Activity {
private CountDownTimer countDownTimer;
private boolean timerHasStarted = false;
public TextView text;
private final long interval = 1 * 1000;
EditText editTime1;
Button startButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editTime1 = (EditText)findViewById(R.id.editTime1);
startButton = (Button)findViewById(R.id.startButton);
text = (TextView) this.findViewById(R.id.timer);
startButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
//get the name from edittext and storing into string variable
long timeVal = Long.parseLong(editTime1.getText().toString());
countDownTimer = new MyCountDownTimer(timeVal, interval);
text.setText(text.getText() + String.valueOf(timeVal / 1000));
if (!timerHasStarted) {
countDownTimer.start();
timerHasStarted = true;
startButton.setText("STOP");
} else {
countDownTimer.cancel();
timerHasStarted = false;
startButton.setText("RESTART");
}
}
class MyCountDownTimer extends CountDownTimer {
public MyCountDownTimer(long timeVal, long interval) {
super(timeVal, interval);
}
#Override
public void onTick(long millisUntilFinished) {
text.setText("" + millisUntilFinished / 1000);
}
#Override
public void onFinish() {
text.setText("Times up");
}
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
Few things to note.
The Activity expects the start time to be in milliseconds. If an input value greater than 1000 is given (ex 10 seconds i.e. 10000), the app shows the count down.
The following two lines are placed incorrectly.
countDownTimer = new MyCountDownTimer(timeVal, interval);
text.setText(text.getText() + String.valueOf(timeVal / 1000));
They should be executed only when the count down is started. But in the given implementation, they are run both at start as well as stop.
As a result, a new MyCountDownTimer is created when the count down is stopped, and the countDownTimer.cancel(); is called in this new object rather than the original object. So the count down continues.
Since the setText is performed both on start and stop, the timeVal is appended to the output. That is causing "Times up0" observed.
The updated onClick method is as follows.
public void onClick(View v) {
// get the name from edittext and storing into string variable
long timeVal = Long.parseLong(editTime1.getText().toString());
if (!timerHasStarted) {
countDownTimer = new MyCountDownTimer(timeVal, interval);
text.setText(text.getText() + String.valueOf(timeVal / 1000));
countDownTimer.start();
timerHasStarted = true;
startButton.setText("STOP");
} else {
countDownTimer.cancel();
timerHasStarted = false;
startButton.setText("RESTART");
}
}
I found a way to do that.
basically I let user to input their own values.
layout : HH:MM:SS
then I get these values from layout then process like below :
EditText tv_hour = findViewById(R.id.timerHHValue);
EditText tv_minute = findViewById(R.id.timerMMValue);
EditText tv_second = findViewById(R.id.timerSSValue);
long inputTime = TimeUnit.MINUTES.toMillis(minute) + TimeUnit.HOURS.toMillis(hour) + TimeUnit.SECONDS.toMillis(second);
mCountDownTimer = new CountDownTimer(inputTime, 1000) {
public void onTick(long millisUntilFinished) {
DecimalFormat f = new DecimalFormat("00");
long hours = (millisUntilFinished / 3600000) % 24;
long minutes = (millisUntilFinished / 60000) % 60;
long second = (millisUntilFinished / 1000) % 60;
tv_hour.setText(f.format(hours)+"");
tv_minute.setText(f.format(minutes)+"");
tv_second.setText(f.format(second)+"");
}
#Override
public void onFinish() {
// timerFinish.setVisibility(View.VISIBLE);
tv_hour.setText("00");
tv_minute.setText("00");
tv_second.setText("00");
}
}.start();
}
So I have a class that is supposed to take in a number and get the Prime factors. Those factors are then stored in an ArrayList, Factors, and printed out at the end. Problem is it only works for 4 and when I do 16 it freezes. Any help would be great!
My java class:
package com.frostbytedev.addsub;
import android.app.Activity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import java.util.ArrayList;
/**
* Created by Steven on 7/4/13.
*/
public class Factor extends Activity implements View.OnClickListener{
ArrayList<Integer> Factors = new ArrayList<Integer>();
ArrayList<Integer> toAdd = new ArrayList<Integer>();
ArrayList<Integer> toRemove = new ArrayList<Integer>();
int numToFactor;
TextView FactorResults;
EditText NumberInput;
Button bFactor;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.factor);
initialize();
}
private void initialize() {
FactorResults = (TextView)findViewById(R.id.tvFactors);
NumberInput = (EditText)findViewById(R.id.etNumber);
bFactor = (Button)findViewById(R.id.bFactor);
bFactor.setOnClickListener(this);
}
#Override
public void onClick(View view) {
switch(view.getId()){
case R.id.bFactor:
numToFactor = Integer.parseInt(NumberInput.getText().toString());
FactorNumber(numToFactor);
FindFactors(Factors);
PrintFactors(Factors);
}
}
private void PrintFactors(ArrayList<Integer> factors) {
//String joined = Factors.get(0)+", "+Factors.get(1);
String joined = TextUtils.join(", ", Factors);
FactorResults.setText(joined);
}
private void FactorNumber(int number) {
int multipliedFactors=1;
int i;
double middle = Math.ceil(number/2);
FactorResults.setText(String.valueOf(middle));
for(i=(int)middle;i>1;i--){
if(number%i==0){
Factors.add(i);
}
else
return;
}
for(i=0;i<Factors.size();i++){
multipliedFactors*=Factors.get(i);
}
if(multipliedFactors<number){
FactorNumber(number);
}
if(Factors.size()==0){
FactorResults.setText(number+" has no factors!");
}
}
public void FindFactors(ArrayList<Integer> factors){
int i;
for(i=0;i<factors.size();i++){
int y;
double middle;
middle = Math.ceil(factors.get(i)/2);
for(y=(int)middle;y>1;y--){
if(i%y==0){
toAdd.add(y);
toAdd.add(factors.get(i)/y);
toRemove.add(i);
RemoveExtras(toRemove);
AddNewFactors(toAdd);
FindFactors(Factors);
}
else
return;
}
}
}
private void AddNewFactors(ArrayList<Integer> toAdd) {
int i;
for(i=0;i<toAdd.size();i++){
Factors.add(toAdd.get(i));
}
}
private void RemoveExtras(ArrayList<Integer> toRemove) {
int i;
for(i=0;i<toRemove.size();i++){
Factors.remove(toRemove.get(i));
}
}
}
Try this algorithm
private void factorNumber(int n) {
for (int i = 2; i <= n / i; i++) {
while (n % i == 0) {
factors.add(i);
n /= i;
}
}
if (n > 1) {
factors.add(n);
}
}