我正在尝试开发一个Android应用程序,它可以访问我手机的当前位置并通过URL将其发送给我的朋友。
因此,我使用位置对象mLocation
来访问我所在位置的纬度和经度。 FectchAddressIntentService.java是一个获取位置地址的服务。
但是它给出了一个错误:
java.lang.IllegalArguementException:Attempt to invoke virtual method 'double android.Location.getlatitude()' on a null object reference
以下是我的MainActivity.java的代码:
public class MainActivity extends AppCompatActivity implements
ConnectionCallbacks, OnConnectionFailedListener {
protected static final String TAG = "main-activity";
protected static final String ADDRESS_REQUESTED_KEY = "address-request-pending";
protected static final String LOCATION_ADDRESS_KEY = "location-address";
protected String message;
protected String phoneNo = "1234567890";
public void sendMessage() {
try {
SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage(phoneNo, null, message, null, null);
Toast.makeText(MainActivity.this,"Sending SMS",Toast.LENGTH_LONG).show();
}
catch (Exception e)
{
Toast.makeText(MainActivity.this,e.toString(),Toast.LENGTH_LONG);
}
}
public void startGuardianActivity(){
Intent intentViewGuardian = new Intent(this, Guardians.class);
startActivity(intentViewGuardian);
}
/**
* Provides the entry point to Google Play services.
*/
protected GoogleApiClient mGoogleApiClient;
/**
* Represents a geographical location.
*/
protected Location mLastLocation;
protected String latitude;
protected String longitude;
/**
* Tracks whether the user has requested an address. Becomes true when the user requests an
* address and false when the address (or an error message) is delivered.
* The user requests an address by pressing the Fetch Address button. This may happen
* before GoogleApiClient connects. This activity uses this boolean to keep track of the
* user's intent. If the value is true, the activity tries to fetch the address as soon as
* GoogleApiClient connects.
*/
protected boolean mAddressRequested;
/**
* The formatted location address.
*/
protected String mAddressOutput;
/**
* Receiver registered with this activity to get the response from FetchAddressIntentService.
*/
private AddressResultReceiver mResultReceiver;
/**
* Kicks off the request to fetch an address when pressed.
*/
Button btnAlert;
Button btnAddGuardian;
Button btnRemoveGuardian;
Button btnViewGuardians;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
mResultReceiver = new AddressResultReceiver(new Handler());
btnAlert = (Button) findViewById(R.id.btn_Alert);
btnAddGuardian = (Button) findViewById(R.id.btn_add_guardian);
btnRemoveGuardian = (Button) findViewById(R.id.btn_remove_guardian);
btnViewGuardians = (Button) findViewById(R.id.btn_view_guardians);
btnAddGuardian.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
btnRemoveGuardian.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
btnViewGuardians.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startGuardianActivity();
}
});
// Set defaults, then update using values stored in the Bundle.
mAddressRequested = false;
mAddressOutput = "";
updateValuesFromBundle(savedInstanceState);
updateUIWidgets();
buildGoogleApiClient();
}
/**
* Updates fields based on data stored in the bundle.
*/
private void updateValuesFromBundle(Bundle savedInstanceState) {
if (savedInstanceState != null) {
// Check savedInstanceState to see if the address was previously requested.
if (savedInstanceState.keySet().contains(ADDRESS_REQUESTED_KEY)) {
mAddressRequested = savedInstanceState.getBoolean(ADDRESS_REQUESTED_KEY);
}
// Check savedInstanceState to see if the location address string was previously found
// and stored in the Bundle. If it was found, display the address string in the UI.
if (savedInstanceState.keySet().contains(LOCATION_ADDRESS_KEY)) {
mAddressOutput = savedInstanceState.getString(LOCATION_ADDRESS_KEY);
displayAddressOutput();
}
}
}
/**
* Builds a GoogleApiClient. Uses {@code #addApi} to request the LocationServices API.
*/
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
/**
* Runs when user clicks the Fetch Address button. Starts the service to fetch the address if
* GoogleApiClient is connected.
*/
public void fetchAddressButtonHandler(View view) {
// We only start the service to fetch the address if GoogleApiClient is connected.
if (mGoogleApiClient.isConnected() && mLastLocation != null) {
startIntentService();
}
// If GoogleApiClient isn't connected, we process the user's request by setting
// mAddressRequested to true. Later, when GoogleApiClient connects, we launch the service to
// fetch the address. As far as the user is concerned, pressing the Fetch Address button
// immediately kicks off the process of getting the address.
mAddressRequested = true;
updateUIWidgets();
}
@Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
@Override
protected void onStop() {
super.onStop();
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
/**
* Runs when a GoogleApiClient object successfully connects.
*/
@Override
public void onConnected(Bundle connectionHint) {
// Gets the best and most recent location currently available, which may be null
// in rare cases when a location is not available.
try {
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
latitude = String.valueOf(mLastLocation.getLatitude());
longitude = String.valueOf(mLastLocation.getLongitude());
}
catch(Exception e)
{
Toast.makeText(MainActivity.this,e.toString(),Toast.LENGTH_LONG).show();
}
try {
if (mLastLocation != null) {
if (!Geocoder.isPresent()) {
Toast.makeText(this, R.string.no_geocoder_available, Toast.LENGTH_LONG).show();
return;
}
}
}
catch(Exception e)
{
Toast.makeText(MainActivity.this,e.toString(),Toast.LENGTH_LONG).show();
}
// It is possible that the user presses the button to get the address before the
// GoogleApiClient object successfully connects. In such a case, mAddressRequested
// is set to true, but no attempt is made to fetch the address (see
// fetchAddressButtonHandler()) . Instead, we start the intent service here if the
// user has requested an address, since we now have a connection to GoogleApiClient.
if (mAddressRequested) {
startIntentService();
}
}
/**
* Creates an intent, adds location data to it as an extra, and starts the intent service for
* fetching an address.
*/
protected void startIntentService() {
// Create an intent for passing to the intent service responsible for fetching the address.
Intent intent = new Intent(this, FetchAddressIntentService.class);
// Pass the result receiver as an extra to the service.
intent.putExtra(Constants.RECEIVER, mResultReceiver);
// Pass the location data as an extra to the service.
intent.putExtra(Constants.LOCATION_DATA_EXTRA, mLastLocation);
// Start the service. If the service isn't already running, it is instantiated and started
// (creating a process for it if needed); if it is running then it remains running. The
// service kills itself automatically once all intents are processed.
startService(intent);
}
@Override
public void onConnectionFailed(ConnectionResult result) {
// Refer to the javadoc for ConnectionResult to see what error codes might be returned in
// onConnectionFailed.
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = " + result.getErrorCode());
}
@Override
public void onConnectionSuspended(int cause) {
// The connection to Google Play services was lost for some reason. We call connect() to
// attempt to re-establish the connection.
Log.i(TAG, "Connection suspended");
mGoogleApiClient.connect();
}
/**
* Updates the address in the UI.
*/
protected void displayAddressOutput() {
sendMessage();
}
private void updateUIWidgets() {
if (mAddressRequested) {
btnAlert.setEnabled(false);
} else {
btnAlert.setEnabled(true);
}
}
/**
* Shows a toast with the given text.
*/
protected void showToast(String text) {
Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
}
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save whether the address has been requested.
savedInstanceState.putBoolean(ADDRESS_REQUESTED_KEY, mAddressRequested);
// Save the address string.
savedInstanceState.putString(LOCATION_ADDRESS_KEY, mAddressOutput);
super.onSaveInstanceState(savedInstanceState);
}
/**
* Receiver for data sent from FetchAddressIntentService.
*/
class AddressResultReceiver extends ResultReceiver {
public AddressResultReceiver(Handler handler) {
super(handler);
}
/**
* Receives data sent from FetchAddressIntentService and updates the UI in MainActivity.
*/
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
// Display the address string or an error message sent from the intent service.
mAddressOutput = resultData.getString(Constants.RESULT_DATA_KEY);
message = "I am in DANGER!!I need your help @"+mAddressOutput+" link: http://maps.google.com/?q="+latitude+","+longitude;
displayAddressOutput();
// Show a toast message if an address was found.
if (resultCode == Constants.SUCCESS_RESULT) {
showToast(getString(R.string.address_found));
}
mAddressRequested = false;
updateUIWidgets();
}
}
}
我试图转换
latitude = String.valueOf(mLastLocation.getLatitude());
到
longitude = String.valueOf(mLastLocation.getLongitude());
但没有工作。
我不知道这个错误是什么,我不知道NullPointerException是什么, 我试图关注类似类型的Stack Overflow上的其他问题,但没有解决问题,任何人都可以帮我解决这个问题吗?
即使您认为它可能与其他问题重复,请告诉我它是如何或如何相关的&如何解决我的问题。在此先感谢。: - )
答案 0 :(得分:1)
错误表示有效的mLastLocation
为空。
这一行的结果是:
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
为空。我认为你应该在这些行之前进行空检查:
latitude = String.valueOf(mLastLocation.getLatitude());
longitude = String.valueOf(mLastLocation.getLongitude());
因为他们正在调用mLastLocation
。
就像:
if (mLastLocation == null || !Geocoder.isPresent()) {
Toast.makeText(this, R.string.no_geocoder_available, Toast.LENGTH_LONG).show();
return;
}
latitude = String.valueOf(mLastLocation.getLatitude());
longitude = String.valueOf(mLastLocation.getLongitude());