UI not updating in Android using AsyncTask - java

I've searched the internet far and wide about getting the UI to update in real-time in Android to no avail. I implemented an AysncTask class as most of the other posts suggested, but it's still not updating my UI in real-time like I want. It only updates after the program is done running. I've even been getting the "Skipped n frames. The application may be doing too much work in its main thread." error, which I don't understand because I'm trying to do these updates in the UI thread. About 5 seconds into running my program the screen turns black and stays like that until its done finishing. Any help would be much appreciated as I've been pulling my hair out on this one for awhile Here's my code.
EDIT: Solved. Removed the Thread.sleep(n) from my UI thread and added it to my AsyncTask. Thanks everyone!
Main class:
public class Home extends Activity {
// Declare objects
Button turingB, socratesB, voltaireB, descartesB, platoB;
int[] eating, thinking, hungry;
Philosopher socrates, turing, voltaire, descartes, plato;
Philosopher[] philosophers;
Chopstick[] chopsticks;
TextView info;
String value;
Context context;
int toastLength;
boolean turingHungry, socratesHungry, voltaireHungry, descartesHungry, platoHungry;
String running;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
// Instantiate objects (keep track of each button individually
context = getApplicationContext();
toastLength = Toast.LENGTH_SHORT;
info = (TextView) findViewById(R.id.textView1);
info.setText("Click Start to begin!");
socratesB = (Button) findViewById(R.id.button1);
descartesB = (Button) findViewById(R.id.button5);
platoB = (Button) findViewById(R.id.button4);
voltaireB = (Button) findViewById(R.id.button3);
turingB = (Button) findViewById(R.id.button2);
running = "false";
// Set all philosophers to thinking (blue)
// socratesB.setBackgroundColor(Color.BLUE);
// descartesB.setBackgroundColor(Color.BLUE);
// platoB.setBackgroundColor(Color.BLUE);
// voltaireB.setBackgroundColor(Color.BLUE);
// turingB.setBackgroundColor(Color.BLUE);
turingHungry = false;
socratesHungry = false;
voltaireHungry = false;
descartesHungry = false;
platoHungry = false;
//Button platoTempButton = (Button) findViewById(R.id.button4);
// Listen for buttons
OnClickListener pBtn = new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
platoHungry = true;
}
};
//platoTempButton.setOnClickListener(pBtn);
OnClickListener tBtn = new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
turingHungry = true;
}
};
OnClickListener sBtn = new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
socratesHungry = true;
}
};
OnClickListener vBtn = new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
voltaireHungry = true;
}
};
OnClickListener dBtn = new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
descartesHungry = true;
}
};
platoB.setOnClickListener(pBtn);
turingB.setOnClickListener(tBtn);
socratesB.setOnClickListener(sBtn);
voltaireB.setOnClickListener(vBtn);
descartesB.setOnClickListener(dBtn);
// Set arrays to count time spent eating, thinking, hungry
eating = new int[5];
thinking = new int[5];
hungry = new int[5];
// Create the chopsticks
chopsticks = new Chopstick[5];
for (int i = 0; i < 5; i ++)
{
chopsticks[i] = new Chopstick(i);
}
for (Chopstick chop: chopsticks)
{
chop.available = true;
}
// Create the philosophers
philosophers = new Philosopher[5];
philosophers[0] = new Philosopher(0, chopsticks[0], chopsticks[1], "Plato", platoB);
philosophers[1] = new Philosopher(1, chopsticks[1], chopsticks[2], "Turing", turingB);
philosophers[2] = new Philosopher(2, chopsticks[2], chopsticks[3], "Socrates", socratesB);
philosophers[3] = new Philosopher(3, chopsticks[3], chopsticks[4], "Voltaire", voltaireB);
philosophers[4] = new Philosopher(4, chopsticks[4], chopsticks[0], "Descartes", descartesB);
// Get sim time from user
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("Simulation Time");
alert.setMessage("Please length of time for the simulation to run (in seconds)");
final EditText input = new EditText(this);
alert.setView(input);
alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
value = String.valueOf(input.getText());
}
});
alert.show();
// Get info
Bundle extras = getIntent().getExtras();
if (extras != null)
{
running = extras.getString("runApp");
value = extras.getString("numToRun");
}
// Run app
if (running.equals("true"))
{
System.out.println("RUNNING!!!");
run(value);
}
}
public void run(String length)
{
int num = Integer.parseInt(length);
// Run num times
for (int i = 0; i < num; i++)
{
try {
// Pass current index, and data arrays to step method
step(i, eating, thinking, hungry);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// Print out some data
for (int j = 0; j < 5; j++)
{
System.out.println("Philosopher " + j + " ate: " + eating[j]);
System.out.println("Philosopher " + j + " thought: " + thinking[j]);
System.out.println("Philosopher " + j + " was hungry: " + hungry[j]);
}
running = "false";
}
// Run simulation n times (n specified by the user)
public void startSim(View v)
{
Intent my_intent = new Intent(this, Home.class);
my_intent.putExtra("runApp", "true");
my_intent.putExtra("numToRun", value);
startActivity(my_intent);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.home, menu);
return true;
}
// Reset simulation
public void reset(View v)
{
Intent my_intent = new Intent(this, Home.class);
startActivity(my_intent);
}
// Return hunger status of philosopher
public boolean isHungry(String name) {
if (name.equals("Voltaire"))
return voltaireHungry;
else if (name.equals("Socrates"))
return socratesHungry;
else if (name.equals("Plato"))
return platoHungry;
else if (name.equals("Turing"))
return turingHungry;
else if (name.equals("Descartes"))
return descartesHungry;
else
return false;
}
// Step method for simulation
// Takes the current index and each of the data arrays
public void step(int i, int[] eating, int[] thinking, int[] hungry) throws InterruptedException
{
// Make random number
Random randomGenerator = new Random();
int num = randomGenerator.nextInt(10);
// Randomly set a philosopher isFull to false (hungry) (10% chance for each to become hungry if not specified by the user)
if (isHungry(philosophers[0].name))
philosophers[0].isFull = false;
if (num == 1 || isHungry(philosophers[1].name))
philosophers[1].isFull = false;
if (num == 2 || isHungry(philosophers[2].name))
philosophers[2].isFull = false;
if (num == 3 || isHungry(philosophers[3].name))
philosophers[3].isFull = false;
if (num == 4 || isHungry(philosophers[4].name))
philosophers[4].isFull = false;
// For each philosopher
for (Philosopher phil: philosophers)
{
// Print current info
System.out.println("PHIL: " + phil.name + " NUM: " + num + " RIGHT: " + phil.rightChopstick.available + " LEFT: " + phil.leftChopstick.available);
// Temp id var
int tempId = phil.id;
// If philosopher is hungry, try to eat
if (phil.isFull == false)
{
// Try to eat only if both chopsticks are available
if (phil.rightChopstick.pickUp(phil.name) && phil.leftChopstick.pickUp(phil.name))
{
// Change button color
new Background(phil.button).execute((long) 1);
//Toast.makeText(context, phil.name + " is eating.", toastLength).show();
// Increment time spent eating
eating[tempId]++;
}
// Check to see if the philosopher is already eating (has both chopsticks)
else if (phil.rightChopstick.who.equals(phil.name) && phil.leftChopstick.who.equals(phil.name))
{
//Toast.makeText(context, phil.name + " is eating.", toastLength).show();
new Background(phil.button).execute((long) 1);
// Increment eating
eating[tempId]++;
// 30% chance to stop eating
if (num >= 5 && num <=7)
{
// Put down chopsticks
phil.rightChopstick.putDown();
phil.leftChopstick.putDown();
// Stop eating
phil.isFull = true;
}
}
// Hungry
else
{
// Change button color
new Background(phil.button).execute((long) 3);
//Toast.makeText(context, phil.name + " is hungry.", toastLength).show();
// Increment time spent hungry
hungry[tempId]++;
}
}
// Thinking
else
{
new Background(phil.button).execute((long) 2);
//Toast.makeText(context, phil.name + " is thinking.", toastLength).show();
// Increment time spent thinking
thinking[tempId]++;
}
Thread.sleep(1000);
}
// Make each step count as 1 second (1000 miliseconds)
System.out.println("--------------------------------------------------------------");
Thread.sleep(5000);
}
}
Background class (AsyncTask):
public class Background extends AsyncTask<Long, Void, Void>
{
// Variables
String color;
Button button;
public Background(Button button)
{
this.button = button;
}
#Override
protected Void doInBackground(Long... params) {
// Get which color the button needs to be
try
{
// Change the color based on the value passed in
if (params[0] == 3)
{
color = "RED";
}
else if (params[0] == 2)
{
color = "BLUE";
}
else if (params[0] == 1)
{
color = "GREEN";
}
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
// Set button to that color
System.out.println("Updating color in real time...");
button.setBackgroundColor(Color.parseColor(color));
}
#Override
protected void onPreExecute() {
}
#Override
protected void onProgressUpdate(Void... values) {
}
}

Here is one problem
Thread.sleep(1000);
and here is another
Thread.sleep(5000);
these are both making the UI sleep for a total of 6 seconds. You almost never want to call sleep() on the UI Thread. You can do this in doInBackground() or anywhere else that runs on a background Thread.
Edit
You don't set your Listeners. For example:
platoB.setOnClickListener(new pBtn());

Progress can be set with publishProgress in your asynctask, you get a call to onProgressUpdate in the UI thread.

Related

Android app layout components are null when restoring from background after some time

The reason for the crash is a NullPointerException which is thrown because the fragment's UI Components are null for some reason.
Exception is thrown at this line:
private void setGameInfo(Game game) {
// Stop/hide all ongoing progress bars (loading)
mSummaryLoading.setVisibility(View.GONE);
}
Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ProgressBar.setVisibility(int)' on a null object reference
This is my (very long) fragment code where the progress bar mSummaryLoading can be found
public class GameInfoFragment extends Fragment implements GamePageActivity.OnDataLoadedListener {
public GameInfoFragment() {
// Required empty public constructors
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_game_info, container, false);
String dateFormat = SharedPrefManager.read(SharedPrefManager.KEY_PREF_DATE_FORMAT, getString(R.string.default_date_format));
mDateFormatterGMT = new SimpleDateFormat(dateFormat);
mDateFormatterGMT.setTimeZone(TimeZone.getTimeZone("GMT"));
mTodayTimeMillis = Calendar.getInstance().getTimeInMillis();
mDatabaseHelper = DatabaseHelper.getDatabaseHelper(getActivity());
mAlarmReceiver = new AlarmReceiver();
return view;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
// onViewCreated make sure the view is fully created, called after onCreateView
super.onViewCreated(view, savedInstanceState);
// Summary UI
mTextSummary = view.findViewById(R.id.summary);
mReadMore = view.findViewById(R.id.read_more);
mSummaryLoading = view.findViewById(R.id.summary_loading);
// Platforms UI
mPlatformsLayout = view.findViewById(R.id.platforms);
mPlatformsLayoutExtra = view.findViewById(R.id.platforms_2);
// Countdown UI
mHeaderReleasesTitle = view.findViewById(R.id.header_count_down);
mHeaderReleaseDate = view.findViewById(R.id.header_release_date);
mCountdownLayout = view.findViewById(R.id.countdown_view);
mOutNowTxt = view.findViewById(R.id.out_now_txt);
mDaysTxt = view.findViewById(R.id.days_txt);
mHoursText = view.findViewById(R.id.hours_txt);
mMinutesText = view.findViewById(R.id.minutes_txt);
mSecondsText = view.findViewById(R.id.seconds_txt);
mCategoryText = view.findViewById(R.id.category_txt);
mNoteTxt = view.findViewById(R.id.note_txt);
// Release dates table UI
mSpinnerRegions = view.findViewById(R.id.spinner_regions);
mNoReleaseDatesTxt = view.findViewById(R.id.empty_releases);
mReleaseTableLoading = view.findViewById(R.id.releases_loading);
mTableReleaseDates = view.findViewById(R.id.table_release_dates);
// Websites (Social link) UI
mWebsitesList = view.findViewById(R.id.websitesList);
mNoWebsitesTxt = view.findViewById(R.id.empty_websites_list);
mSocialLoading = view.findViewById(R.id.social_loading);
mWebsitesAdapter = new WebsitesAdapter(getContext());
mWebsitesList.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));
mWebsitesList.setAdapter(mWebsitesAdapter);
// Start progressbar
mSummaryLoading.setVisibility(View.VISIBLE);
mSocialLoading.setVisibility(View.VISIBLE);
mReleaseTableLoading.setVisibility(View.VISIBLE);
// User region
String region = SharedPrefManager.read(SharedPrefManager.KEY_PREF_REGION, "north_america");
mRegion = SharedPrefManager.getRegionToFilter(region);
// Release social actions
// The RELEASE DATA OBJECT
mRelease = ((GamePageActivity)getActivity()).getRelease();
mAuth = FirebaseAuth.getInstance();
mAuthListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
if (firebaseAuth.getCurrentUser() != null) {
// When the user signs in in this page [refresh]
initHypes(mRelease.getId());
}
}
};
mReleasesActions = view.findViewById(R.id.release_actions);
// Favorite
mAddToFavorite = view.findViewById(R.id.favorite);
mAddNote = view.findViewById(R.id.add_note);
mEditAlarms = view.findViewById(R.id.alarms);
mShareRelease = view.findViewById(R.id.share);
mDatabaseHelper = DatabaseHelper.getDatabaseHelper(getActivity());
// HYPE!!!
mHypeLoading = view.findViewById(R.id.hype_loading);
mHypeRelease = view.findViewById(R.id.hype);
mHypeCountTxt = view.findViewById(R.id.hype_count);
mHypeCountTxt.setText("0 hypes");
// Release actions icons
mStarIcon = view.findViewById(R.id.star_icon);
mHeartIcon = view.findViewById(R.id.favorite_icon);
mNoteIcon = view.findViewById(R.id.note_icon);
mAlarmIcon = view.findViewById(R.id.alarm_icon);
// Default colors [hype]
mStarIcon.setImageResource(R.drawable.ic_star);
mHeartIcon.setImageResource(R.drawable.ic_favorite);
mNoteIcon.setImageResource(R.drawable.ic_note);
mAlarmIcon.setImageResource(R.drawable.ic_notification);
// Init likes (hypes) and puts color to yellow if liked
// if game has't been released yet or has been released for a week
if (mRelease.getDate() >= mTodayTimeMillis - 604800000) {
initHypes(mRelease.getId());
mHypeRelease.setVisibility(View.VISIBLE);
} else {
mHypeRelease.setVisibility(View.GONE);
}
// Social actions, favorite, alarm, note, etc.
initReleaseActions();
// Countdown
initCountdown(mRelease);
// Platforms
initPlatforms(mRelease);
// The release date
mHeaderReleaseDate.setText(mDateFormatterGMT.format(mRelease.getDate()));
// Expandable TextView
mReadMore.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View v) {
if (mTextSummary.isExpanded()) {
mTextSummary.collapse();
mReadMore.setText("Read more");
} else {
mTextSummary.expand();
mReadMore.setText("Collapse");
}
}
});
// Like [hype up] game
mHypeRelease.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mAuth.getCurrentUser() != null) {
onStarClicked(mRelease, mAuth.getCurrentUser().getUid());
} else {
startActivity(new Intent(getActivity(), SignInActivity.class));
}
}
});
}
public void loadHypeLayout() {
if (mHypeLoading.getVisibility() == View.VISIBLE) {
mHypeLoading.setVisibility(View.GONE);
mHypeCountTxt.setVisibility(View.VISIBLE);
mStarIcon.setVisibility(View.VISIBLE);
} else {
mHypeLoading.setVisibility(View.VISIBLE);
mHypeCountTxt.setVisibility(View.GONE);
mStarIcon.setVisibility(View.GONE);
}
}
public void initReleaseActions() {
// User saved release actions
if (mDatabaseHelper.favoriteExists(mRelease)) {
mHeartIcon.setImageResource(R.drawable.ic_favorite_red);
mAddNote.setVisibility(View.VISIBLE);
// If game already out, can't have alarms
if (mRelease.getDate() >= Calendar.getInstance().getTimeInMillis()) {
mEditAlarms.setVisibility(View.VISIBLE);
} else {
mEditAlarms.setVisibility(View.GONE);
}
} else {
mAddNote.setVisibility(View.GONE);
mEditAlarms.setVisibility(View.GONE);
}
if (mDatabaseHelper.alarmExists(mRelease)) {
mAlarmIcon.setImageResource(R.drawable.ic_notification_blue);
}
if (mDatabaseHelper.noteExists(mRelease)) {
mNoteIcon.setImageResource(R.drawable.ic_note_red);
mNoteTxt.setText("Edit note");
}
mAddToFavorite.setOnClickListener(new FavoriteOnClickListener(getContext(), mRelease, mAlarmIcon, mHeartIcon, mNoteIcon,
mAddNote, mEditAlarms));
mAddNote.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AddNoteFragment addNoteFragment = new AddNoteFragment();
addNoteFragment.setDatabaseHelper(mDatabaseHelper);
addNoteFragment.setRelease(mRelease);
addNoteFragment.setIcon(mNoteIcon);
addNoteFragment.setNoteTxt(mNoteTxt);
addNoteFragment.show(getFragmentManager(), addNoteFragment.getTag());
}
});
mEditAlarms.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
EditAlarmsFragment editAlarmsFragment = new EditAlarmsFragment();
editAlarmsFragment.setDatabaseHelper(mDatabaseHelper);
editAlarmsFragment.setRelease(mRelease);
editAlarmsFragment.setIcon(mAlarmIcon);
editAlarmsFragment.show(getFragmentManager(), editAlarmsFragment.getTag());
}
});
mShareRelease.setOnClickListener(new ShareOnClickListener(getContext(), mRelease, mAPISearchedGame));
}
public void initPlatforms(Release release) {
List<Integer> platforms = release.getPlatforms();
if (platforms != null) {
for (int i = 0; i < platforms.size(); i++) {
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT);
params.setMargins(0, 0, 18, 0);
TextView current = new TextView(getActivity());
current.setId(i + 1);
current.setLayoutParams(params);
current.setPadding(8, 8, 8, 8);
current.setTextSize(14);
current.setGravity(Gravity.CENTER);
current.setTextColor(ContextCompat.getColor(getActivity(), R.color.color_text));
switch (platforms.get(i)) {
case 6:
current.setText("Win");
current.setBackgroundResource(R.drawable.round_pc);
break;
case 49:
current.setText("Xbox One");
current.setBackgroundResource(R.drawable.round_xboxone);
break;
case 48:
current.setText("PS4");
current.setBackgroundResource(R.drawable.round_ps4);
break;
case 9:
current.setText("PS3");
current.setBackgroundResource(R.drawable.round_ps3);
break;
case 46:
current.setText("PS Vita");
current.setBackgroundResource(R.drawable.round_psvita);
break;
case 12:
current.setText("Xbox 360");
current.setBackgroundResource(R.drawable.round_xbox360);
break;
case 130:
current.setText("Nintendo Switch");
current.setBackgroundResource(R.drawable.round_switch);
break;
case 41:
current.setText("Wii U");
current.setBackgroundResource(R.drawable.round_wiiu);
break;
case 37:
current.setText("3DS");
current.setBackgroundResource(R.drawable.round_3ds);
break;
case 3:
current.setText("Linux");
current.setBackgroundResource(R.drawable.round_linux);
break;
case 14:
current.setText("Mac");
current.setBackgroundResource(R.drawable.round_mac);
break;
case 34:
current.setText("Android");
current.setBackgroundResource(R.drawable.round_android);
break;
case 39:
current.setText("IOS");
current.setBackgroundResource(R.drawable.round_ios);
break;
case 5:
current.setText("Wii");
current.setBackgroundResource(R.drawable.round_wii);
break;
}
// if (i == 7; change to platform_2)
if (i < 7) {
mPlatformsLayout.addView(current);
} else {
mPlatformsLayoutExtra.setVisibility(View.VISIBLE);
mPlatformsLayoutExtra.addView(current);
}
}
}
}
public void initCountdown(Release release) {
// https://stackoverflow.com/questions/46332398/android-countdown-based-on-gmt-utc-and-not-the-users-timezone
// Set the release date in millis to calender set to GMT timezone (universal)
Calendar releaseCalendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
releaseCalendar.setTimeInMillis(release.getDate());
// Get the release date
LocalDate localReleaseDate = null;
boolean success = false;
int dayOfMonth = releaseCalendar.get(Calendar.DAY_OF_MONTH);
while (!success) {
try {
localReleaseDate = LocalDate.of(releaseCalendar.get(Calendar.YEAR),
releaseCalendar.get(Calendar.MONTH) + 1,
dayOfMonth);
success = true;
} catch (DateTimeException dateTimeException) {
// Invalid date e.g 'November 31' Small fix?
dayOfMonth -= 1;
}
}
LocalTime localReleaseTime = LocalTime.of(0, 0, 0); // midnight release
// Set to the user's timezone
ZoneId zoneId = ZoneId.of(TimeZone.getDefault().getID());
ZonedDateTime zonedDateTime = ZonedDateTime.of(localReleaseDate, localReleaseTime, zoneId);
// Convert from a time zone to UTC. Same point on the timeline
Instant instant = zonedDateTime.toInstant();
Duration d = Duration.between(Instant.now(), instant);
mCountdownTimer = new CountDownTimer(d.toMillis() , 1000) { // adjust the milli seconds here
public void onTick(long millisUntilFinished) {
// 1 sec = 1000 millis
long seconds = millisUntilFinished / 1000;
long minutes = seconds / 60;
long hours = minutes / 60;
long days = hours / 24;
mDaysTxt.setText(String.valueOf(days));
mHoursText.setText(String.valueOf(hours % 24));
mMinutesText.setText(String.valueOf(minutes % 60));
mSecondsText.setText(String.valueOf(seconds % 60));
}
public void onFinish() {
mHeaderReleasesTitle.setText("Released on");
mOutNowTxt.setVisibility(View.VISIBLE);
mCountdownLayout.setVisibility(View.GONE);
// Games already out, can't have alarms, but they can still be hyped for a week after release
mEditAlarms.setVisibility(View.GONE);
}
};
mCountdownTimer.start();
long updatedAt = release.getUpdatedAt();
if (updatedAt != 0) {
mTxtLastUpdatedOnRelease.setText("Release date last updated on " + mDateFormatterGMT.format(updatedAt));
}
}
private void setGameInfo(Game game) {
// Stop/hide all ongoing progress bars (loading)
mSummaryLoading.setVisibility(View.GONE);
mSocialLoading.setVisibility(View.GONE);
mReleaseTableLoading.setVisibility(View.GONE);
loadHypeLayout();
// The category
String category = game.getCategory();
if (category != null) {
mCategoryText.setText(game.getCategory());
}
String summary = game.getSummary();
if (summary != null) {
mTextSummary.setText(summary);
} else {
mTextSummary.setText("No summary available");
mReadMore.setVisibility(View.GONE);
}
List<Website> websites = game.getWebsites();
if (websites != null) {
mWebsitesAdapter.setData(websites);
} else {
mWebsitesList.setVisibility(View.GONE);
mNoWebsitesTxt.setVisibility(View.VISIBLE);
}
// Organizing Table Release dates
List<ReleaseDate> releaseDates = game.getReleaseDates();
if (releaseDates != null) {
// Creating the Hash map / Every region that exists will have a list of release dates
mRegionsReleaseHashMap = new HashMap<>();
for (ReleaseDate releaseDate : releaseDates) {
String region = releaseDate.getRegionName();
// Doesn't contain region
if (!mRegionsReleaseHashMap.containsKey(region)) {
mRegionsReleaseHashMap.put(region, new ArrayList<ReleaseDate>());
}
mRegionsReleaseHashMap.get(region).add(releaseDate);
}
// Setting first the spinner, then the data
if (!mRegionsReleaseHashMap.isEmpty()) {
List<String> regions = new ArrayList<>();
for (String region : mRegionsReleaseHashMap.keySet()) {
if (!regions.contains(region)) { regions.add(region); }
}
Collections.sort(regions); // By alpha order
// Spinner takes an ArrayAdapter as adapter
ArrayAdapter spinnerAdapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_spinner_item, regions);
spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mSpinnerRegions.setAdapter(spinnerAdapter);
/*
I removed this
// First spinner item is always the user's region
String defaultRegion = ((GamePageActivity) getActivity()).mRegion;
if (regions.contains(defaultRegion)) {
mSpinnerRegions.setSelection(spinnerAdapter.getPosition(defaultRegion));
} else if (regions.contains("Worldwide")) {
mSpinnerRegions.setSelection(spinnerAdapter.getPosition("Worldwide"));
} */
// Spinner listener [called on selected and on shown]
mSpinnerRegions.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
initReleaseDatesTable(mRegionsReleaseHashMap.get(mSpinnerRegions.getSelectedItem().toString()));
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
} else {
mNoReleaseDatesTxt.setVisibility(View.VISIBLE);
mTableReleaseDates.setVisibility(View.GONE);
}
long updatedAt = game.getUpdatedAt();
if (updatedAt != 0) {
mTxtLastUpdatedOnGame.setText("Game data last updated on " + mDateFormatterGMT.format(updatedAt));
}
}
public void initReleaseDatesTable(List<ReleaseDate> releaseDates) {
mTableReleaseDates.removeAllViews();
TableRow tblRowHeader = new TableRow(getContext());
TextView txtPlatform = new TextView(getContext());
txtPlatform.setTextSize(16);
txtPlatform.setText("Platform");
tblRowHeader.addView(txtPlatform);
TextView txtReleaseDate = new TextView(getContext());
txtReleaseDate.setTextSize(16);
txtReleaseDate.setText("Release Date");
tblRowHeader.addView(txtReleaseDate);
TextView txtCountdown = new TextView(getContext());
txtCountdown.setTextSize(16);
txtCountdown.setText("Days left");
tblRowHeader.addView(txtCountdown);
mTableReleaseDates.addView(tblRowHeader);
// Creating rows
// One row: platform, release date and pre-order
for (int i = 0; i < releaseDates.size(); i++) {
TableRow tblRowData = new TableRow(getContext());
TextView textPlatformData = new TextView(getContext());
String platform = releaseDates.get(i).getPlatformName();
// Gaming Reminder doesn't support/recognize this platform ;)
if (!platform.isEmpty()) {
textPlatformData.setTextSize(16);
textPlatformData.setText(platform);
tblRowData.addView(textPlatformData);
TextView textReleaseDateData = new TextView(getContext());
textReleaseDateData.setTextSize(16);
long releaseTimeMillis = releaseDates.get(i).getDate();
textReleaseDateData.setText(mDateFormatterGMT.format(releaseTimeMillis));
tblRowData.addView(textReleaseDateData);
TextView textCountdownData = new TextView(getContext());
textCountdownData.setTextSize(16);
long daysLeft = AppUtil.daysBetween(releaseTimeMillis);
if (daysLeft <= 0) {
textCountdownData.setText("Now Out");
} else {
textCountdownData.setText(daysLeft + " days");
}
tblRowData.addView(textCountdownData);
mTableReleaseDates.addView(tblRowData);
}
}
}
// Shows the number of likes in our respective likes count view
private void initHypes(final long releaseId) {
// Toast.makeText(getContext(), "Loading likes...", Toast.LENGTH_SHORT).show();
DatabaseReference likeRef = mLikesRef.child(mRegion);
likeRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.child(String.valueOf(releaseId)).exists()) {
long starCount = dataSnapshot.child(String.valueOf(releaseId)).child("starCount").getValue(Long.class);
mHypeCountTxt.setText(starCount + " hypes");
// Now check if current logged in user hyped it (the release) up
if (mAuth.getCurrentUser() != null) {
// the stars node is only used to check if the current user hyped up the current game
if (dataSnapshot.child(String.valueOf(releaseId)).child("stars").hasChild(mAuth.getCurrentUser().getUid())) {
mStarIcon.setImageResource(R.drawable.ic_star_yellow);
} else {
mStarIcon.setImageResource(R.drawable.ic_star);
}
}
} // else : no votes yet for this release
}
#Override
public void onCancelled(DatabaseError databaseError) { }
});
}
private void onStarClicked(final Release release, final String uid) {
final DatabaseReference postRef = mLikesRef.child(mRegion).child(String.valueOf(release.getId()));
postRef.runTransaction(new Transaction.Handler() {
#Override
public Transaction.Result doTransaction(MutableData mutableData) {
Post p = mutableData.getValue(Post.class);
if (p == null) {
// When p is null this means, the release object [no node exists] hasn't been added to likes
p = new Post();
p.setStarCount(1);
p.setRelease(release);
p.setDate(release.getDate());
p.getStars().put(uid, true);
mutableData.setValue(p);
return Transaction.success(mutableData);
}
if (p.getStars().containsKey(uid)) {
// Unstar the post and remove self from stars
p.setStarCount(p.getStarCount() - 1);
if (p.getStarCount() == 0) {
// Delete the node
postRef.removeValue();
}
// remove the entire key
p.getStars().remove(uid);
} else {
// Star the post and add self to stars
p.setStarCount(p.getStarCount() + 1);
// Update the date [flawed, some release dates saved in likes can have a different release date]
// Update the release each time the user puts a star
p.setRelease(release);
p.getStars().put(uid, true);
}
// Set value and report transaction success
mutableData.setValue(p);
return Transaction.success(mutableData);
}
#Override
public void onComplete(DatabaseError databaseError, boolean b,
DataSnapshot dataSnapshot) {
// Transaction completed
}
});
}
#Override
public void onStart() {
super.onStart();
mAuth.addAuthStateListener(mAuthListener);
}
#Override
public void onDataLoaded(Game game) {
mCategoryText.setText("but");
setGameInfo(game);
}
}
When you app is put in the background and brought back, it can kill the fragment and recreated it. If you method setGameInfo is being called with nulls its because the method is being called between when the Fragment is recreated and when its onViewCreated (where you set up the view references) is called.
From your code, I have to guess there is something happening in the owning Activity that invokes the fragment's onDataLoaded method while the fragment is still be initialized.
Use your debugger to put a breakpoint at this method and in onViewCreated to see which is being called first and why.
I think the problem, or most part of it at least is where you are initializing the views.
As a rule of thumb, anything that needs to be created for the Fragment which is not a View should be declared in onCreate(), and anything with a findViewById() should go in onCreateView(), not onViewCreated().
For example, I would move this part to onCreate():
String dateFormat = SharedPrefManager.read(SharedPrefManager.KEY_PREF_DATE_FORMAT, getString(R.string.default_date_format));
mDateFormatterGMT = new SimpleDateFormat(dateFormat);
mDateFormatterGMT.setTimeZone(TimeZone.getTimeZone("GMT"));
mTodayTimeMillis = Calendar.getInstance().getTimeInMillis();
mDatabaseHelper = DatabaseHelper.getDatabaseHelper(getActivity());
mAlarmReceiver = new AlarmReceiver();
Also put here the creation of the adapter and the database helper:
mWebsitesAdapter = new WebsitesAdapter(getContext());
Other candidates for onCreate() are:
String region = SharedPrefManager.read(SharedPrefManager.KEY_PREF_REGION, "north_america");
mRegion = SharedPrefManager.getRegionToFilter(region);
// Release social actions
// The RELEASE DATA OBJECT
mRelease = ((GamePageActivity)getActivity()).getRelease();
mAuth = FirebaseAuth.getInstance();
mAuthListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
if (firebaseAuth.getCurrentUser() != null) {
// When the user signs in in this page [refresh]
initHypes(mRelease.getId());
}
}
};
And most if not all you have in onViewCreated() to onCreateView()
I didn't run your code and it is quite long, so there may be exceptions to this in what you have done, but onViewCreated() should remian practically empty after the refactoring.
Note: I think the databasehelper is set twice, after moving it ot onCreate() you shouldn't need to repeat the initialization somewhere else.

