0

I have a trackingService locationManager component which processes in the background and it is launched from the MainActivity activity. At the same time, I have another component to retrieve this data from the server and displaying it in the Map activity. The user can access data in the server from the MainActivity, when he clicks a buton in it. Thereupon, the data is being retrieved from the server and the user redirects to the Map activity. Everything it works for me so far.

I am trying to remove the locationManager in two cases:

  • When the user click the checkbox in the menu of MainActivity.
  • or when he closes the app (Not when the user changes the activity).

With this code snippet:

@Override
public void onDestroy() {
    super.onDestroy();
    unregisterReceiver(wifi_receiver);
    System.out.println("ABC TrackingService onDestroy() was invoked.");
    // commeted 13.08.15

    if(lm != null){
        lm.removeUpdates(this);
        System.out.println("ABC lm locationManager is not equal null.");
    }else{
        System.out.println("ABC lm locationManager is null.");

    }       
}

I have tried it with the code below so when I click the button in the MainActivity for the first time, the user is being redirected to the Map activity and the service works (without calling the onDestroy() in the TrackingService class) but when I go back from the Map activity to the MainActivity(Service still works) and then clicks the button to go again to the Map activity, at this point, the onDestroy() in the TrackingService class is being called and the service stops

With this code snippet:

@Override
public void onDestroy() {
    super.onDestroy();
    unregisterReceiver(wifi_receiver);
    System.out.println("ABC TrackingService onDestroy() was invoked.");
    lm.removeUpdates(this);

}

I am getting this error below: Error:

08-29 12:46:06.624: E/AndroidRuntime(6332): FATAL EXCEPTION: main
08-29 12:46:06.624: E/AndroidRuntime(6332): Process: com.bustracker, PID: 6332
08-29 12:46:06.624: E/AndroidRuntime(6332): java.lang.RuntimeException: Unable to stop service com.bustracker.TrackingService@1e57ec95: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.location.LocationManager.removeUpdates(android.location.LocationListener)' on a null object reference
08-29 12:46:06.624: E/AndroidRuntime(6332):     at android.app.ActivityThread.handleStopService(ActivityThread.java:3356)
08-29 12:46:06.624: E/AndroidRuntime(6332):     at android.app.ActivityThread.access$2300(ActivityThread.java:177)
08-29 12:46:06.624: E/AndroidRuntime(6332):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1551)
08-29 12:46:06.624: E/AndroidRuntime(6332):     at android.os.Handler.dispatchMessage(Handler.java:102)
08-29 12:46:06.624: E/AndroidRuntime(6332):     at android.os.Looper.loop(Looper.java:145)
08-29 12:46:06.624: E/AndroidRuntime(6332):     at android.app.ActivityThread.main(ActivityThread.java:5944)
08-29 12:46:06.624: E/AndroidRuntime(6332):     at java.lang.reflect.Method.invoke(Native Method)
08-29 12:46:06.624: E/AndroidRuntime(6332):     at java.lang.reflect.Method.invoke(Method.java:372)
08-29 12:46:06.624: E/AndroidRuntime(6332):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1389)
08-29 12:46:06.624: E/AndroidRuntime(6332):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1184)
08-29 12:46:06.624: E/AndroidRuntime(6332): Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.location.LocationManager.removeUpdates(android.location.LocationListener)' on a null object reference
08-29 12:46:06.624: E/AndroidRuntime(6332):     at com.bustracker.TrackingService.onDestroy(TrackingService.java:301)
08-29 12:46:06.624: E/AndroidRuntime(6332):     at android.app.ActivityThread.handleStopService(ActivityThread.java:3339)
08-29 12:46:06.624: E/AndroidRuntime(6332):     ... 9 more

How can I stop the service in this two cases and why onDestroy() not being invoked when I click the button for the first time?

I appreciate any help.

MainActivity:

