java.lang.IllegalArguementException:尝试调用虚方法' double android.Location.getlatitude()'在null对象引用上

时间:2015-09-24 20:13:57

标签: java android android-location

我正在尝试开发一个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上的其他问题,但没有解决问题,任何人都可以帮我解决这个问题吗?

即使您认为它可能与其他问题重复,请告诉我它是如何或如何相关的&如何解决我的问题。在此先感谢。: - )

1 个答案:

答案 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());