How to calculate reaction time?

I have developed an app that has two buttons (left and right) and a Textview that will pop up on the screen.Each button has it's corresponding word.
The user has to click the button that corresponds to TextView's word as quickly as possible when it shows. I want to calculate it's reaction time on clicking the button.
Below is my code.
public class Place_to_go_1 extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_place_to_go_1);
placeone = Global_variables.getFirst_choice_label();
placetwo = Global_variables.getSecond_choice_label();
p_one = (TextView)findViewById(R.id.p_one);
p_two = (TextView)findViewById(R.id.p_two);
btnleft = (ImageButton)findViewById(R.id.btnleft);
btnright = (ImageButton)findViewById(R.id.btnright);
next = (ImageButton)findViewById(R.id.Next);
lblmaintext = (TextView)findViewById(R.id.lblmaintext);
lblprompt = (TextView)findViewById(R.id.lblprompt);
lblreact = (TextView)findViewById(R.id.lblreact);
imgmain = (ImageView)findViewById(R.id.imgmain);
//prac = (ImageView) findViewById(R.id.prac);
Intent intent = getIntent();
final String randomId = intent.getStringExtra("Info_id");
//============ validate image if not empty
setImage_onLaunch();
//==== populate left and right choices===
populate_headers(placeone, placetwo);
//==== populate attributes=====
populate_attributes();
//============== instruction ======
setInstruction();
//=============media
wrong_press = MediaPlayer.create(this, R.raw.wrong_press);
react_fast = MediaPlayer.create(this, R.raw.react_faster);
//=== left button click trigger
btnleft.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String position = "H";
if (tanan[counter].equals(p_one.getText().toString())) {
lblprompt.setVisibility(View.INVISIBLE);
HashMap<String,String> queryValues = new HashMap<String, String>();
queryValues.put("Info_id",randomId);
queryValues.put("Choice",p_one.getText().toString());
queryValues.put("Reaction_time",String.valueOf(elapsedTime));
queryValues.put("Position",position);
queryValues.put("Main",main);
queryValues.put("Error",error);
mydb.insertTest(queryValues);
counter++;
if (counter < tanan.length) {
btnleft.setEnabled(false);
btnright.setEnabled(false);
timeStamp = System.currentTimeMillis();
//Toast.makeText(Place_to_go_1.this, ""+timeStamp, Toast.LENGTH_SHORT).show();
getreactionTime(p_one.getText().toString(), String.valueOf((((timeStamp) / 1000.0) - ((timeRun) / 1000.0))));
setIntervalTime();
} else {
//======end sa data
postEnd();
}
} else {
// Toast.makeText(Place_to_go_1.this, "Wrong pressed", Toast.LENGTH_SHORT).show();
//wrong_press.start();
wrong_click_audio();
error = "1";
lblprompt.setVisibility(View.VISIBLE);
}
}
});
//==== right button click trigger
btnright.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String position = "A";
if (tanan[counter].equals(p_two.getText().toString())) {
lblprompt.setVisibility(View.INVISIBLE);
HashMap<String,String> queryValues = new HashMap<String, String>();
queryValues.put("Info_id",randomId);
queryValues.put("Choice",p_two.getText().toString());
queryValues.put("Reaction_time", String.valueOf(elapsedTime));
queryValues.put("Position",position);
queryValues.put("Main",main);
queryValues.put("Error",error);
mydb.insertTest(queryValues);
counter++;
if (counter < tanan.length) {
btnleft.setEnabled(false);
btnright.setEnabled(false);
timeStamp = System.currentTimeMillis();
//Toast.makeText(Place_to_go_1.this, ""+timeStamp, Toast.LENGTH_SHORT).show();
getreactionTime(p_two.getText().toString(), String.valueOf((((timeStamp) / 1000.0) - ((timeRun) / 1000.0))));
setIntervalTime();
} else {
//======end sa data
postEnd();
}
} else {
// Toast.makeText(Place_to_go_1.this, "Wrong pressed", Toast.LENGTH_SHORT).show();
// wrong_press.start();
wrong_click_audio();
error = "1";
lblprompt.setVisibility(View.VISIBLE);
}
}
});
// ==== next button for the next activity (Place to go 2)
next.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = getIntent();
String randomId = intent.getStringExtra("Info_id");
//============= launch activity 2 for place to go
if (instruct == true) {
next.setVisibility(View.INVISIBLE);
// prac.setVisibility(View.VISIBLE);
CountDownTimer();
} else {
//Toast.makeText(getApplication(),"Saved Successfully.",Toast.LENGTH_SHORT).show();
Intent i = new Intent(getApplicationContext(), Place_to_go_2.class);
i.putExtra("Info_id", randomId);
startActivity(i);
}
}
});
}
public void interval(){
if(counter < tanan.length){
lblmaintext.setVisibility(View.VISIBLE);
timeRun = System.currentTimeMillis();
btnleft.setEnabled(true);
btnright.setEnabled(true);
lblmaintext.setText(tanan[counter]);
setImage();
imgmain.setVisibility(View.VISIBLE);
react = true;
reacFaster();
}else{
//======end sa data
Toast.makeText(Place_to_go_1.this, "End data", Toast.LENGTH_SHORT).show();
lblmaintext.setVisibility(View.VISIBLE);
lblmaintext.setText("Ok for now");
}
}
public void setIntervalTime(){
react = false;
lblreact.setVisibility(View.INVISIBLE);
reactFaster_timer.cancel();
lblmaintext.setVisibility(View.INVISIBLE);
lblreact.setVisibility(View.INVISIBLE);
imgmain.setVisibility(View.INVISIBLE);
timer = new CountDownTimer(Global_variables.interval_time_before_choices_will_show,Global_variables.interval_time_before_choices_will_show) {
#Override
public void onTick(long millisUntilFinished) {
}
#Override
public void onFinish() {
interval();
}
}.start();
}
int counter_countdown = 0;
int drawwable_amber = R.drawable.amber;
String arr[] = {"Ready...","Set...","Start."};
public void CountDownTimer(){
btnleft.setVisibility(View.INVISIBLE);
btnright.setVisibility(View.INVISIBLE);
lblmaintext.setBackgroundResource(0);
timer = new CountDownTimer(4000,1000) {
#Override
public void onTick(long millisUntilFinished) {
lblmaintext.setTextSize(35);
lblmaintext.setText(arr[counter_countdown]);
counter_countdown++;
}
#Override
public void onFinish() {
btnleft.setVisibility(View.VISIBLE);
btnright.setVisibility(View.VISIBLE);
lblmaintext.setBackgroundResource(drawwable_amber);
// lblmaintext.setText(tanan[counter]);
//setImage();
val_first_launch();
timeRun = System.currentTimeMillis();
react = true;
reacFaster();
}
}.start();
}
public void reacFaster(){
reactFaster_timer = new CountDownTimer(Global_variables.reaction_time_first_param,Global_variables.reaction_time_second_param) {
#Override
public void onTick(long millisUntilFinished) {
}
#Override
public void onFinish() {
if(react == true){
//Toast.makeText(Place_to_go_1.this, "please react faster", Toast.LENGTH_SHORT).show();
react_fast.start();
lblreact.setVisibility(View.VISIBLE);
}
}
}.start();
}
public void populate_headers(String one,String two){
//== this methos sets headers as random==//
headers = new ArrayList<String>();
headers.add(one);
headers.add(two);
Collections.shuffle(headers);
p_one.setText(headers.get(0));
p_two.setText(headers.get(1));
}
public void populate_attributes(){
attributes = new ArrayList<String>();
for(int h =0;h < 5;h++){
attributes.add(placeone);
attributes.add(placetwo);
}
Collections.shuffle(attributes);
tanan = new String[attributes.size()];
for(int k = 0; k < tanan.length;k++ ){
tanan[k] = attributes.get(k);
}
}
public void postEnd(){
instruct = false;
lblprompt.setVisibility(View.INVISIBLE);
btnright.setVisibility(View.INVISIBLE);
btnleft.setVisibility(View.INVISIBLE);
next.setVisibility(View.VISIBLE);
lblmaintext.setBackgroundResource(0);
lblmaintext.setTextSize(20);
p_one.setVisibility(View.INVISIBLE);
p_two.setVisibility(View.INVISIBLE);
imgmain.setVisibility(View.INVISIBLE);
reactFaster_timer.cancel();
lblreact.setVisibility(View.INVISIBLE);
lblmaintext.setText("Well done!\nNext, is the main task. It is exactly the same as before but this time words will appear on the screen that might distract you. \nPlease respond as quickly as you can.\n Press Next to begin");
}
//=========== validate if image is enabled/ disble if not set
public void setImage_onLaunch(){
if(Global_variables.getFirst_choice_image().equals("") || Global_variables.getSecond_choice_image().equals("")){
disbaleImage();
}else{
}
}
public void setImage(){
/* if(tanan[counter].equals(p_one.getText().toString())){
imgmain.setImageBitmap(BitmapFactory.decodeFile(Global_variables.getFirst_choice_image()));
}else{
imgmain.setImageBitmap(BitmapFactory.decodeFile(Global_variables.getSecond_choice_image()));
}*/
if(placeone.equals(tanan[counter])){
imgmain.setImageBitmap(BitmapFactory.decodeFile(Global_variables.getFirst_choice_image()));
}else{
imgmain.setImageBitmap(BitmapFactory.decodeFile(Global_variables.getSecond_choice_image()));
}
}
public void val_first_launch(){
if(Global_variables.getFirst_choice_image().equals("") || Global_variables.getSecond_choice_image().equals("")){
lblmaintext.setVisibility(View.VISIBLE);
lblmaintext.setText(tanan[counter]);
}else{
imgmain.setVisibility(View.VISIBLE);
if(placeone.equals(tanan[counter])){
imgmain.setImageBitmap(BitmapFactory.decodeFile(Global_variables.getFirst_choice_image()));
}else{
imgmain.setImageBitmap(BitmapFactory.decodeFile(Global_variables.getSecond_choice_image()));
}
}
}
public void disbaleImage(){
imgmain.setBackgroundResource(0);
imgmain.setVisibility(View.GONE);
}
#Override
public void onBackPressed() {
super.onBackPressed();
startActivity(new Intent(getApplication(), MainActivity.class));
finish();
}
public String getreactionTime(String domain, String time){
// Toast.makeText(Place_to_go_1.this, time, Toast.LENGTH_SHORT).show();
//== get reaction time to every activity
Global_variables.set_timeStamps(domain, time);
return domain;
}
//===== prompt instruction====
public void setInstruction(){
btnleft.setVisibility(View.INVISIBLE);
btnright.setVisibility(View.INVISIBLE);
lblmaintext.setBackgroundResource(0);
lblmaintext.setTextSize(20);
lblmaintext.setText("Instruction:\n\nIf " + p_one.getText().toString() + " appears, press arrow left.\n If " + p_two.getText().toString() +
" appears, press arrow right.\n\nRespond as quickly as you can.");
next.setVisibility(View.VISIBLE);
}
//===== prompt instruction====
public void wrong_click_audio(){
wrong_press.start();
}
//=============end class====================
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Checks the orientation of the screen
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
// Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
//Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
}
}
}
Here a simple logic to calculate reaction time is to create a variable which hold a time when a question is popped up to user and the time when a user show a click reaction to question and calculate the time difference between these two action.
long timeWhenQuestionShowed = System.currentTimeMillis();
long timeWhenUserReacted = System.currentTimeMillis();
long reactionTime = timeWhenQuestionShowed - timeWhenUserReacted;
This should help:
Try using onTouch instead of onClick.
long timeBefor=0;
long timeReaction=0;
btnleft.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: // when pressed
timeBefore=System.currentTimeMillis();
break;
case MotionEvent.ACTION_UP: // when released
timeReaction=System.currentTimeMillis() - timeBefore; // calculate difference
break;
}
}
timeReaction is your desired value.
The idea is to calculate the difference between 2 points in time. I will write 2 examples of calculating time difference in Java / measuring reaction time in Java:
System.nanoTime() or System.currentTimeMillis()
Differences are discussed here: Time measuring overhead in Java
long endTimeNanoSec = 0;
long startTimeNanoSec = System.nanoTime();
myWorkThatNeedsTiming(); // wait for user button press here
endTimeNanoSec = System.nanoTime();
long totalWorkTimeNanos = endTimeNanoSec - startTimeNanoSec;
Java StopWatch
JavaDoc: StopWatch
Stopwatch stopwatch = Stopwatch.createStarted();
myWorkThatNeedsTiming(); // wait for user button press here
stopwatch.stop();
long totalWorkTimeMillis = stopwatch.elapsedMillis();

