-1

I'm trying to us SharedPreferences to set a flag to enable a "Dev mode" within my app. I created a boolean and set it to false, and when the proper command is entered, the app will set it to true.

However, every time I try to read this new SharedPreference, I get a null pointer exception, even through my logging shows that it is returning false, as expected.

My splashScreen activity acts as my main:

public class splashScreen extends AppCompatActivity {

    public static String jsonURL="https://www.tourofhonor.com/BonusData.json";
    public static String jsonDevURL="https://www.tommyc.net/BonusData.json";

    SharedPreferences sharedpreferences;
    public static final String tohPreferences = "Tour of Honor Preferences";
    public static final String riderNum = "RiderNumber";
    public static final String pillionNum = "PillionNumber";
    public static final String devModeStatus = "DevModeStatus";

    public static String riderNumToH;
    public static String pillionNumToH;
    public static boolean devModeOn = false;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.e("splashScreen","Creating Splash Screen");
        setContentView(R.layout.activity_splash_screen);

        sharedpreferences = getSharedPreferences(tohPreferences,
                Context.MODE_PRIVATE);
        if (sharedpreferences.contains(riderNum)) {
            Log.e("splashScreen","riderNum set to " + riderNum);
            riderNumToH = sharedpreferences.getString(riderNum,"000");
        } else {
            Log.e("splashScreen","riderNum Failed");
        }
        if (sharedpreferences.contains(pillionNum)) {
            Log.e("splashScreen","pillionNum set to " + pillionNum);
            pillionNumToH = sharedpreferences.getString(pillionNum,"000");
        } else {
            Log.e("splashScreen","pillionNum Failed");
        }
        if (sharedpreferences.contains(devModeStatus)) {
            Log.e("splashScreen","Dev Mode set to " + devModeStatus + devModeOn);
            devModeOn = sharedpreferences.getBoolean(devModeStatus,false);
        } else {
            Log.e("splashScreen","devModeStatus Failed " +devModeStatus + devModeOn);
        }
    }

    public void goToBonusDetail (View View) {
        Log.e("splashScreen","Gong to Bonus Detail");
        Intent goToBonusDetail = new Intent(this, captureBonus.class);
        startActivity(goToBonusDetail);
    }

    public void goToBonusList (View View) {
        Log.e("splashScreen","Going to Bonus List");
        Intent goToBonusList = new Intent(this,bonusListing.class);
        startActivity(goToBonusList);
    }
}

The splashScreen page loads, however my logging shows that it took my else statement for the boolean (it take the true side for the two other calls to SharedPreferences).

Logcat Output for the three SharedPreferences calls:

E/splashScreen: riderNum set to RiderNumber
E/splashScreen: pillionNum set to PillionNumber
E/splashScreen: devModeStatus Failed DevModeStatusfalse

But when I go to my bonusListing page, I instantly get the NPE, which is pointing at line 35:

devModeOn = sharedpreferences.getBoolean(devModeStatus,false); 

Here is the bonusListing class:

public class bonusListing extends AppCompatActivity {

    SharedPreferences sharedpreferences;
    ArrayList<jsonBonuses> dataModels;
    ListView listView;
    private static jsonToListViewAdapter adapter;

    ListView lv;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bonus_listing);
        Toolbar myToolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(myToolbar);
        devModeOn = sharedpreferences.getBoolean(devModeStatus,false);

        if (!devModeOn) {
            jsonURL = "https://www.tourofhonor.com/BonusData.json";
        } else if (devModeOn) {
            jsonURL = "https://www.tommyc.net/BonusData.json";
        } else {
            Log.e("bonusListing", "Invalid Dev Mode Setting");
            return;
        }

        listView = (ListView) findViewById(R.id.lvBonusData);
        new jsonDownloader(bonusListing.this,jsonURL, lv).execute();

        // Populate the DataModel with some false data for testing purposes
        dataModels= new ArrayList<>();

        // dataModels.add(new jsonBonuses("BC1", "category1", "name1",1,"address1","city1","state1","GPS1","access1","flavor1","madeInAmerica1","imageName"));
        // dataModels.add(new jsonBonuses("BC2", "category2", "name2",2,"address2","city2","state2","GPS2","access2","flavor2","madeInAmerica2","imageName"));

        adapter= new jsonToListViewAdapter(dataModels,getApplicationContext());
        if(adapter != null) {
            Log.e("onCreate","entered adapter code");
            listView.setAdapter(adapter);
        } else {
            Log.e("onCreate","adapter has no data");
        }

        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                jsonBonuses dataModel= dataModels.get(position);

                Log.e("onClick for Data Row","Tapped on row");
            }
            });
    }
  ... // Omitted code that isn't related to the above for brevity.
}

EDIT: Here is the stack trace:

java.lang.RuntimeException: Unable to start activity ComponentInfo{net.tommyc.android.tourofhonor/net.tommyc.android.tourofhonor.bonusListing}: java.lang.NullPointerException: Attempt to invoke interface method 'boolean android.content.SharedPreferences.getBoolean(java.lang.String, boolean)' on a null object reference
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3194)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3302)
        at android.app.ActivityThread.-wrap12(Unknown Source:0)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1891)
        at android.os.Handler.dispatchMessage(Handler.java:108)
        at android.os.Looper.loop(Looper.java:166)
        at android.app.ActivityThread.main(ActivityThread.java:7425)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)
     Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'boolean android.content.SharedPreferences.getBoolean(java.lang.String, boolean)' on a null object reference
        at net.tommyc.android.tourofhonor.bonusListing.onCreate(bonusListing.java:35)
        at android.app.Activity.performCreate(Activity.java:7372)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1218)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3147)

Why am I getting an NPE here? I set it to false at creation and I use false as the default in both calls, so I'm at a loss.

DJFriar
  • 340
  • 7
  • 21
  • Show the stack trace. In which line do you get the NPE? – Henry Jan 13 '19 at 11:59
  • @Henry I have added the stack trace to my question. The trace points to line 35 in the bonusListing code, which says `devModeOn = sharedpreferences.getBoolean(devModeStatus,false);` – DJFriar Jan 13 '19 at 12:03

1 Answers1

1

put this line after setConentViewMethod in bonusListing activity

 sharedpreferences = getSharedPreferences(tohPreferences,
                    Context.MODE_PRIVATE);

because you use sharedpreferences object without initalization

and this string

public static final String tohPreferences = "Tour of Honor Preferences";

at the start of your bonusListing activity

Ramzy Hassan
  • 926
  • 8
  • 21
  • Do I need the `public static final` line if I'm using `import static net.tommyc.android.tourofhonor.splashScreen.tohPreferences;` already? (It worked with the import statement, just curious if I'm doing something non-standard) – DJFriar Jan 13 '19 at 12:06
  • I think no, but it is preferred to put your shared preference operations in one class with its constants and handle the dealing with preference using and object from this class @DJFriar – Ramzy Hassan Jan 13 '19 at 12:09