-1

I have a non activity class MyLocation searching for location which is called form MainActivity. When MainActivity is onPause() I want to remove updates but I get an NPE because the listener = null even it's running. I know I can catch the NPE with an if but my problem is why the listener is null.

I'm calling in the MainActivity @ onPause():

MyLocation myLocation = new MyLocation(MainActivity.this, this);
myLocation.removeListener();

In MyLocation I start the location manager and want to stop listening with the method removeListener():

EDIT: Added complete code of MyLocation:

    public class MyLocation {
    LocationManager lm;
    LocationManager lmNetwork;
    LocationManager lmGPS;
    LocationResult locationResult;
    boolean gps_enabled = false;
    boolean network_enabled = false;
    Context context;
    static Activity activity;
    private String gps, network, strLocationProvider;
    static ProgressDialog progress;

    private final int interval = 30000;
    private Handler handler = new Handler();
    private Handler handler2 = new Handler();

    public MyLocation(MainActivity context, MainActivity activity) {
        this.context = context;
        MyLocation.activity = activity;
    }

    public boolean getLocation(Context context, LocationResult result) {
        // Create a progress bar to display while the list loads
        showLoadingDialog();

        // I use LocationResult callback class to pass location value from
        // MyLocation to user code.
        locationResult = result;
        if (lm == null)
            lm = (LocationManager) context
            .getSystemService(Context.LOCATION_SERVICE);

        // exceptions will be thrown if provider is not permitted.
        try {
            network_enabled = lm
                    .isProviderEnabled(LocationManager.NETWORK_PROVIDER);
        } catch (Exception ex) {
        }
        try {
            gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
        } catch (Exception ex) {
        }

        // don't start listeners if no provider is enabled
        if (!gps_enabled && !network_enabled)
            enableLocationServices(context);

        if (network_enabled)
            System.out.println("Network => enabled");
        lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0,
                locationListenerNetwork);

        if (gps_enabled)
            System.out.println("GPS => enabled");
        lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,
                locationListenerGps);

        handler.postDelayed(locationfallback, interval);
        return true;
    }

    LocationListener locationListenerNetwork = new LocationListener() {
        public void onLocationChanged(Location location) {

            System.out
            .println("Provider => Network");

            locationResult.gotLocation(location);
            hideLoadingDialog();

            lm.removeUpdates(this);
            handler.removeCallbacks(locationfallback);

            //Continue searching for GPS for a defined time period
            handler2.postDelayed(GPSstopdelayed, interval);

        }

        public void onProviderDisabled(String provider) {
        }

        public void onProviderEnabled(String provider) {
        }

        public void onStatusChanged(String provider, int status, Bundle extras) {
        }
    };

    LocationListener locationListenerGps = new LocationListener() {

        public void onLocationChanged(Location location) {

            System.out
            .println("Provider => GPS");

            locationResult.gotLocation(location);
            hideLoadingDialog();

            lm.removeUpdates(this);
            lm.removeUpdates(locationListenerNetwork);

            handler.removeCallbacks(locationfallback);

        }

        public void onProviderDisabled(String provider) {
        }

        public void onProviderEnabled(String provider) {
        }

        public void onStatusChanged(String provider, int status, Bundle extras) {
        }
    };

    //Schedule GPS listener
    private Runnable GPSstopdelayed = new Runnable() {

        @Override
        public void run() {
            lm.removeUpdates(locationListenerGps);
        }
    };

    //Fallback if listeners don't find any location until handler timer elapses
    private Runnable locationfallback = new Runnable() {

        @Override
        public void run() {

            lm.removeUpdates(locationListenerGps);
            lm.removeUpdates(locationListenerNetwork);

            try {
                LocationManager lm = (LocationManager) context
                        .getSystemService(Context.LOCATION_SERVICE);

                Criteria criteria = new Criteria();
                criteria.setAccuracy(Criteria.ACCURACY_FINE);
                criteria.setAltitudeRequired(false);
                criteria.setBearingRequired(false);
                criteria.setCostAllowed(true);
                criteria.setPowerRequirement(Criteria.POWER_LOW);
                strLocationProvider = lm.getBestProvider(criteria, true);

                System.out
                .println("FallbackLocationProvider => " + strLocationProvider);
                Location location = lm
                        .getLastKnownLocation(strLocationProvider);
                if (location != null) {
                    locationResult.gotLocation(location);
                    // Highlight GPS or Network icon
                    String usedProvider = location.getProvider();
                    if (usedProvider.equals("gps")) {
                        //Do something
                    }
                    if (usedProvider.equals("network")) {
                        //Do something else
                    }
                    hideLoadingDialog();

                }
                if (location == null) {
                    hideLoadingDialog();

                    Toast.makeText(
                            activity,context.getResources()
                            .getString(R.string.place_not_found),
                                    Toast.LENGTH_LONG).show();
                }
                return;

            } catch (Exception ex) {
                ex.printStackTrace();
            }

        }

    };

    public static abstract class LocationResult {
        public abstract void gotLocation(Location location);
    }

    public void enableLocationServices(final Context context) {

        // Show dialog to enable location services
        AlertDialog.Builder mAlertDialog = new AlertDialog.Builder(context);

        // Setting Dialog Title
        mAlertDialog
        // .setTitle(
        // context.getResources().getString(
        // R.string.location_not_available))
        .setMessage(
                context.getResources().getString(
                        R.string.enable_location_services))
                        .setPositiveButton(
                                context.getResources()
                                .getString(R.string.open_settings),
                                new DialogInterface.OnClickListener() {
                                    public void onClick(DialogInterface dialog,
                                            int which) {
                                        Intent intent = new Intent(
                                                Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                                        context.startActivity(intent);
                                        dialog.dismiss();
                                    }
                                }).show();
    }

    protected void removeListener() {
        handler.removeCallbacks(locationfallback);
        lm.removeUpdates(locationListenerGps);
        lm.removeUpdates(locationListenerNetwork);
    }

    protected void showLoadingDialog() {
        if (progress != null){
            progress.cancel();
            progress = ProgressDialog.show(activity, null, null, true, true);
            progress.setContentView(R.layout.progress_location_layout);
        } 
        if (progress == null){
            progress = ProgressDialog.show(activity, null, null, true, true);
            progress.setContentView(R.layout.progress_location_layout);
        }
    }

    protected void hideLoadingDialog() {
        if (progress != null && progress.isShowing()) {
            progress.cancel();
        }

    }

}

