-1

When I open this activity in my app (Template1Activity) the app crashes with the following message:

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.SharedPreferences android.content.Context.getSharedPreferences(java.lang.String, int)' on a null object reference

My code for Template1Activity is:

package com.idleappsinc.smartmirror;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;

/**
 * Created by Luke on 04/02/2018.
 */

public class Template1Activity extends AppCompatActivity {

    Preferences sharedPreferences;
    TimeModule timeModule = new TimeModule();

    TextView timeDisplayTextView;
    TextView timeLocationTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_template_1);
        sharedPreferences = new Preferences(this);

        timeDisplayTextView = findViewById(R.id.time_display_text_view);
        timeLocationTextView = findViewById(R.id.time_location_text_view);

        timeModule.startTimer(timeDisplayTextView);
        timeLocationTextView.setText(timeModule.getCurrentLocation());


        View decorView = getWindow().getDecorView();
        int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN;
        decorView.setSystemUiVisibility(uiOptions);

    }

}

My code for TimeModule is:

package com.idleappsinc.smartmirror;


import android.app.Activity;
import android.content.Context;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationManager;
import android.os.Handler;
import android.widget.TextView;

import java.io.IOException;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;

/**
 * Created by Luke on 05/02/2018.
 */

public class TimeModule extends Activity {

    Preferences sharedPreferences = new Preferences(this);
    List<Address> addressList;

    @SuppressWarnings({"MissingPermission"})
    public String getCurrentLocation() {
        String currentLocation = "";

        Geocoder geocoder = new Geocoder(this, Locale.getDefault());
        try {
            LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
            Location location = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
            addressList = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1);
            String area = addressList.get(0).getLocality();
            String country = addressList.get(0).getCountryCode();

            currentLocation = area + ", " + country;

        } catch (IOException e) {
            e.printStackTrace();
        }

        return currentLocation;
    }

    public void startTimer(final TextView timeDisplayTextView) {

        final Handler handler = new Handler();
        Runnable runnable = new Runnable() {

            @Override
            public void run() {
                try {

                    if (sharedPreferences.getBooleanValue(getResources().getString(R.string.preference_time_clock_hours))) {
                        // User wants 24 hour format

                        if (sharedPreferences.getBooleanValue(getResources().getString(R.string.preference_time_segment_seconds))) {
                            // User wants to see seconds
                            int secondsLength = String.valueOf(Calendar.getInstance().get(Calendar.SECOND)).length();
                            int minutesLength = String.valueOf(Calendar.getInstance().get(Calendar.MINUTE)).length();

                            if (secondsLength == 1) {
                                if (minutesLength == 1) {
                                    // Seconds = 0-9
                                    // Minutes = 0-9
                                    timeDisplayTextView.setText(Calendar.getInstance().get(Calendar.HOUR_OF_DAY) + ":0" + Calendar.getInstance().get(Calendar.MINUTE) + ":0" + Calendar.getInstance().get(Calendar.SECOND));
                                } else {
                                    // Seconds = 0-9
                                    timeDisplayTextView.setText(Calendar.getInstance().get(Calendar.HOUR_OF_DAY) + ":" + Calendar.getInstance().get(Calendar.MINUTE) + ":0" + Calendar.getInstance().get(Calendar.SECOND));
                                }
                            } else {
                                if (minutesLength == 1) {
                                    // Minutes = 0-9
                                    timeDisplayTextView.setText(Calendar.getInstance().get(Calendar.HOUR_OF_DAY) + ":0" + Calendar.getInstance().get(Calendar.MINUTE) + ":" + Calendar.getInstance().get(Calendar.SECOND));
                                } else {
                                    // Seconds = 0-9
                                    timeDisplayTextView.setText(Calendar.getInstance().get(Calendar.HOUR_OF_DAY) + ":" + Calendar.getInstance().get(Calendar.MINUTE) + ":" + Calendar.getInstance().get(Calendar.SECOND));
                                }
                                timeDisplayTextView.setText(Calendar.getInstance().get(Calendar.HOUR_OF_DAY) + ":" + Calendar.getInstance().get(Calendar.MINUTE) + ":" + Calendar.getInstance().get(Calendar.SECOND));
                            }

                        } else {
                            timeDisplayTextView.setText(Calendar.getInstance().get(Calendar.HOUR_OF_DAY) + ":" + Calendar.getInstance().get(Calendar.MINUTE));
                        }


                    } else {
                        // The user wants the 12 hours format

                        if (sharedPreferences.getBooleanValue(getResources().getString(R.string.preference_time_segment_seconds))) {
                            int secondsLength = String.valueOf(Calendar.getInstance().get(Calendar.SECOND)).length();
                            int minutesLength = String.valueOf(Calendar.getInstance().get(Calendar.MINUTE)).length();

                            if (secondsLength == 1) {
                                Calendar cal = Calendar.getInstance();
                                if (cal.get(Calendar.AM_PM) == Calendar.PM) {
                                    if (minutesLength == 1) {
                                        // Seconds = 0-9
                                        // Minutes = 0-9
                                        // PM
                                        timeDisplayTextView.setText(Calendar.getInstance().get(Calendar.HOUR) + ":0" + Calendar.getInstance().get(Calendar.MINUTE) + ":0" + Calendar.getInstance().get(Calendar.SECOND) + "pm");
                                    } else {
                                        // Seconds = 0-9
                                        // PM
                                        timeDisplayTextView.setText(Calendar.getInstance().get(Calendar.HOUR) + ":" + Calendar.getInstance().get(Calendar.MINUTE) + ":0" + Calendar.getInstance().get(Calendar.SECOND) + "pm");
                                    }
                                } else {
                                    if (minutesLength == 1) {
                                        // Seconds = 0-9
                                        // Minutes = 0-9
                                        // AM
                                        timeDisplayTextView.setText(Calendar.getInstance().get(Calendar.HOUR) + ":0" + Calendar.getInstance().get(Calendar.MINUTE) + ":0" + Calendar.getInstance().get(Calendar.SECOND) + "am");
                                    } else {
                                        // Seconds = 0-9
                                        // Minutes = 0-9
                                        // AM
                                        timeDisplayTextView.setText(Calendar.getInstance().get(Calendar.HOUR) + ":" + Calendar.getInstance().get(Calendar.MINUTE) + ":0" + Calendar.getInstance().get(Calendar.SECOND) + "am");
                                    }
                                }

                            } else {
                                Calendar cal = Calendar.getInstance();
                                if (cal.get(Calendar.AM_PM) == Calendar.PM) {
                                    if (minutesLength == 1) {
                                        // Minutes = 0-9
                                        // PM
                                        timeDisplayTextView.setText(Calendar.getInstance().get(Calendar.HOUR) + ":0" + Calendar.getInstance().get(Calendar.MINUTE) + ":" + Calendar.getInstance().get(Calendar.SECOND) + "pm");
                                    } else {
                                        // PM
                                        timeDisplayTextView.setText(Calendar.getInstance().get(Calendar.HOUR) + ":" + Calendar.getInstance().get(Calendar.MINUTE) + ":" + Calendar.getInstance().get(Calendar.SECOND) + "pm");
                                    }
                                } else {
                                    if (minutesLength == 1) {
                                        // Minutes = 0-9
                                        // AM
                                        timeDisplayTextView.setText(Calendar.getInstance().get(Calendar.HOUR) + ":0" + Calendar.getInstance().get(Calendar.MINUTE) + ":" + Calendar.getInstance().get(Calendar.SECOND) + "am");
                                    } else {
                                        // AM
                                        timeDisplayTextView.setText(Calendar.getInstance().get(Calendar.HOUR) + ":" + Calendar.getInstance().get(Calendar.MINUTE) + ":" + Calendar.getInstance().get(Calendar.SECOND) + "am");
                                    }
                                }
                            }
                        } else {
                            Calendar cal = Calendar.getInstance();
                            if (cal.get(Calendar.AM_PM) == Calendar.PM) {
                                timeDisplayTextView.setText(Calendar.getInstance().get(Calendar.HOUR) + ":" + Calendar.getInstance().get(Calendar.MINUTE) + "pm");
                            } else {
                                timeDisplayTextView.setText(Calendar.getInstance().get(Calendar.HOUR) + ":" + Calendar.getInstance().get(Calendar.MINUTE) + "am");
                            }
                        }

                    }

                } catch (Exception e) {
                    // TODO: handle exception
                } finally {
                    //also call the same runnable to call it at regular interval
                    if (sharedPreferences.getBooleanValue(getResources().getString(R.string.preference_time_segment_seconds))) {
                        handler.postDelayed(this, 1000);
                    } else {
                        handler.postDelayed(this, (60 - Calendar.getInstance().get(Calendar.SECOND)) * 1000);
                    }

                }
            }
        };
        handler.postDelayed(runnable, (1 - Calendar.getInstance().get(Calendar.MILLISECOND)) * 1000);

    }


}