public class MainActivity extends ActionBarActivity implements
        AsyncTaskCallback {
    TrackingService mService;
    boolean mBound = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.route_available);
        // Start the TrackingService class.
        Intent i = new Intent(this, TrackingService.class);
        startService(i);
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.main_menu, menu);
        System.out.println("test onCreateOptionsMenu was invoked.");

        return true;
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        MenuItem checkable = menu.findItem(R.id.checkable_menu);
        checkable.setChecked(isChecked);
        return true;
    }

    // Start and stop the background service.
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.checkable_menu:
            if (isChecked = !item.isChecked()) {
                item.setChecked(isChecked);
                Intent i = new Intent(this, TrackingService.class);
                startService(i);
                System.out.println("test if onOptionsItemSelected");
            } else {
                mService.stopTrackingService();

            }
            return true;

        default:
            return false;
        }
    }

}

TrackingService class:

public class TrackingService extends Service implements AsyncTaskCallback,
        LocationListener {
    LocationManager lm;
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        detectLocation();
        return START_STICKY;
    }
    private void detectLocation() {
        // TODO Auto-generated method stub
        Toast.makeText(this, "Inside detectlocation()", Toast.LENGTH_SHORT)
                .show();
        lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 30 * 1000, 0,
                this);
        enableGPS(lm);

    }
    @Override
    public void onDestroy() {
        super.onDestroy();
        lm.removeUpdates(this);
        System.out.println("ABC locationManager is not equal null.");       
    }

    public void stopTrackingService(){
        lm.removeUpdates(this);
    }
}

Map activity:

public class Map extends FragmentActivity implements OnMapReadyCallback, ConnectionCallbacks, OnConnectionFailedListener{
    @Override
    protected void onDestroy() {
        super.onDestroy();
 // To stop the service when the user closed the app in the background and the map ativity was opened.      
        stopAlarm();
        Intent i = new Intent(this, TrackingService.class);
        stopService(i);
        System.out.println("ABC Map onDestroy() was invoked!");

    }

}
benz
  • 693
  • 1
  • 9
  • 29
  • Have you tired to override BackButton and unregistered the service when clicked? – Want2bExpert Aug 29 '15 at 11:01
  • Where have I to override `onBackPressed` in the TrackingService or in the Map activity? I dont want to stop the service when I go back ! – benz Aug 29 '15 at 11:10
  • My apology what I.meant was, try to create a Variables that passes value to the Activity. E.g. in onDestroy if value = false don't unregistered the service else value = true unregistered the service. – Want2bExpert Aug 29 '15 at 11:26
  • It would be helpful if your add your apporach as answer since I dont know which `onDestroy()` do you mean? and when should the value be true and false? – benz Aug 29 '15 at 11:54
  • OK.I have had a quick look at the code. Since you starting the service from the MainActivity and want the service to stop only when MainActivity is destroyed then I don't think you need onDestroy in the service and just unregistered it in MainActivity onDestroy. Additionally, have a look at this link maybe it could help, perhaps you can check if the service is still running before starting it http://stackoverflow.com/questions/600207/how-to-check-if-a-service-is-running-on-android – Want2bExpert Aug 29 '15 at 12:14
  • I need `onDestroy()` in the service since when I close the app with one of the both activities the `onDestroy()` of the activity is invoked then I am using `stopService(i);` in it. Thereupon, the `onDestroy()` in the service is called and the `lm` locationManager is removed. – benz Aug 29 '15 at 16:13
  • How can I distinguish when onDestroy() is invoked when the app is being closed and when the user changed the activities? – benz Aug 29 '15 at 16:14
  • Override some Activity life cycles e.g. In onResume() and/or onPause() registered, since you only want to stop the service only when application is destroyed then in will say perhaps unregistered in onStop() – Want2bExpert Aug 29 '15 at 16:36

1 Answers1

0

In your MainActivity and try something like:

@Override
public void onBackPressed() {
    super.onBackPressed();
    // remove locationManager here
    finish();
}
zkminusck
  • 1,230
  • 1
  • 12
  • 23
  • You mean in the Map activity?! and I dont want to stop the service when the user clicks the back button anywhere – benz Aug 29 '15 at 12:03
  • Sorry, wrote closing not removing, I updated my answer :) You said, you want to remove your locationManager when you close the app. In this case, you have to Override the onBackPressed in your MainActivity. – zkminusck Aug 29 '15 at 12:10