I’m currently trying to debug my application, however, I’m running into some difficulties with a NullPointerException. I have a dialog box with 4 checkboxes, a save button, and a cancel button. When the user marks their choices in the dialog box then presses the save button it returns a NullPointerException and I don’t understand why. Below is the XML file in case it’s relevant to finding the solution:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/scrollviewPref"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fillViewport="true"
android:layout_marginTop="10dip">
<LinearLayout
android:layout_width="300dip"
android:layout_height="wrap_content"
android:orientation="vertical"
android:minWidth="200dip">
<CheckBox
android:id="@+id/altitudeCheckbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Altitude"
android:layout_gravity="left" />
<CheckBox
android:id="@+id/latitudeCheckbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Latitude"
android:layout_gravity="left" />
<CheckBox
android:id="@+id/longitudeCheckbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Longitude"
android:layout_gravity="left" />
<CheckBox
android:id="@+id/velocityCheckbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Velocity"
android:layout_gravity="left" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:layout_marginBottom="10dip"
android:layout_marginTop="10dip">
<Button
android:id="@+id/saveBtn"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Save"
android:layout_weight="1" />
<Button
android:id="@+id/cancelBtn"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Cancel"
android:layout_weight="1" />
</LinearLayout>
</LinearLayout>
</ScrollView>
The set set of code is the code that saves the user’s choices to a SharedPreferences.
package shc_BalloonSat.namespace;
import android.app.Dialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.util.Log;
import android.view.View;
import android.widget.CheckBox;
public class CheckPreferences extends Dialog
{
Context shc;
private CheckBox altitudeCheckBox = null;
private CheckBox latitudeCheckbox = null;
private CheckBox longitudeCheckbox = null;
private CheckBox velocityCheckbox = null;
private CheckPreferencesListener listener;
SharedPreferences pref;
Editor prefEditor;
String userAltitudePreference = "";
String userLatitudePreference = "";
String userLongitudePreference = "";
String userVelocityPreference = "";
String userAltitudeChoice = "";
String userLatitudeChoice = "";
String userLongitudeChoice = "";
String userVelocityChoice = "";
public interface CheckPreferencesListener
{
public void onSettingsSaved();
public void onCancel();
}
public CheckPreferences(Context context, CheckPreferencesListener l)
{
super(context);
shc = context;
this.listener = l;
this.setContentView(R.layout.custompreferences);
altitudeCheckBox = (CheckBox) findViewById(R.id.altitudeCheckbox);
latitudeCheckbox = (CheckBox) findViewById(R.id.latitudeCheckbox);
longitudeCheckbox = (CheckBox) findViewById(R.id.longitudeCheckbox);
velocityCheckbox = (CheckBox) findViewById(R.id.velocityCheckbox);
this.setCancelable(false);
this.setCanceledOnTouchOutside(false);
this.setTitle("Data View Settings");
pref = shc.getSharedPreferences("shared_prefs", 1);
prefEditor = pref.edit();
initOnClick();
}
private void initOnClick()
{
View.OnClickListener click = new View.OnClickListener()
{
public void onClick(View v)
{
switch (v.getId())
{
case R.id.saveBtn:
{
saveSettings();
listener.onSettingsSaved();
dismiss();
break;
}
case R.id.cancelBtn:
{
listener.onCancel();
dismiss();
break;
}
}
}
};
// Save Button
this.findViewById(R.id.saveBtn).setOnClickListener(click);
// Cancel Button
this.findViewById(R.id.cancelBtn).setOnClickListener(click);
}
// This function is called when the user chooses the save their preferences
public void saveSettings()
{
try
{
if (altitudeCheckBox.isChecked())
{
userAltitudeChoice = "true";
prefEditor.putString(userAltitudePreference, userAltitudeChoice);
prefEditor.commit();
}
else if (latitudeCheckbox.isChecked())
{
userLatitudeChoice = "true";
prefEditor.putString(userLatitudePreference, userLatitudeChoice);
prefEditor.commit();
}
else if (longitudeCheckbox.isChecked())
{
userLongitudeChoice = "true";
prefEditor.putString(userLongitudePreference, userLongitudeChoice);
prefEditor.commit();
}
else if (velocityCheckbox.isChecked())
{
userVelocityChoice = "true";
prefEditor.putString(userVelocityPreference, userVelocityChoice);
prefEditor.commit();
}
else
{
}
}
catch (NullPointerException npe)
{
if (npe.getMessage() != null)
{
Log.e("<tag>", npe.getMessage());
}
else
{
Log.e("<tag>", "Save Settings e.getMessage() was null");
}
}
}
}
The NullPointerException happens in the savedSettings function. All that function does is put data in the SharedPreferences. Any idea why that wold cause something to be null? Thanks in advance for any help given.
Update: Below is the error log.
05-09 17:25:28.835: E/<tag>(5447): Save Settings e.getMessage() was null
05-09 17:25:28.866: E/AndroidRuntime(5447): FATAL EXCEPTION: main
05-09 17:25:28.866: E/AndroidRuntime(5447): java.lang.NullPointerException
05-09 17:25:28.866: E/AndroidRuntime(5447): at shc_BalloonSat.namespace.CheckPreferences$1.onClick(CheckPreferences.java:59)
05-09 17:25:28.866: E/AndroidRuntime(5447): at android.view.View.performClick(View.java:2408)
05-09 17:25:28.866: E/AndroidRuntime(5447): at android.view.View$PerformClick.run(View.java:8816)
05-09 17:25:28.866: E/AndroidRuntime(5447): at android.os.Handler.handleCallback(Handler.java:587)
05-09 17:25:28.866: E/AndroidRuntime(5447): at android.os.Handler.dispatchMessage(Handler.java:92)
05-09 17:25:28.866: E/AndroidRuntime(5447): at android.os.Looper.loop(Looper.java:123)
05-09 17:25:28.866: E/AndroidRuntime(5447): at android.app.ActivityThread.main(ActivityThread.java:4627)
05-09 17:25:28.866: E/AndroidRuntime(5447): at java.lang.reflect.Method.invokeNative(Native Method)
05-09 17:25:28.866: E/AndroidRuntime(5447): at java.lang.reflect.Method.invoke(Method.java:521)
05-09 17:25:28.866: E/AndroidRuntime(5447): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
05-09 17:25:28.866: E/AndroidRuntime(5447): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
05-09 17:25:28.866: E/AndroidRuntime(5447): at dalvik.system.NativeStart.main(Native Method)
Below is my main class where the listener is instantiated.
package shc_BalloonSat.namespace;
import java.text.DecimalFormat;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.net.ConnectivityManager;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.SubMenu;
import android.widget.TextView;
import android.widget.Toast;
public class Shc_BalloonSat_Activity extends Activity
{
int historyCountFromUser;
httpAPI api;
mapAPI map;
runDialog dialog;
CheckPreferences check;
DecimalFormat df = new DecimalFormat("##.#####");
DecimalFormat decimalf = new DecimalFormat("##.######");
AlertDialog alert;
SharedPreferences pref;
Editor prefEditor;
String lastpacketsPHP;
TextView historyTV;
TextView infoTV;
// User to determine how many packet the user would like to see.
int userDefinedCount = 5;
/*
* Called when the activity is first created.
*/
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
loadApp();
}
public boolean isNetworkConnected(Context context)
{
ConnectivityManager connectionManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectionManager.getActiveNetworkInfo() != null && connectionManager.getActiveNetworkInfo().isAvailable() && connectionManager.getActiveNetworkInfo().isConnected())
{
return true;
}
else
{
return false;
}
}
public void showAlert()
{
alert.setTitle("Sorry!");
alert.setMessage("Please connect to the internet to access the full functionality of this app.");
alert.setButton("OK", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int which)
{
}
});
alert.show();
}
public void loadApp()
{
setContentView(shc_BalloonSat.namespace.R.layout.main);
alert = new AlertDialog.Builder(this).create();
lastpacketsPHP = "";
pref = getSharedPreferences("shared_prefs", 1);
prefEditor = pref.edit();
//prefEditor.putString(lastpacketsPHP, "\* PHP file location goes here. */");
//prefEditor.commit();
// These next two lines are used to test the PHP files on the SHC server by determining if PHP is set up correctly.
prefEditor.putString(lastpacketsPHP, "\* PHP file location goes here. */");
prefEditor.commit();
if (!isNetworkConnected(this))
{
showAlert();
}
else
{
api = new httpAPI(this);
map = new mapAPI(this);
dialog = new runDialog(this, api, new runDialog.OnDataLoadedListener()
{
public void dataLoaded(String textViewString)
{
infoTV = (TextView)findViewById(shc_BalloonSat.namespace.R.id.info);
infoTV.setText(textViewString);
}
});
dialog.execute();
}
CheckPreferences cp = new CheckPreferences(this, new CheckPreferences.CheckPreferencesListener()
{
public void onSettingsSaved()
{
// This function let's the activity know that the user has saved their preferences and
// that the rest of the app should be now be shown.
check.saveSettings();
assignInfoToInfoTextView();
assignInfoToHistoryTextView();
}
public void onCancel()
{
Toast.makeText(getApplicationContext(), "Settings dialog cancelled", Toast.LENGTH_LONG).show();
}
});
cp.show();
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
MenuInflater inflater = getMenuInflater();
inflater.inflate(shc_BalloonSat.namespace.R.menu.mainmenu, menu);
SubMenu submenu = menu.addSubMenu(0, Menu.FIRST, Menu.NONE, "Preferences");
submenu.add(0, 5, Menu.NONE, "Get Last 5 Packets");
submenu.add(0, 10, Menu.NONE, "Get Last 10 Packets");
submenu.add(0, 20, Menu.NONE, "Get Last 20 Packets");
inflater.inflate(shc_BalloonSat.namespace.R.menu.mainmenu, submenu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
// Handle item selection
switch (item.getItemId())
{
case shc_BalloonSat.namespace.R.id.viewKML:
viewKML();
return true;
case 5:
viewLast5Packets();
return true;
case 10:
viewLast10Packets();
return true;
case 20:
viewLast20Packets();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public void assignInfoToInfoTextView()
{
try
{
String result = api.result.substring(1, api.result.length()-2);
JSONObject json_data = new JSONObject(result);
String infoText = "";
if (check.userAltitudePreference.equals("true"))
{
double altitudeData = json_data.getDouble("altitude");
double altitudeInFeet = altitudeData * 3.281;
infoText = "Last Known Altitude: " + df.format(altitudeInFeet) + " ft\n";
}
else if (check.userVelocityPreference.equals("true"))
{
Double speedData = json_data.optDouble("speed");
if (speedData.isNaN())
{
speedData = 0.00;
}
Double direction = json_data.optDouble("heading");
String directionUnits = " degrees from N";
String directionText = "";
if (direction == 0)
{
directionText = ", N";
}
else if (direction > 0 && direction < 45)
{
directionText = ", N NE";
}
else if (direction == 45)
{
directionText = ", NE";
}
else if (direction > 45 && direction < 90)
{
directionText = ", E NE";
}
else if (direction == 90)
{
directionText = ", E";
}
else if (direction > 90 && direction < 135)
{
directionText = ", E SE";
}
else if (direction == 135)
{
directionText = ", SE";
}
else if (direction > 135 && direction < 180)
{
directionText = ", S SE";
}
else if (direction == 180)
{
directionText = ", S";
}
else if (direction > 180 && direction < 225)
{
directionText = ", S SW";
}
else if (direction == 225)
{
directionText = ", SW";
}
else if (direction > 225 && direction < 270)
{
directionText = ", W SW";
}
else if (direction == 270)
{
directionText = ", W";
}
else if (direction > 270 && direction < 315)
{
directionText = ", W NW";
}
else if (direction == 315)
{
directionText = ", NW";
}
else if (direction > 315 && direction < 360)
{
directionText = ", N NW";
}
else if (direction.isNaN())
{
directionText = " Invalid direction";
}
else
{
}
infoText += "Last Known Velocity: " + df.format(speedData) + " m/s " + direction + directionUnits + directionText + "\n";
}
else if (check.userLatitudePreference.equals("true"))
{
double recentLatitudeData = json_data.getDouble("latitude");
infoText += "Last Known Latitude: " + df.format(recentLatitudeData) + "\n";
}
else if (check.userLongitudePreference.equals("true"))
{
double recentLongitudeData = json_data.getDouble("longitude");
infoText += "Last Known Longtitude: " + df.format(recentLongitudeData) + "\n";
}
infoTV.setText(infoText);
}
catch (JSONException e)
{
if (e.getMessage() != null)
{
Log.e("<tag>", e.getMessage());
}
else
{
Log.e("<tag>", "Last Known Textview 1 e.getMessage() was null");
}
Toast.makeText(this,"JSON Error in (Last Known) method!",Toast.LENGTH_SHORT).show();
}
catch (Exception e)
{
//broke here, not getting a message for some reason
if (e.getMessage() != null)
{
Log.e("<tag>", e.getMessage());
}
else
{
Log.e("<tag>", "Last Known Textview 2 e.getMessage() was null");
}
Toast.makeText(this,"Error in (Last Known) method!",Toast.LENGTH_SHORT).show();
}
}
public void assignInfoToHistoryTextView()
{
try
{
JSONArray jArray = new JSONArray(api.result);
historyTV = (TextView)findViewById(shc_BalloonSat.namespace.R.id.history);
for (int count = 1; count < userDefinedCount; count++)
{
JSONObject json_data = jArray.getJSONObject(count);
double altitudeData = json_data.getDouble("altitude");
double altitudeInFeet = altitudeData * 3.281;
String historyText = "Altitude: " + decimalf.format(altitudeInFeet) + " ft\n";
Double speedData = json_data.optDouble("speed");
if (speedData.isNaN())
{
speedData = 0.00;
}
Double direction = json_data.optDouble("heading");
String directionUnits = " degrees from N";
String directionText = "";
if (direction == 0)
{
directionText = ", N";
}
else if (direction > 0 && direction < 45)
{
directionText = ", N NE";
}
else if (direction == 45)
{
directionText = ", NE";
}
else if (direction > 45 && direction < 90)
{
directionText = ", E NE";
}
else if (direction == 90)
{
directionText = ", E";
}
else if (direction > 90 && direction < 135)
{
directionText = ", E SE";
}
else if (direction == 135)
{
directionText = ", SE";
}
else if (direction > 135 && direction < 180)
{
directionText = ", S SE";
}
else if (direction == 180)
{
directionText = ", S";
}
else if (direction > 180 && direction < 225)
{
directionText = ", S SW";
}
else if (direction == 225)
{
directionText = ", SW";
}
else if (direction > 225 && direction < 270)
{
directionText = ", W SW";
}
else if (direction == 270)
{
directionText = ", W";
}
else if (direction > 270 && direction < 315)
{
directionText = ", W NW";
}
else if (direction == 315)
{
directionText = ", NW";
}
else if (direction > 315 && direction < 360)
{
directionText = ", N NW";
}
else if (direction.isNaN())
{
directionText = " Invalid direction";
}
else
{
}
if (direction.isNaN())
{
historyText += "Velocity: " + df.format(speedData) + " m/s " + directionText + "\n";
}
else
{
historyText += "Velocity: " + df.format(speedData) + " m/s,\n" + direction + directionUnits + directionText + "\n";
}
double latitudeData = json_data.getDouble("latitude");
historyText += "Latitude: " + df.format(latitudeData) + "\n";
double longitudeData = json_data.getDouble("longitude");
historyText += "Longtitude: " + df.format(longitudeData) + "\n\n";
historyTV.setText(historyTV.getText().toString() + historyText);
}
}
catch (JSONException e)
{
if (e.getMessage() != null)
{
Log.e("log_tag", "Error parsing data: " + e.toString());
}
else
{
Log.e("<tag>", "History TextView 1 e.getMessage() was null");
}
}
catch(Exception e)
{
if (e.getMessage() != null)
{
Log.e("log_tag", "Error parsing data: " + e.toString());
}
else
{
Log.e("<tag>", "History TextView 2 e.getMessage() was null");
}
}
}
void viewLast5Packets()
{
if (!isNetworkConnected(this))
{
showAlert();
}
else
{
historyTV.setText("");
userDefinedCount = 5;
//prefEditor.putString(lastpacketsPHP, "\* PHP file location goes here. */");
//prefEditor.commit();
// These next two lines are used to test the PHP files on the SHC server by determining if PHP is set up correctly.
prefEditor.putString(lastpacketsPHP, "\* PHP file location goes here. */");
prefEditor.commit();
dialog = new runDialog(this, api, new runDialog.OnDataLoadedListener()
{
public void dataLoaded(String textViewString)
{
TextView infoTV = (TextView)findViewById(shc_BalloonSat.namespace.R.id.info);
infoTV.setText(textViewString);
assignInfoToInfoTextView();
assignInfoToHistoryTextView();
}
});
dialog.execute();
}
}
void viewLast10Packets()
{
if (!isNetworkConnected(this))
{
showAlert();
}
else
{
historyTV.setText("");
userDefinedCount = 10;
//prefEditor.putString(lastpacketsPHP, "\* PHP file location goes here. */");
//prefEditor.commit();
// These next two lines are used to test the PHP files on the SHC server by determining if PHP is set up correctly.
prefEditor.putString(lastpacketsPHP, \* PHP file location goes here. */");
prefEditor.commit();
dialog = new runDialog(this, api, new runDialog.OnDataLoadedListener()
{
public void dataLoaded(String textViewString)
{
TextView infoTV = (TextView)findViewById(shc_BalloonSat.namespace.R.id.info);
infoTV.setText(textViewString);
assignInfoToInfoTextView();
assignInfoToHistoryTextView();
}
});
dialog.execute();
}
}
void viewLast20Packets()
{
if (!isNetworkConnected(this))
{
showAlert();
}
else
{
historyTV.setText("");
userDefinedCount = 20;
//prefEditor.putString(lastpacketsPHP, "\* PHP file location goes here. */");
//prefEditor.commit();
// These next two lines are used to test the PHP files on the SHC server by determining if PHP is set up correctly.
prefEditor.putString(lastpacketsPHP, "\* PHP file location goes here. */");
prefEditor.commit();
dialog = new runDialog(this, api, new runDialog.OnDataLoadedListener()
{
public void dataLoaded(String textViewString)
{
TextView infoTV = (TextView)findViewById(shc_BalloonSat.namespace.R.id.info);
infoTV.setText(textViewString);
assignInfoToInfoTextView();
assignInfoToHistoryTextView();
}
});
dialog.execute();
}
}
public void viewKML()
{
if (!isNetworkConnected(this))
{
showAlert();
}
else
{
map.openKML();
}
}
}
My thought is that
are called BEFORE your dialog’s constructor so they are null because findViewById doesn’t find the layout views. Try to change them in:
and then add the following just after the this.setContentView(R.layout.custompreferences) line in your constructor:
Hope this helps…