Why doesn't my delay happen?

currently developing an app where I need to take a number of wifi measurements, take an average of these measurements and store the averages. However I've found that I have to implement a delay between measurements otherwise there's not enough time to see any variation between measurements.
In the Handler.postDelayed() method I've tried to implement a 2000ms delay, however when I view the timestamp of the logs generated by TAKEWIFI, there appears to be no delay at all.
Any help would be greatly appreciated :)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_takewifi);
final String[] strArr = new String[60];
for (int i=0;i<60;i++)
{
strArr[i] = "EMPTY";
}
WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
final int state = wifi.getWifiState();
if(state == WifiManager.WIFI_STATE_ENABLED) {
RawData rD = new RawData();
Toast.makeText(TakeWifi.this,
"Taking RSS measurement, hold still!",
Toast.LENGTH_SHORT).show();
for(int a=0;a<30;a++)
{
wifi.startScan();
final Handler handler = new Handler();
handler.post(new Runnable() {
#Override
public void run() {
handler.postDelayed(this, 2000);
}
});
List<ScanResult> results = wifi.getScanResults();
String index = (String) results.toString();
int forCount = 0;
int ifCount = 0;
for (String retval: index.split(",")){
if (((forCount%5==1)||(forCount%5==3))&&(ifCount<60)){
strArr[ifCount] = retval;
strArr[ifCount] = strArr[ifCount].replace(" BSSID:", "BSSID:");
strArr[ifCount] = strArr[ifCount].replace(" level:", "level:");
ifCount++;
}
forCount++;
}
for(int check=0;check<60;check++)
{
Log.d("TAKEWIFI","strArr[" + check + "]: " + strArr[check]);
}
rD.setStrArr(strArr,rD);
}
final String[] temp = rD.getStrArr(rD);
for(int b=0;b<20;b++)
{
strArr[b]=temp[b];
}
for(int i=0;i<20;i++)
{Log.d("STRARR",strArr[i]);}
List<String> stringList = Arrays.asList(temp);
for (int i = 0; i < 20; i++) {
Log.d("STRLIST",stringList.get(i));
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, stringList);
ListView listview = (ListView) findViewById(R.id.listview);
if (listview==null)
{
Log.d("LISTVIEW","NULL");
}listview.setAdapter(adapter);
Toast.makeText(TakeWifi.this,"RSS measurement complete",Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(TakeWifi.this,"Wifi Not Enabled",Toast.LENGTH_SHORT).show();
}
final Button commitBut=(Button)findViewById(R.id.button4);
commitBut.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
if(state == WifiManager.WIFI_STATE_ENABLED){
commit(strArr);
}
else
{
Toast.makeText(TakeWifi.this,"Wifi Not Enabled",Toast.LENGTH_SHORT).show();
}
}
});
}
Replace your handle with this and put everything you want delayed into it.
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// Everything you want to be delayed needs to go inside this runnable
}
}, 2000);
You are waiting in another thread (hence the run() method in your handler) :) Try removing that whole handler magic and call Thread.sleep directly.