The error is happening on the following line in the TimeModule class: Preferences sharedPreferences = new Preferences(this);

I believe it's something to do with the fact that a standard Java class doesn't have context until an onCreate() method is called, however I'm clueless as to what goes next. I've tried a few things but no luck.

The Java Class TimeModule is simply a Java Class, rather than a Class linked to a layout. The erason it extends Activity is so I can access certain methods such as getResources()

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Luke C
  • 140
  • 2
  • 12
  • what happens if you have 'this' to 'getApplicationContext();' – letsCode Feb 05 '18 at 20:14
  • Making TimeModule an Activity is not a good idea. Pass the Context of Template1Activity instead, e.g. via the Constructor. – Bö macht Blau Feb 05 '18 at 20:17
  • On the same line the current issue persists, this is the new error: Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.content.Context.getApplicationContext()' on a null object reference – Luke C Feb 05 '18 at 20:17
  • I assume you mean like this @0X0nosugar? Because if so, it still produces an error: > Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.SharedPreferences android.content.Context.getSharedPreferences(java.lang.String, int)' on a null object reference https://hastebin.com/oxavuhulas.cpp – Luke C Feb 05 '18 at 20:24
  • never create an instance of Activity. You should **never** do this. Only system can do it. – Vladyslav Matviienko Feb 05 '18 at 20:26
  • The other issue is that one can't make use of the Template1Activity as a kind of Context before it is fully initialised. So you have to initialise the TimeModule instance in onCreate() of Template1Activity or later – Bö macht Blau Feb 05 '18 at 20:27
  • @0X0nosugar Thanks! Along with this I also did what the accepted answer told me to. – Luke C Feb 05 '18 at 20:33

2 Answers2

1

Since you are creating the TimeModule object yourself in Template1Activity . Use a constructor to pass in the context of Template1Activity to it. Then you can initialise the the sharedPreference in the constructor.

TimeModule(Context context){
    sharedPreferences = new Preferences(this);
}
0

Using getResources() in non-activity class you can use the ideas given in the answers instead of inhering activity.
it's not good idea passing contexts it might cause memory leaks.

Amr
  • 1,068
  • 12
  • 21