1

If I have this service, I need to create a method getCoordinates() since I want to broadcast from the service but i want those coordinates available for consumption from activities when need it. Lets say I have a method getCoordinates(), which is the best way to create an accesible method for activities to call it? How that call would be in the activities that wants to consume it?. Any check is needed in case the service is not up for not to make the app crash?. My current code is provided below. Thank you very much.

   @SuppressWarnings("MissingPermission")
public class GPSService extends Service {

    private LocationListener listener;
    private LocationManager locationManager;


    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        listener= new LocationListener() {
            @Override
            public void onLocationChanged(Location location) {
                //To transfer the data to the main activity I use broadcast receiver in the main activity, using an intent filter location_update
                 Intent intentSendLocationMainActivity = new Intent("location_update");
                Log.d("Location-update",location.getLongitude()+" "+location.getLongitude());
                intentSendLocationMainActivity.putExtra("coordinates",location.getLongitude()+" "+location.getLongitude());
                //I need to differentiate here if the app is killed or not to send the location to main activity or to a server
                sendBroadcast(intentSendLocationMainActivity);
            }

            @Override
            public void onStatusChanged(String s, int i, Bundle bundle) {

            }

            @Override
            public void onProviderEnabled(String s) {

            }

            @Override
            public void onProviderDisabled(String s) {
                Intent activateGPSIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                activateGPSIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(activateGPSIntent);

            }
        };
        locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
        //noinspection MissingPermission, listen for updates every 3 seconds
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,3000,0,listener);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d("ClearFromRecentService", "Service Started");
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d("ClearFromRecentService", "Service Destroyed, Removing update location listener");
        //unregistering the listener
        /*if(locationManager != null){
            locationManager.removeUpdates(listener);
        }*/

    }

    public void onTaskRemoved(Intent rootIntent) {
        Log.e("ClearFromRecentService", "END");
        //here you can call a background network request to post you location to server when app is killed
        Toast.makeText(getApplicationContext(), "Warning: App killed", Toast.LENGTH_LONG).show();
        //stopSelf(); //call this method to stop the service
    }

    public void getCoordinate(){
        //return coordinates to the user
  }
}
John
  • 1,711
  • 2
  • 29
  • 42

2 Answers2

1

You can define getCoordinates() method how static method:

public static void getCoordinate(){
    //return coordinates to the user
}

With this soluction you can call it everywhere and always.

NOTE: you have defined getCoordinates() how void, it can't return nothing.

  • 1
    I will try this for sure...it seems the perfect way of doing it...can I call it from an instance even if it's a class-level method? – John Oct 25 '16 at 16:49
  • Yes, you can call it from a istance of GPSService class but the correct way is with the sintax: `GPSService.getCoordinate();` **I advise you to see examples or read the guides to 'use of static methods, even if it is very simple in concept** – Paolo Mastrangelo Oct 25 '16 at 22:09
  • Read the first phrase of the top answer to this question: http://stackoverflow.com/questions/2671496/java-when-to-use-static-methods _One rule-of-thumb: ask yourself "does it make sense to call this method, even if no Obj has been constructed yet?" If so, it should definitely be static._ – Paolo Mastrangelo Oct 25 '16 at 22:15
  • yes, It totally makes sense in this case since it's the object responsibility and there is not going to be more than one instance and it has to be consumed from everywhere...I will try to implement this as soon as I get home from work and give feedback! – John Oct 25 '16 at 22:22
0

In your service create a class that extends Binder, and inside this class create a function that returns a pointer to the service itself. Also create a member variable of the same tipe of your Binder class, and return this object in onBind()... all this inside your service

private final IBinder mBinder = new GPSBinder();

public class GPSBinder extends Binder {
    public GPSService getService() {
        return GPSService.this;
    }
}

@Override
public IBinder onBind(Intent intent) {
    return mBinder;
}

In your activity you need to add a variable of kind GPSServie, and bind to the service, probably in your onResume(), and add a ServiceConnection object which will be notified when the binding is done and you'll get an instance of the Binder, which you can use to get the instance of your Service

GPSService mService;

bindService(intent, mConnection, Context.BIND_AUTO_CREATE); // Put this in onResume()

private ServiceConnection mConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName className, IBinder service) {
        // We've bound to LocalService, cast the IBinder and get LocalService instance
        GPSService.GPSBinder binder = (GPSService.GPSBinder)service;
        myService = binder.getService();
    }

    @Override
    public void onServiceDisconnected(ComponentName arg0) {
        mService = null;
    }
};

Finally whenever you need to call getCoordinate(), you just use the service variable

if (myService!=null)
    myService.getCoordinate(); // YEAH!!!!!

Don't forget to unbind from the service on onPause()

Merlevede
  • 8,140
  • 1
  • 24
  • 39
  • the thing is that on the activity that I need to consume this on demand I have 3 tabs which are fragments. If I go into a fragment will I be able to retrieve the instance of the service if on the onPause() of the activity i'm unbinding it? To make it clearer, imagine on the MainActivity I have a method called 'getGPSServiceInstance()'...... Activity Binds to Service-->Activity stores it on the variable that is returned by the getter method-->activity puts on pause-->one of the tabs contained on the activity opens(fragment) tries to retrieve the gps instance with the getGPS... will that work? – John Oct 24 '16 at 17:04
  • @Juan You can put all the logic from the activity inside a fragment if that fits your needs. You call `getActivity().bindService(...);`. You can even bind to the service from multiple activities or fragments at the same time. – Merlevede Oct 24 '16 at 17:35