Search code examples
androidandroid-asynctaskgoogle-geocoder

NullPointer with Geocoder/AsyncTask - Android


I have what seems like should be an easy find, but I'm looking at all my variables and can't find the null value. I recently separated the MyGeocoderTask class out of LocationMain, which is probably where I messed things up. It worked fine before. :( Now when I click the button which activates findThroughPopup(), the app crashes. I'm still not completely a pro at getting variables to transfer over to other classes when needed, so besides finding which one is null, I should probably have help coding it right too. My two classes and stacktrace below. Thanks for your help.

LocationMain.java

package org.azurespot.practiceapp.location;

import org.azurespot.practiceapp.R;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.FragmentManager;
import android.content.Context;
import android.content.DialogInterface;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import android.widget.FrameLayout;

import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;

public class LocationMain extends Activity {

    public static FragmentManager fragmentManager;
    public final int RQS_GooglePlayServices = 1;

    protected static Double latitude;
    protected static Double longitude;
    protected static Context context;
    protected static EditText addressInput;

    protected LatLng myPosition;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_location_main);

        fragmentManager = getFragmentManager();

    }

    // locates the user's location
    public void findMe(View v){

        if (LocationFragment.mMap == null){
            LocationFragment.setUpMapIfNeeded();
        }

        if (LocationFragment.mMap != null) {

        // Enabling MyLocation Layer of Google Map
        LocationFragment.mMap.setMyLocationEnabled(true);   

        // Getting LocationManager object from System Service LOCATION_SERVICE
        LocationManager locationManager = (LocationManager) 
                                        getSystemService(LOCATION_SERVICE);

        // Creating a criteria object to retrieve provider
        Criteria criteria = new Criteria();

        // Getting the name of the best provider
        String provider = locationManager.getBestProvider(criteria, true);

        // Getting Current Location
        Location location = locationManager.getLastKnownLocation(provider);
        latitude = location.getLatitude();
        longitude = location.getLongitude();

        // Creating a LatLng object for the current location
        myPosition = new LatLng(latitude, longitude);

        LocationFragment.mMap.addMarker(new MarkerOptions().position
                                                (myPosition).title("Start"));

        // For zooming automatically to the Dropped PIN Location
        LocationFragment.mMap.animateCamera(CameraUpdateFactory.newLatLngZoom
                (new LatLng(latitude, longitude), 12.0f));
        }
    }

    // enter address of your choosing into the Dialog box
    public void findThroughPopup(View v) {

        AlertDialog.Builder builder = new AlertDialog.Builder(this);

        // set title
        builder.setTitle("Enter an address");

        // set EditText into your dialog box layout, using FrameLayout
        final FrameLayout frameView = new FrameLayout(this);
        builder.setView(frameView);
        // must inflate EditText separately
        AlertDialog alertDialog = builder.create();
        LayoutInflater inflater = alertDialog.getLayoutInflater();
        View etView = inflater.inflate(R.layout.alert_dialog_edit_text, frameView);
        // initialize EditText, use etView to pull from its specific XML
        addressInput = (EditText)etView.findViewById(R.id.address_field);

        // set Find button that finds address by showing on map
        builder.setPositiveButton("Find", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog,int id) {

                // go through map setup if needed, otherwise process address input
                if (LocationFragment.mMap == null){

                    LocationFragment.setUpMapIfNeeded();
                }

                if (LocationFragment.mMap != null) {

                    String userLocale = addressInput.getText().toString();
                    if(userLocale!=null && !userLocale.equals("")){
                        new MyGeocoderTask().execute(userLocale); 
                    }
                }
                // zooms in to wherever you map ends up,
                // the 15f is in a range of 2.0 - 21.0
                CameraUpdate camZoom = CameraUpdateFactory.zoomTo(12f);
                LocationFragment.mMap.animateCamera(camZoom);
            }
        });

        // set Cancel button
        builder.setNegativeButton("Cancel",new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog,int id) {
                // if this button is clicked, just close
                // the dialog box and do nothing
                dialog.cancel();
            }
        });

        // put all your builders in one create command
        alertDialog = builder.create();

        // show the dialog box
        alertDialog.show();

    } // end findThroughPopup()

    // resets map when back button is pressed
     @Override
        public void onBackPressed()
        {
            super.onBackPressed();
            LocationFragment.onBackPressed();
        }
}

MyGeocoderTask.java

package org.azurespot.practiceapp.location;

import java.io.IOException;
import java.util.List;

import android.location.Address;
import android.location.Geocoder;
import android.os.AsyncTask;
import android.widget.Toast;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;

/***An AsyncTask class for accessing the GeoCoding Web Service****/

public class MyGeocoderTask extends AsyncTask<String, Void, List<Address>>{

    protected LatLng enteredAddress;
    protected MarkerOptions markerOptions;