And here's my gotLocation() from MainActivity which calls a method to show the location:

 LocationResult locationResult = new LocationResult() {
 @Override
 public void gotLocation(Location location) {
     if (location == null){
         tvcity.setText(R.string.notfound);
     }       
     if (location != null) {
         setLocation(location);
     }
 }
 };

Here's the log:

10-08 14:16:22.805: W/dalvikvm(4939): threadid=1: thread exiting with uncaught  exception (group=0x40c87318)
10-08 14:16:22.805: E/AndroidRuntime(4939): FATAL EXCEPTION: main
10-08 14:16:22.805: E/AndroidRuntime(4939): java.lang.RuntimeException: Unable to pause activity {com.fleank.skybuddy/com.fleank.skybuddy.MainActivity}: java.lang.NullPointerException
10-08 14:16:22.805: E/AndroidRuntime(4939):     at android.app.ActivityThread.performPauseActivity(ActivityThread.java:2842)
10-08 14:16:22.805: E/AndroidRuntime(4939):     at android.app.ActivityThread.performPauseActivity(ActivityThread.java:2798)
10-08 14:16:22.805: E/AndroidRuntime(4939):     at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:2776)
10-08 14:16:22.805: E/AndroidRuntime(4939):     at android.app.ActivityThread.access$800(ActivityThread.java:134)
10-08 14:16:22.805: E/AndroidRuntime(4939):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1210)
10-08 14:16:22.805: E/AndroidRuntime(4939):     at android.os.Handler.dispatchMessage(Handler.java:99)
10-08 14:16:22.805: E/AndroidRuntime(4939):     at android.os.Looper.loop(Looper.java:137)
10-08 14:16:22.805: E/AndroidRuntime(4939):     at android.app.ActivityThread.main(ActivityThread.java:4744)
10-08 14:16:22.805: E/AndroidRuntime(4939):     at java.lang.reflect.Method.invokeNative(Native Method)
10-08 14:16:22.805: E/AndroidRuntime(4939):     at java.lang.reflect.Method.invoke(Method.java:511)
10-08 14:16:22.805: E/AndroidRuntime(4939):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
10-08 14:16:22.805: E/AndroidRuntime(4939):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
10-08 14:16:22.805: E/AndroidRuntime(4939):     at dalvik.system.NativeStart.main(Native Method)
10-08 14:16:22.805: E/AndroidRuntime(4939): Caused by: java.lang.NullPointerException
10-08 14:16:22.805: E/AndroidRuntime(4939):     at com.fleank.skybuddy.MyLocation.removeListener(MyLocation.java:131)
10-08 14:16:22.805: E/AndroidRuntime(4939):     at com.fleank.skybuddy.MainActivity.onPause(MainActivity.java:457)
10-08 14:16:22.805: E/AndroidRuntime(4939):     at android.app.Activity.performPause(Activity.java:5106)
10-08 14:16:22.805: E/AndroidRuntime(4939):     at android.app.Instrumentation.callActivityOnPause(Instrumentation.java:1225)
10-08 14:16:22.805: E/AndroidRuntime(4939):     at android.app.ActivityThread.performPauseActivity(ActivityThread.java:2829)
sascha
  • 265
  • 2
  • 4
  • 13

1 Answers1

1

Looks like the error is at the MyLocation Class and at the MainActivity, My bet is that you initiate a new instance of the class and then try to access the location listener, Can you edit your post and publish the entire code of MyLocation.java? I think that if you'll save a reference to the instance of MyLocation and call that instance at the onPause() method it will work.

Edit

You initiate a new instance of myLocation at the onPause() method and the location listener is being initiated at the class, That means that you have atleast two instances of myLocation and therefore two instances of LocaitonListener. You start the location updates with one of them and then try to stop them with the second. What you can do is hold a class variable of my location, initiate it at onCreate and use it at the onPause method. something like that:

public class MainActivity extends Activity {

    private MyLocation mMyLocation;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mMyLocation = new MyLocation(MainActivity.this, this);
    }

    @Override
    protected void onPause() {
        myLocation.removeListener();
        super.onPause();
    }
}

Another option which is very similar to what you do now is to use the Singleton design pattern described here: http://www.tutorialspoint.com/design_pattern/singleton_pattern.htm , I would use the first suggestion I made.

Ohad Zadok
  • 3,452
  • 1
  • 22
  • 26
  • Thanks for your reply! I've added my complete code of MyLocation.java – sascha Oct 18 '14 at 14:48
  • Ah, understood, so I initiated a new instance in my onPause. Thanks a lot, that fixed the issue and thanks for the explanation! – sascha Oct 19 '14 at 10:47