我目前正在尝试调试我的应用程序,但是,我遇到了 NullPointerException 的一些困难。我有一个带有 4 个复选框、一个保存按钮和一个取消按钮的对话框。当用户在对话框中标记他们的选择然后按下保存按钮时,它返回 NullPointerException,我不明白为什么。以下是与查找解决方案相关的 XML 文件:
<?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>
代码集是将用户的选择保存到 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");
}
}
}
}
NullPointerException 发生在 savedSettings 函数中。该函数所做的只是将数据放入 SharedPreferences 中。知道为什么这会导致某些东西为空吗?提前感谢您提供的任何帮助。
更新:以下是错误日志。
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)
下面是我在其中实例化侦听器的主类。
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();
}
}
}