0

In my app I have a time in milliseconds (between 0 and 60000) divided by a certain value (In the current example it's 60000) Then, I times that by 100.

However, when printing the answer into the log, it always returns 0.

This is my code:

countDownTimer = new CountDownTimer(activityDuration, 1000) {
        @Override
        public void onTick(long timeLeftInMillis) {
            int minutes = (int) (timeLeftInMillis / 1000) / 60;
            int seconds = (int) (timeLeftInMillis / 1000) % 60;

            String timeLeftFormatted = String.format(Locale.getDefault(), "%02d:%02d", minutes, seconds);
            countDownTimerTextView.setText(timeLeftFormatted);

            System.out.println("L: " + timeLeftInMillis); // Returns correctly. Values between 0 and 60000
            System.out.println("Activity Duration: " + activityDuration); // Returns correctly. 60000
            System.out.println("Progress: " + (timeLeftInMillis / activityDuration) * 100); // Returns 0
        }

        @Override
        public void onFinish() {

        }
    }.start();
Luke C
  • 140
  • 2
  • 12

2 Answers2

1

The answer by user3818491 gives you a correct solution. I should like to contribute the modern version. Don’t use primitive numbers for durations, use the Duration class of java.time (the modern Java date and time API). This means, first declare activityDuration a Duration, for example:

    final Duration activityDuration = Duration.ofMinutes(1);

IMHO this is already much clearer to read as 1 minute than your value of 60000.

    Duration timeLeft = Duration.ofMillis(timeLeftInMillis);
    int minutes = (int) timeLeft.toMinutes();
    int seconds = timeLeft.toSecondsPart();

    String timeLeftFormatted = String.format(Locale.getDefault(), "%02d:%02d", minutes, seconds);
    countDownTimerTextView.setText(timeLeftFormatted);

    System.out.println("L: " + timeLeftInMillis); // Returns correctly. Values between 0 and 60000
    System.out.println("Activity Duration: " + activityDuration); // Returns correctly. 60000
    System.out.println("Progress: " + timeLeft.multipliedBy(100).dividedBy(activityDuration));

A possible output is:

L: 25555
Activity Duration: PT1M
Progress: 42

In this case 00:25 was filled into your text view. PT1M comes from Duration.toString and means 1 minute (it‘s ISO 8601 format, it goes like this, you will learn to read it easily if you need to).

The Duration.dividedBy(Duration) method was introduced in Java 9. For earlier Java versions and Android instead use:

    System.out.println(
            "Progress: " + timeLeft.multipliedBy(100).toMillis() / activityDuration.toMillis());

The result is the same.

Question: Can I use java.time on Android?

Yes, java.time works nicely on older and newer Android (only not the modest Java 9 additions). It just requires at least Java 6.

  • In Java 8 and later and on new Android devices (API level 26 and above, I am told) the modern API comes built-in.
  • In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310; see the links at the bottom).
  • On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages, for example import org.threeten.bp.Duration;.

Links

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
0

timeLeftInMillis / activityDuration is integer division and is always truncated to the nearest integer.

You need to cast to a float or double before doing the divsion i.e. ((double)timeLeftInMillis / activityDuration) * 100)

user3818491
  • 498
  • 1
  • 6
  • 16