tic tac toe game, multiplayer android

am new to android and was using the sample api's using the bluetooth chat code i created a tic tac toe game,
i'm able to connect two devices via bluetooth and can use the bluetooth name as the opponent's name
eg if my device name is "ABC" and opponents "DEF"
then the names in my device will be You : 0 DEF: 0
opponets device will have names YOU : 0 ABC : 0
( the score is initially set to 0).
where the problem is :
each of these device consider it as player 1 and can make a move. But i want to restrict it, the player who first tries to connect the device gets the 1st move and then the other.
how can i deal with the situation ??? please help
my code :
public class test extends Activity {
// Debugging
private static final String TAG = "TicTacToe";
private static final boolean D = true;
// Message types sent from the BluetoothChatService Handler
public static final int MESSAGE_STATE_CHANGE = 1;
public static final int MESSAGE_READ = 2;
public static final int MESSAGE_WRITE = 3;
public static final int MESSAGE_DEVICE_NAME = 4;
public static final int MESSAGE_TOAST = 5;
// Key names received from the BluetoothChatService Handler
public static final String DEVICE_NAME = "device_name";
public static final String TOAST = "toast";
// Intent request codes
private static final int REQUEST_CONNECT_DEVICE = 1;
private static final int REQUEST_ENABLE_BT = 2;
// Layout Views
private TextView mTitle;
private ListView mConversationView;
private EditText mOutEditText;
private Button mSendButton;
// Name of the connected device
private String mConnectedDeviceName = null;
// Array adapter for the conversation thread
private ArrayAdapter<String> mConversationArrayAdapter;
// String buffer for outgoing messages
private StringBuffer mOutStringBuffer;
// Local Bluetooth adapter
private BluetoothAdapter mBluetoothAdapter = null;
// Member object for the chat services
private BluetoothGameService mGameService = null;
// Member object for the chat services
private BluetoothChatService mChatService = null;
//game variable
// player names initialized with default values.
CharSequence player_name_1 = "Player 1";
CharSequence player_name_2 = "Player 2";
// score initialized to 0.
public static int ben = 0;
int game_mode = 0;
int count = 0; // to count the number of moves made.
int player = 1; // sets the player no. to 1 by default.
int score_player_1 = 0;
int score_player_2 = 0;
int arr[][] = {{0,0,0},{0,0,0},{0,0,0}}; // array which stores the movements made.
// dialog IDs
final int NAME_DIALOG_ID = 1;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(D) Log.e(TAG, "+++ ON CREATE +++");
// Set up the window layout
requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
setContentView(R.layout.tictactoe);
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title);
// Set up the custom title
mTitle = (TextView) findViewById(R.id.title_left_text);
mTitle.setText(R.string.app_name);
mTitle = (TextView) findViewById(R.id.title_right_text);
// Get local Bluetooth adapter
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
// If the adapter is null, then Bluetooth is not supported
if (mBluetoothAdapter == null) {
Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show();
finish();
return;
}
final Button st = (Button) findViewById(R.id.start);
st.setEnabled(false);
}
// set player names
protected Dialog onCreateDialog(int id){
Dialog mdialog = new Dialog(this);
switch(id) {
case NAME_DIALOG_ID:
mdialog.setContentView(R.layout.name);
mdialog.setTitle("Player Names");
mdialog.setCancelable(true);
final EditText namep1 = (EditText) mdialog.findViewById(R.id.namep1);
final EditText namep2 = (EditText) mdialog.findViewById(R.id.namep2);
Button ok_b = (Button) mdialog.findViewById(R.id.ok);
ok_b.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
player_name_2 = mConnectedDeviceName; //player 2 name
player_name_1 = "You"; //player 1 name
score_player_1 = 0;
score_player_2 = 0;
new_game(namep1.getText()); //calling fn
dismissDialog(1);
}
});
break;
default:
mdialog = null;
}
return mdialog;
}
OnClickListener button_listener = new View.OnClickListener() {
public void onClick(View v) {
ImageButton ibutton = (ImageButton) v;
// Button inactive for further clicks until a result is obtained.
ibutton.setClickable(false);
ibutton.setBackgroundResource(R.drawable.xo);
// Increment Count on clicking the button.
count++;
if ((count % 2 != 0)) {
player = 1;
ibutton.setImageResource(R.drawable.system_cross);
}
else if ((count % 2 == 0)) {
player = 2; // human player.
ibutton.setImageResource(R.drawable.system_dot);
}
// after_move function to check the result and decide.
after_move(ibutton);
}
};
public void new_game(CharSequence player_name) {
setContentView(R.layout.tictactoe);
final ImageButton b3 = (ImageButton) findViewById(R.id.b3);
final ImageButton b2 = (ImageButton) findViewById(R.id.b2);
final ImageButton b1 = (ImageButton) findViewById(R.id.b1);
final ImageButton b6 = (ImageButton) findViewById(R.id.b6);
final ImageButton b5 = (ImageButton) findViewById(R.id.b5);
final ImageButton b4 = (ImageButton) findViewById(R.id.b4);
final ImageButton b9 = (ImageButton) findViewById(R.id.b9);
final ImageButton b8 = (ImageButton) findViewById(R.id.b8);
final ImageButton b7 = (ImageButton) findViewById(R.id.b7);
// set the OnClickListeners.
b1.setOnClickListener(button_listener);
b2.setOnClickListener(button_listener);
b3.setOnClickListener(button_listener);
b4.setOnClickListener(button_listener);
b5.setOnClickListener(button_listener);
b6.setOnClickListener(button_listener);
b7.setOnClickListener(button_listener);
b8.setOnClickListener(button_listener);
b9.setOnClickListener(button_listener);
// Re-enable the Click-able property of buttons.
b1.setClickable(true);
b2.setClickable(true);
b3.setClickable(true);
b4.setClickable(true);
b5.setClickable(true);
b6.setClickable(true);
b7.setClickable(true);
b8.setClickable(true);
b9.setClickable(true);
// dismissDialog(NAME_DIALOG_ID);
// dismissDialog(HELP_DIALOG_ID);
// update the score board with the already existing values.
// this line should come ONLY after the player name is set in the above lines.
set_score(3);
// reset the array arr.
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
arr[i][j] = 0;
/* *********************************************************
* Initiates the computer's chance during start of the game,
* as well as when there is a win / loose and the next
* chance is for the computer.
* *********************************************************
if ((game_mode == 1) && (count % 2 != 0))
CompGame();
*/
}
public void set_score(int player_number) {
TextView tv = (TextView) findViewById(R.id.scoreboard);
if (player_number == 1)
score_player_1 += 1;
else if (player_number == 2)
score_player_2 += 1;
else ; // Don't change score, but set the score board right.
CharSequence score_txt = player_name_1 + " : " + score_player_1 + " " + player_name_2 + " : " + score_player_2;
tv.setText(score_txt);
}
public void after_move (ImageButton ib) {
CharSequence pos_str = ""; // position as a string.
int pos = 0;
boolean result = false;
pos_str = (CharSequence) ib.getTag(); // get the position from the tag.
pos = (int) pos_str.charAt(0) - 48; // char to integer conversion.
// set the values in the array according to the player number.
if (player == 1) {
if (pos < 4)
arr[0][pos - 1] = 1;
else if (pos < 7)
arr[1][(pos - 1) % 3] = 1;
else if (pos < 10)
arr[2][(pos - 1) % 3] = 1;
}
else {
if (pos < 4)
arr[0][pos - 1] = 2;
else if (pos < 7)
arr[1][(pos - 1) % 3] = 2;
else if (pos < 10)
arr[2][(pos - 1) % 3] = 2;
}
// Check for the game result.
result = result_check(player);
// Result check section.
if (result == true) {
// check for the player number.
if (player == 1) {
set_score(1);
if (game_mode == 0) {
show_result("Congrats. " + player_name_1 + " wins !!");
}
}
else {
set_score(2);
if (game_mode == 0) { // human vs human
show_result("Congrats. " + player_name_2 + " wins !!");
}
}
return;
}
else if ((result == false) && arr_isFull()) {
show_result(" Game Draw ! "); // leave the space, or else dialog becomes cramped.
return;
}
else { } // continue game.
}
public boolean result_check(int player_local) {
boolean win = true;
int k = 0;
// check for horizontal condition only.
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (arr[i][j] != player_local) { // check with player number.
win = false;
break;
}
} // column loop.
if (win == true) {
return true;
}
win = true;
} // row loop.
win = true; // resetting win to true.
// checking for vertical condition only.
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (arr[j][i] != player_local) {
win = false;
break;
}
} // column loop.
if (win == true) {
return true;
}
win = true;
} // row loop.
win = true; // reset win to true.
// check for diagonal condition 1.
for (int i = 0; i < 3; i++)
if (arr[i][k++] != player_local) {
win = false;
break;
}
if (win == true) {
return true;
}
k = 2;
win = true; // reset win to true;
// check for diagonal condition 2.
for (int i = 0; i < 3; i++)
if (arr[i][k--] != player_local) {
win = false;
break;
}
if (win == true) {
return true;
}
return false;
}
public boolean show_result(CharSequence message) //function to select the game mode
{
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(message)
.setPositiveButton("Continue", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// reset the game environment.
new_game(player_name_2);
}
});
AlertDialog alert = builder.create();
alert.show();
return true;
}
public boolean arr_isFull () {
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
if (arr[i][j] == 0)
return false;
return true;
}
#Override
public void onStart() {
super.onStart();
if(D) Log.e(TAG, "++ ON START ++");
// If BT is not on, request that it be enabled.
// setupChat() will then be called during onActivityResult
if (!mBluetoothAdapter.isEnabled()) {
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
// Otherwise, setup the chat session
} else {
if (mGameService == null)
setupGame();
}
}
private void setupGame() {
Log.d(TAG, "setupGame()");
// Initialize the BluetoothGameService to perform bluetooth connections
mGameService = new BluetoothGameService(this, mHandler);
// Initialize the buffer for outgoing messages
mOutStringBuffer = new StringBuffer("");
}
#Override
public synchronized void onResume() {
super.onResume();
if(D) Log.e(TAG, "+ ON RESUME +");
// Performing this check in onResume() covers the case in which BT was
// not enabled during onStart(), so we were paused to enable it...
// onResume() will be called when ACTION_REQUEST_ENABLE activity returns.
if (mGameService != null) {
// Only if the state is STATE_NONE, do we know that we haven't started already
if (mGameService.getState() == BluetoothChatService.STATE_NONE) {
// Start the Bluetooth chat services
mGameService.start();
}
}
}
#Override
public synchronized void onPause() {
super.onPause();
if(D) Log.e(TAG, "- ON PAUSE -");
}
#Override
public void onStop() {
super.onStop();
if(D) Log.e(TAG, "-- ON STOP --");
}
#Override
public void onDestroy() {
super.onDestroy();
// Stop the Bluetooth chat services
if (mGameService != null) mGameService.stop();
if(D) Log.e(TAG, "--- ON DESTROY ---");
}
/**
* Sends a message.
* #param message A string of text to send.
*/
private void sendMessage(String message) {
// Check that we're actually connected before trying anything
if (mChatService.getState() != BluetoothChatService.STATE_CONNECTED) {
Toast.makeText(this, R.string.not_connected, Toast.LENGTH_SHORT).show();
return;
}
// Check that there's actually something to send
if (message.length() > 0) {
// Get the message bytes and tell the BluetoothChatService to write
byte[] send = message.getBytes();
mChatService.write(send);
// Reset out string buffer to zero and clear the edit text field
mOutStringBuffer.setLength(0);
mOutEditText.setText(mOutStringBuffer);
}
}
// The Handler that gets information back from the BluetoothChatService
private final Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_STATE_CHANGE:
if(D) Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1);
switch (msg.arg1) {
case BluetoothGameService.STATE_CONNECTED:
mTitle.setText(R.string.title_connected_to);
mTitle.append(mConnectedDeviceName);
//mConversationArrayAdapter.clear();
break;
case BluetoothGameService.STATE_CONNECTING:
mTitle.setText(R.string.title_connecting);
break;
case BluetoothGameService.STATE_LISTEN:
case BluetoothGameService.STATE_NONE:
mTitle.setText(R.string.title_not_connected);
break;
}
break;
case MESSAGE_WRITE:
byte[] writeBuf = (byte[]) msg.obj;
// construct a string from the buffer
String writeMessage = new String(writeBuf);
//mConversationArrayAdapter.add("Me: " + writeMessage);
break;
case MESSAGE_READ:
byte[] readBuf = (byte[]) msg.obj;
// construct a string from the valid bytes in the buffer
String readMessage = new String(readBuf, 0, msg.arg1);
//mConversationArrayAdapter.add(mConnectedDeviceName+": " + readMessage);
break;
case MESSAGE_DEVICE_NAME:
// save the connected device's name
mConnectedDeviceName = msg.getData().getString(DEVICE_NAME);
Toast.makeText(getApplicationContext(), "Connected to "
+ mConnectedDeviceName, Toast.LENGTH_SHORT).show();
if(ben>0)
{
final Button st = (Button) findViewById(R.id.start); // enable start button
st.setEnabled(true);
}
else
{
final Button st = (Button) findViewById(R.id.start); // disable start button
st.setEnabled(false);
}
break;
case MESSAGE_TOAST:
Toast.makeText(getApplicationContext(), msg.getData().getString(TOAST),
Toast.LENGTH_SHORT).show();
break;
}
}
};
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if(D) Log.d(TAG, "onActivityResult " + resultCode);
switch (requestCode) {
case REQUEST_CONNECT_DEVICE:
// When DeviceListActivity returns with a device to connect
if (resultCode == Activity.RESULT_OK) {
// Get the device MAC address
String address = data.getExtras()
.getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
// Get the BLuetoothDevice object
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
// Attempt to connect to the device
mGameService.connect(device);
}
break;
case REQUEST_ENABLE_BT:
// When the request to enable Bluetooth returns
if (resultCode == Activity.RESULT_OK) {
// Bluetooth is now enabled, so set up a chat session
setupGame();
} else {
// User did not enable Bluetooth or an error occured
Log.d(TAG, "BT not enabled");
Toast.makeText(this, R.string.bt_not_enabled_leaving, Toast.LENGTH_SHORT).show();
finish();
}
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.activity_main, menu);
return true;
}
private void ensureDiscoverable() {
if(D) Log.d(TAG, "ensure discoverable");
if (mBluetoothAdapter.getScanMode() !=
BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(discoverableIntent);
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.scan:
ben = ben + 1;
// Launch the DeviceListActivity to see devices and do scan
Intent serverIntent = new Intent(this, DeviceListActivity.class);
startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
return true;
case R.id.discoverable:
// Ensure this device is discoverable by others
ensureDiscoverable();
return true;
}
return false;
}
//when start is pressed
public void start(View v){
//showDialog(NAME_DIALOG_ID);
player_name_2 = mConnectedDeviceName; //player 2 name
player_name_1 = "You"; //player 1 name
score_player_1 = 0;
score_player_2 = 0;
new_game(player_name_1); //calling fn
}
//when back | return button is pressed
public void back(View v){
player_name_1 = "Player 1";
player_name_2 = "Player 2";
count = 0;
player = 1;
score_player_1 = 0;
score_player_2 = 0;
Intent open = new Intent("com.example.tictactoechat_abs.STARTINGPOINT");
startActivity(open);
}
}
I would suggest when the connection is made, and before the game begins, that you transmit a message on the client saying 'the game is starting and I am going first'. You can presumably tell who tried to connect if one person presses 'join' and the other presses 'host'.
Alternatively you could randomise it by having both sides send a random number and whoever is the highest goes first.
You could create a player class that will represent a player. In there you could set a instance variable to the desired number, incrementing it by one each time. The player with the lowest number then could go first, followed by the rest of the players in order of that number. You can then have a class to manage all the player objects. That class will be responsible for checking for the next available number and assigning it to a player.

