0

Working on an Android app where each activity has its own timer. Originally I had code like this in every class

public void tTimer() {
    mTextField = (TextView) findViewById(R.id.countDown_timer);

    final CountDownTimer tCounter = new CountDownTimer(7000, 1000) {

        @Override
        public void onTick(long millisUntilFinished) {
            mTextField
                    .setText("Time Remaining: "
                            + String.format(
                                    "%d min,  %d sec",
                                    TimeUnit.MILLISECONDS
                                            .toMinutes(millisUntilFinished),
                                    TimeUnit.MILLISECONDS
                                            .toSeconds(millisUntilFinished)
                                            - TimeUnit.MINUTES
                                                    .toSeconds(TimeUnit.MILLISECONDS
                                                            .toMinutes(millisUntilFinished))));

        }

        @Override
        public void onFinish() {
            mTextField.setText("Done!");
            Intent i = new Intent (ColdActivity.this, PopUpActivity.class);
            startActivity(i);
        }
    };

    Button startButton = (Button) findViewById(R.id.timer_button_start);
    /* When the Start Button is touched, the Countdown Timer will start */

    startButton.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {

            AlertDialog.Builder builder = new AlertDialog.Builder(
                    ColdActivity.this);

            builder.setNegativeButton("Dismiss",
                    new DialogInterface.OnClickListener() {

                        @Override
                        public void onClick(DialogInterface arg0, int arg1) {
                            tCounter.start();
                            // Once the user has been notified that they should increase
                            // their alarm volume, and they dismiss the notification, the timer
                            // will start
                        }
                    });

            builder.setTitle("Notification");
            builder.setMessage("It is recommended that you turn your Alarm/Ringtone volume on so that you can hear the alarm when it is finished");

            AlertDialog dlg = builder.create();

            dlg.show();
        }
    });

    Button stopButton = (Button) findViewById(R.id.timer_button_cancel);
    /* When the Stop Button is touched, the Countdown Timer will stop */
    stopButton.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            tCounter.cancel();
        }
    });
}

I am now trying to create a new class that has a method called tTimer() like in the above code, so that I can instantiate a new object of that class, and then call the method in onCreate(), that way I don't have to rewrite timer code in every class, like I had previously done.

I tried to parameterize the method like this:

CustomTimerActivity cGT = new CustomTimerActivity();
cGT.tTimer(7000, ColdActivity.this, R.id.countDown_timer, R.id.timer_button_start, R.id.timer_button_cancel);

And what I keep getting is a NullPointerException, which points to my class called CustomTimerActivity

Why am I not able to pass the resource Id's as parameters? Or is the NPE coming from something else?

enter image description here

Here is the CustomTimerActivity I made:

public class CustomTimerActivity extends Activity {

    TextView mTextField;
    int mId;

    public void tTimer(long millisecs, final Activity activity1, int tv, int start, int cancel) {

        mTextField = (TextView) findViewById(tv);

        final CountDownTimer tCounter = new CountDownTimer(millisecs, 1000) {

            @Override
            public void onTick(long millisUntilFinished) {
                mTextField
                        .setText("Time Remaining: "
                                + String.format(
                                "%d min,  %d sec",
                                TimeUnit.MILLISECONDS
                                        .toMinutes(millisUntilFinished),
                                TimeUnit.MILLISECONDS
                                        .toSeconds(millisUntilFinished)
                                        - TimeUnit.MINUTES
                                        .toSeconds(TimeUnit.MILLISECONDS
                                                .toMinutes(millisUntilFinished))));
            }

            @Override
            public void onFinish() {
                mTextField.setText("Done!");
                Intent i = new Intent (activity1, PopUpActivity.class);
                startActivity(i);
            }
        };

        Button startButton = (Button) findViewById(start);
        /* When the Start Button is touched, the Countdown Timer will start */

        startButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {

                AlertDialog.Builder builder = new AlertDialog.Builder(
                        activity1);

                builder.setNegativeButton("Dismiss",
                        new DialogInterface.OnClickListener() {

                            @Override
                            public void onClick(DialogInterface arg0, int arg1) {
                                tCounter.start();
                                // Once the user has been notified that they should increase
                                // their alarm volume, and they dismiss the notification, the timer
                                // will start
                            }
                        });

                builder.setTitle("Notification");
                builder.setMessage("It is recommended that you turn your Alarm/Ringtone volume on so that you can hear the alarm when your tea is finished");

                AlertDialog dlg = builder.create();

                dlg.show();
            }
        });

        Button stopButton = (Button) findViewById(cancel);
        /* When the Stop Button is touched, the Countdown Timer will stop */
        stopButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                tCounter.cancel();
            }
        });
    }
}

The issue must be something to do with findViewById() and the Id that is used as input, right?

Here is another NullPointerException I get when the Intent is called.

Logcat2

freddiev4
  • 2,501
  • 2
  • 26
  • 46

1 Answers1

1

The Activity has not been initialized in the constructor. Only collect the parameters in the constructor and do the initialization in the onCreate(Bundle) method!

However, if you want to call it from a givin activity, you have to call .findViewById on that class, not on your own class

engineercoding
  • 832
  • 6
  • 14
  • OK. I see now. I changed it so that it says `activity1.findViewById()` and then I pass in the name of the activity in the method call. So, it works. Thank you! – freddiev4 Mar 06 '15 at 17:25
  • Oops. Jumped ahead too early. Sorry. I also have an intent `Intent i = new Intent (activity1, PopUpActivity.class);` that causes a PopUp/Alert to occur on the user's phone. It will make a sound and show a notification. However, I have another NullPointerException when this Intent occurs. Why? – freddiev4 Mar 06 '15 at 18:20
  • @Freddie_V4 Please provide another logcat – engineercoding Mar 06 '15 at 18:39
  • @Freddie_V4 Make the countdown class not an Activity, because you don't really use it as an Activity. You are calling startActivity from Countdown, but because it hasn't been initialized again, it wont work. You have to start the activity from the parameter like the previous fix. To avoid those issues, please make CountDown not an instance of Activity – engineercoding Mar 06 '15 at 19:00
  • OK. I removed `extends Activity`. This solution works. Thank you. – freddiev4 Mar 06 '15 at 19:39