    @Override
    protected List<Address> doInBackground(String... locationName) {
        // Creating an instance of Geocoder class
        Geocoder geocoder = new Geocoder(LocationMain.context);
        List<Address> addresses = null;

        try {
            // Getting a maximum of 3 Address that matches the input text
            addresses = geocoder.getFromLocationName(locationName[0], 3);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return addresses;
    }

    // part of the GeocoderTask life cycle
    @Override
    protected void onPostExecute(List<Address> addresses) {

        if(addresses==null || addresses.size()==0){
            Toast.makeText(LocationMain.context, "No Location found", 
                                            Toast.LENGTH_SHORT).show();
        }

        // Clears all the existing markers on the map
        LocationFragment.mMap.clear();

        // Adding Markers on Google Map for each matching address
        for(int i=0;i<addresses.size();i++){

            Address address = (Address) addresses.get(i);

            // Creating an instance of GeoPoint, to display in Google Map
            enteredAddress = new LatLng(address.getLatitude(), address.getLongitude());

            String addressText = String.format("%s, %s",
            address.getMaxAddressLineIndex() > 0 ? address.getAddressLine(0) : "",
            address.getCountryName());

            markerOptions = new MarkerOptions();
            markerOptions.position(enteredAddress);
            markerOptions.title(addressText);

            LocationFragment.mMap.addMarker(markerOptions);

            // Locate the first location
            if(i==0)
                LocationFragment.mMap.animateCamera
                        (CameraUpdateFactory.newLatLng(enteredAddress));
        }
    }
}

Logcat

12-29 22:55:00.444: D/AbsListView(20174): unregisterIRListener() is called 
12-29 22:55:06.154: W/dalvikvm(20174): threadid=24: thread exiting with uncaught exception (group=0x41737da0)
12-29 22:55:06.154: E/AndroidRuntime(20174): FATAL EXCEPTION: AsyncTask #1
12-29 22:55:06.154: E/AndroidRuntime(20174): Process: org.azurespot.practiceapp, PID: 20174
12-29 22:55:06.154: E/AndroidRuntime(20174): java.lang.RuntimeException: An error occured while executing doInBackground()
12-29 22:55:06.154: E/AndroidRuntime(20174):    at android.os.AsyncTask$3.done(AsyncTask.java:300)
12-29 22:55:06.154: E/AndroidRuntime(20174):    at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
12-29 22:55:06.154: E/AndroidRuntime(20174):    at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
12-29 22:55:06.154: E/AndroidRuntime(20174):    at java.util.concurrent.FutureTask.run(FutureTask.java:242)
12-29 22:55:06.154: E/AndroidRuntime(20174):    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
12-29 22:55:06.154: E/AndroidRuntime(20174):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
12-29 22:55:06.154: E/AndroidRuntime(20174):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
12-29 22:55:06.154: E/AndroidRuntime(20174):    at java.lang.Thread.run(Thread.java:841)
12-29 22:55:06.154: E/AndroidRuntime(20174): Caused by: java.lang.NullPointerException
12-29 22:55:06.154: E/AndroidRuntime(20174):    at android.location.GeocoderParams.<init>(GeocoderParams.java:50)
12-29 22:55:06.154: E/AndroidRuntime(20174):    at android.location.Geocoder.<init>(Geocoder.java:83)
12-29 22:55:06.154: E/AndroidRuntime(20174):    at android.location.Geocoder.<init>(Geocoder.java:95)
12-29 22:55:06.154: E/AndroidRuntime(20174):    at org.azurespot.practiceapp.location.MyGeocoderTask.doInBackground(MyGeocoderTask.java:26)
12-29 22:55:06.154: E/AndroidRuntime(20174):    at org.azurespot.practiceapp.location.MyGeocoderTask.doInBackground(MyGeocoderTask.java:1)
12-29 22:55:06.154: E/AndroidRuntime(20174):    at android.os.AsyncTask$2.call(AsyncTask.java:288)
12-29 22:55:06.154: E/AndroidRuntime(20174):    at java.util.concurrent.FutureTask.run(FutureTask.java:237)
12-29 22:55:06.154: E/AndroidRuntime(20174):    ... 4 more
12-29 22:55:06.164: D/AbsListView(20174): unregisterIRListener() is called 
12-29 22:55:06.164: E/ViewRootImpl(20174): sendUserActionEvent() mView == null
12-29 22:55:06.374: D/AbsListView(20174): unregisterIRListener() is called 
12-29 22:55:06.784: D/AbsListView(20174): onDetachedFromWindow
12-29 22:55:06.784: D/AbsListView(20174): unregisterIRListener() is called 
12-29 22:55:07.524: I/Process(20174): Sending signal. PID: 20174 SIG: 9

Solution

  • May be LocationMain.context=null in MyGeocoderTask as per your code.

    So you probably pass context as a Constructor in your MyGeocoderTask like so

    private Context mainContxt;
    
    public MyGeocoderTask(Context con){
    mainContxt=com;
    } 
    

    and used like

     Geocoder geocoder = new Geocoder(mainContxt);
    

    and called from Activity like

     new MyGeocoderTask(your_Activity.this).execute(userLocale); 
    

    Update:

     new MyGeocoderTask(getApplicationContext()).execute(userLocale);