Timer not stopping after activity has been closed and restarted

I have a runnable timer that update a textview every second, when the activity is onStop (or called into the background) the timer continues to run. The issue i am having is that when i re-launch the activity it starts the same timer again, so the numbers are going up twice as fast as they should. I have it coded so that it will kill both timers before it restarts them but i believe that when the activity is started again the timers are not being killed. Here is an example of my code :
t.cancel();
cd.cancel();
t = new Timer();
t.schedule(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
public void run() {
That is only a small part but it should kill the timer (t.cancel();) then start a new one, this only happens when the activity is stopped and then restarted. please help this issue is driving me absolutely insane.
=========================================================
For the brave souls willing to read alot, here is my entire activity that i am having the issue with:
public class PayTracker extends Activity {
private static double Reserve;
private static int Reserve1;
public static double money;
public static double counter;
private static int go;
private static int countdown;
public static int convert;
public static double HW;
public static double OTW;
public static double HPD;
public static double DPPS;
public Timer t = new Timer();
public Timer cd = new Timer();
public static String mcountdown = "Time till overtime";
public static String mmoney = "total cash";
public static String mcounter = "ticks";
public static String mReserve = "building total";
public static String mReserve1 = "building total 2";
public static String mHW;
public static String mOTW;
public static String mHPD;
public static String mDPPS;
public static String mgo;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pay_tracker);
getActionBar().setDisplayHomeAsUpEnabled(true);
// Receive messages from options page
double pHW, pOTW, pHPD;
Intent intent = getIntent();
pHW = intent.getDoubleExtra(Options.MESSAGE_HW, 0);
pOTW = intent.getDoubleExtra(Options.MESSAGE_OTW, 0);
pHPD = intent.getDoubleExtra(Options.MESSAGE_HPD, 0);
if(pHW != 0){
HW = pHW;
OTW = pOTW;
HPD = pHPD;
}
// Color buttons
Button buttonc = (Button) findViewById(R.id.clockin);
buttonc.getBackground().setColorFilter(0xFF00FF00, PorterDuff.Mode.MULTIPLY);
Button buttond = (Button) findViewById(R.id.clockout);
buttond.getBackground().setColorFilter(0xFFFF0000, PorterDuff.Mode.MULTIPLY);
// go = 0;
// Calculate pay per second
final double PPS = (HW/3600);
DPPS = (PPS/50);
final double OTPPS = (OTW/3600);
final double DOTPPS = (OTPPS/50);
final double HPDPS = (HPD*3600);
final double DHPDPS = (HPDPS*50);
// Display
final TextView t1 = (TextView) findViewById(R.id.yourpay);
t1.setTextColor(Color.parseColor("#008000"));
final TextView t2 = (TextView) this.findViewById(R.id.payper);
final String result2 = String.format("%.8f", OTPPS);
final String result = String.format("%.8f", PPS);
// if(go != 1){
// go = 1;
// if(go == 1){
t.cancel();
cd.cancel();
// go = 0;
// }
// if(go == 0){
// go = 1;
t = new Timer();
t.schedule(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
public void run() {
if(DHPDPS==0){
money = (DPPS+Reserve);
Reserve = (money);
String end = String.format("%1f", money);
t1.setText("$" + end);
}else if(counter > DHPDPS && DOTPPS != 0 && DHPDPS != 0){
money = (DOTPPS+Reserve);
Reserve = (money);
String end = String.format("%1f", money);
t1.setText("$" + end);
} else{
money = (DPPS+Reserve);
Reserve = (money);
String end = String.format("%1f", money);
t1.setText("$" + end);
}
counter++;
//if(counter == 3000)
// t.cancel();
// Display pay per second
if(counter <= DHPDPS || DHPDPS == 0){
t2.setText("Your pay per second is: $"+result);
}else{
t2.setText("Your pay per second is: $"+result2);
}
}
});
}
}, 20, 20);
// Make countdown to overtime display
final Intent intent1 = new Intent(this, PayTracker.class);
// Create the notification
final Notification notification = new Notification(R.drawable.ic_launcher, "Click here to check your pay!", System.currentTimeMillis());
// Create an Intent for the notification to launch
// Create a PendingIntent for the associated Intent
final PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent1, 0);
cd = new Timer();
final TextView count = (TextView) findViewById(R.id.countdown);
convert = (int)HPDPS;
cd.schedule(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
public void run(){
countdown = (convert - Reserve1);
int hours = (countdown/3600);
if(OTPPS != 0 && HPDPS != 0){
count.setText("Seconds Remaining to Overtime: " + countdown + "\nAbout " + hours + " Hours");
Reserve1++;
}
// Set the notification's details
final String end = String.format("%.6f", money);
notification.setLatestEventInfo(getApplicationContext(), "Your Current Pay:", "$"+end, pendingIntent);
// Submit the notification to the system
((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).notify(0, notification);
}
});
}
}, 1000, 1000);
// }
// }
final Button b = (Button) findViewById(R.id.clockout);
b.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if(go == 1)
go = 0;
if (t != null){
t.cancel();
cd.cancel();
}
}
});
}
public void onRestoreInstanceState(Bundle savedInstanceState) {
// Always call the superclass so it can restore the view hierarchy
super.onRestoreInstanceState(savedInstanceState);
// Restore value of members from saved state
countdown = savedInstanceState.getInt(mcountdown);
Reserve = savedInstanceState.getInt(mReserve);
money = savedInstanceState.getInt(mmoney);
counter = savedInstanceState.getInt(mcounter);
Reserve1 = savedInstanceState.getInt(mReserve1);
HW = savedInstanceState.getInt(mHW);
OTW = savedInstanceState.getInt(mOTW);
HPD = savedInstanceState.getInt(mHPD);
DPPS = savedInstanceState.getInt(mDPPS);
go = savedInstanceState.getInt(mgo);
}
#Override
public void onStart(){
super.onStart();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_pay_tracker, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
NavUtils.navigateUpFromSameTask(this);
return true;
}
return super.onOptionsItemSelected(item);
}
public void sendMessage(View view) {
// Calculate pay per second
final double PPS = (HW/3600);
DPPS = (PPS/50);
final double OTPPS = (OTW/3600);
final double DOTPPS = (OTPPS/50);
final double HPDPS = (HPD*3600);
final double DHPDPS = (HPDPS*50);
// Display
final TextView t1 = (TextView) findViewById(R.id.yourpay);
t1.setTextColor(Color.parseColor("#008000"));
final TextView t2 = (TextView) this.findViewById(R.id.payper);
final String result2 = String.format("%.8f", OTPPS);
final String result = String.format("%.8f", PPS);
//if(go != 1){
// go = 1;
t.cancel();
cd.cancel();
t = new Timer();
t.schedule(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
public void run() {
if(DHPDPS==0){
money = (DPPS+Reserve);
Reserve = (money);
String end = String.format("%1f", money);
t1.setText("$" + end);
}else if(counter > DHPDPS && DOTPPS != 0 && DHPDPS != 0){
money = (DOTPPS+Reserve);
Reserve = (money);
String end = String.format("%1f", money);
t1.setText("$" + end);
} else{
money = (DPPS+Reserve);
Reserve = (money);
String end = String.format("%1f", money);
t1.setText("$" + end);
}
counter++;
if(counter == 3000)
t.cancel();
// Display pay per second
if(counter <= DHPDPS || DHPDPS == 0){
t2.setText("Your pay per second is: $"+result);
}else{
t2.setText("Your pay per second is: $"+result2);
}
}
});
}
}, 20, 20);
// Make countdown to overtime display
final Intent intent1 = new Intent(this, PayTracker.class);
// Create the notification
final Notification notification = new Notification(R.drawable.ic_launcher, "Click here to check your pay!", System.currentTimeMillis());
// Create an Intent for the notification to launch
// Create a PendingIntent for the associated Intent
final PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent1, 0);
cd = new Timer();
final TextView count = (TextView) findViewById(R.id.countdown);
convert = (int)HPDPS;
cd.schedule(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
public void run(){
countdown = (convert - Reserve1);
int hours = (countdown/3600);
if(OTPPS != 0 && HPDPS != 0){
count.setText("Seconds Remaining to Overtime: " + countdown + "\nAbout " + hours + " Hours");
Reserve1++;
}
// Set the notification's details
final String end = String.format("%.6f", money);
notification.setLatestEventInfo(getApplicationContext(), "Your Current Pay:", "$"+end, pendingIntent);
// Submit the notification to the system
((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).notify(0, notification);
}
});
}
}, 1000, 1000);
//}
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save the user's current game state
savedInstanceState.putInt(mcountdown, countdown);
savedInstanceState.putDouble(mReserve, Reserve);
savedInstanceState.putDouble(mmoney, money);
savedInstanceState.putDouble(mcounter, counter);
savedInstanceState.putDouble(mReserve1, Reserve1);
savedInstanceState.putDouble(mHW, HW);
savedInstanceState.putDouble(mOTW, OTW);
savedInstanceState.putDouble(mHPD, HPD);
savedInstanceState.putDouble(mDPPS, DPPS);
savedInstanceState.putInt(mgo, go);
// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}
#Override
public void onDestroy() {
super.onDestroy();
if(t != null)
t.cancel();
if(cd != null)
cd.cancel();
}
}
This is one way to get around that.
static Timer mTimer = null;
onCreate() {
if (mTimer == null)
mTimer = new Timer();
} else {
// You shouldn't have to do nothing because your timer should be running
}
}
Note that there are several issues in general here. The static is basically saying just to create one instance of that object. As a side effect it also tries to reclaim the same memory address. Either way, once your app is in the background it can be cleaned up by the system at any time so your not guaranteed to get your Timer back. There are a bunch of other ways to get around that, but that is out of scope for this question.

Categories