android – Get last location from FusedLocation in service-ThrowExceptions

Exception or error:

I’ trying to getLastLocation() in my Service, witch is starting every minute. As I can see, fusedLocation requires Activity or Executor in .addOnSuccessListener(). How I can get it in Service?

LocationCheckService.class

public class LocationCheckService extends Service{

    private FusedLocationProviderClient mFusedLocationClient;

    @Override
    public void onCreate() {
        super.onCreate();
        mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
        mFusedLocationClient.getLastLocation()
                .addOnSuccessListener(this, new OnSuccessListener<Location>() {
                    @Override
                    public void onSuccess(Location location) {
                        // Got last known location. In some rare situations this can be null.
                        if (location != null) {

                        }
                    }
                });
    }

    @SuppressLint("MissingPermission")
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        return START_STICKY;
    }
How to solve:

I provide one separate class for fetching location data using faused API. you can call this class into your service it gets latest location lat and long value.

public class GPSController  implements
    LocationListener,
    GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener{

OnLocationUpdateListener onLocationUpdateListener;
public final String TAG = getClass().getSimpleName();

private FusedLocationProviderApi fusedLocationProviderApi =    LocationServices.FusedLocationApi;
GoogleApiClient googleApiClient;
LocationRequest mLocationRequest;
Location mCurrentLocation;
private static long INTERVAL = 1000 * 10;
private static long FASTEST_INTERVAL = 1000 * 5;
FragmentActivity mActivity;
private boolean isLiveUpdate = false;


PendingResult<LocationSettingsResult> result;


/**
 * Checking permission and connect with Google Location service
 * @param activity
 */
public GPSController(FragmentActivity activity) {

    this.mActivity = activity;
    if(PermissionManager.checkPermission(mActivity,PermissionManager.ACCESS_LOCATION))
    {
        if (!isGooglePlayServicesAvailable()) {
            CustomLogHandler.printInfolog("checking googleplayservice : ", "false");
            ((BaseActivity)mActivity).showAlertDialog(mActivity, mActivity.getString(R.string.app_name), mActivity.getString(R.string.play_service_not_found));
        } else {
            CustomLogHandler.printInfolog("checking googleplayservice : ", "true");
            createLocationRequest();
            initFuseAPI();

        }
    }
    else
    {
        PermissionManager.askForPermission(PermissionManager.ACCESS_LOCATION,mActivity);
    }

}

public void connectForLocation()
{
    createLocationRequest();
    initFuseAPI();
}

/**
 * Turn on Live update of location on given interval
 * @param value
 * @param INTERVAL
 * @param FASTEST_INTERVAL
 */
public void turnOnLiveUpdate(boolean value,long INTERVAL,long FASTEST_INTERVAL)
{
    isLiveUpdate = value;
    this.INTERVAL = INTERVAL;
    this.FASTEST_INTERVAL = FASTEST_INTERVAL;
}

/**
 * Turn off live update of location
 */
public void turnOffLiveUpdate()
{
    isLiveUpdate = false;
}

/**
 * Disconnect from Google location service
 */
public void disconnect()
{
    try {
        Log.d(TAG, "onStop fired ..............");
        googleApiClient.disconnect();
        Log.d(TAG, "isConnected ...............: " +googleApiClient.isConnected());
    }catch (Throwable throwable)
    {
        throwable.printStackTrace();
    }
}

/**
 * Resume Location update service if stopped
 */
public void onResumeUpdate()
{
    try {
        if(googleApiClient != null) {
            if (googleApiClient.isConnected()) {
                startLocationUpdates();
                Log.d(TAG, "Location update resumed .....................");
            }
        }
    }catch (Throwable throwable)
    {
        throwable.printStackTrace();
    }
}


public void setLocatonUpdateListener(OnLocationUpdateListener onLocationUpdateListener)
{
    this.onLocationUpdateListener  = onLocationUpdateListener;
}

/**
 * Create location update request
 */
protected void createLocationRequest() {
    try {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(INTERVAL);
        mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    }catch (Throwable throwable)
    {
        throwable.printStackTrace();
    }
}


/**
 * Initialize google location service
 */
void initFuseAPI()
{
    try
    {
        googleApiClient = new GoogleApiClient.Builder(mActivity)
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();
        Log.d(TAG, "initFuseAPI fired ..............");
        googleApiClient.connect();
    }catch (Throwable throwable)
    {
        throwable.printStackTrace();
    }
}


/**
 * Check Google location service is available or not
 * @return
 */
private boolean isGooglePlayServicesAvailable() {
    int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(mActivity);
    if (ConnectionResult.SUCCESS == status) {
        return true;
    } else {
        GooglePlayServicesUtil.getErrorDialog(status, mActivity, 0).show();
        return false;
    }
}

/**
 * called when connected with google location service
 * @param bundle
 */
@Override
public void onConnected( Bundle bundle) {
    Log.d(TAG, "onConnected - isConnected ...............: " + googleApiClient.isConnected());
    LocationManager manager = (LocationManager) mActivity.getSystemService(Context.LOCATION_SERVICE );
    boolean statusOfGPS = manager.isProviderEnabled(LocationManager.GPS_PROVIDER);
    if(statusOfGPS) {
        startLocationUpdates();
    }else
    {
        enableGpsService();
    }
}

@Override
public void onConnectionSuspended(int i) {

}

@Override
public void onConnectionFailed( ConnectionResult connectionResult) {

}

/**
 * Location update received here
 * @param location
 */
@Override
public void onLocationChanged(Location location) {
    Log.d(TAG, "Firing onLocationChanged..............................................");
    mCurrentLocation = location;
    SetLocation();
}


void enableGpsService()
{
    try
    {
        LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
                .addLocationRequest(mLocationRequest);
        builder.setAlwaysShow(true);
        result = LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build());
        result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
            @Override
            public void onResult( LocationSettingsResult locationSettingsResult) {
                final Status status = locationSettingsResult.getStatus();
                switch (status.getStatusCode()) {
                    case LocationSettingsStatusCodes.SUCCESS:
                        //already connected to GPS
                        startLocationUpdates();
                        break;
                    case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                        // Location settings are not satisfied. But could be fixed by
                        // showing the user a dialog.
                        try {
                            status.startResolutionForResult(mActivity, PermissionManager.REQUEST_LOCATION);
                            startLocationUpdates();
                        } catch (IntentSender.SendIntentException e) {
                            // Ignore the error.
                        }
                        break;
                    case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                        //redirect user to setting screen, manually user can enble GPS
                        mActivity.startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS));
                        break;
                }
            }
        });
    }catch (Throwable throwable)
    {
        throwable.printStackTrace();
    }
}





/**
 * Request location update service
 */
public void startLocationUpdates()
{
    try {
        //check required even you checked it previously
        if (PermissionManager.checkPermission(mActivity, PermissionManager.ACCESS_LOCATION))
        {
            fusedLocationProviderApi.requestLocationUpdates(googleApiClient, mLocationRequest, this);
            Log.d(TAG, "Location update started ..............: ");
        } else {
            PermissionManager.askForPermission(PermissionManager.ACCESS_LOCATION, mActivity);
        }
    }catch (Throwable throwable)
    {
        throwable.printStackTrace();
    }
}

/**
 * Stop location update
 */
public void stopLocationUpdates() {
    try {
        if(googleApiClient != null) {
            fusedLocationProviderApi.removeLocationUpdates(
                    googleApiClient, this);
            Log.d(TAG, "Location update stopped .......................");
        }
    }catch (Throwable throwable)
    {
        throwable.printStackTrace();
    }
}


/**
 * set location values received
 */
private void SetLocation()
{
    try {
        Log.d(TAG, "UI update initiated .............");
        if (null != mCurrentLocation) {
            onLocationUpdateListener.onLocationUpdate(mCurrentLocation);

            /**isLiveUpdate = true for Live update **/

            if (!isLiveUpdate) {
                fusedLocationProviderApi.removeLocationUpdates(googleApiClient,this);
            }
            googleApiClient.disconnect();

            //mCurrentLocation.getAccuracy()
            //mCurrentLocation.getProvider()

        } else {
            Log.d(TAG, "location is null ...............");
        }
    }catch (Throwable throwable)
    {
        throwable.printStackTrace();
    }
}

public Location getLocation(){
    return mCurrentLocation;
}
public static List<Address> getAddress(Double mLat, Double mLang, Context context)
{
    List<Address> addresses = null;
    try
    {
        Geocoder geocoder = new Geocoder(context, Locale.getDefault());
        addresses = geocoder.getFromLocation(mLat, mLang, 1);
    }catch (Exception e)
    {
        e.printStackTrace();
    }
    return  addresses;
}

/**
 * For receive location update
 */
public interface OnLocationUpdateListener {
     void onLocationUpdate(Location mCurrentLocation);
}

}

call into this service class like this ..

    gpsController = new GPSController(getActivity());
    gpsController.setLocatonUpdateListener(this);
    if (gpsController != null)
        gpsController.onResumeUpdate();

    public void setLocatonUpdateListener(OnLocationUpdateListener onLocationUpdateListener) {
    this.onLocationUpdateListener = onLocationUpdateListener;
}

and also implement this into class ..

implements GPSController.OnLocationUpdateListener

@Override
public void onLocationUpdate(Location mCurrentLocation) {
    CURRENT_LET = String.valueOf(mCurrentLocation.getLatitude());// both string variable to store value
    CURRENT_LANG = String.valueOf(mCurrentLocation.getLongitude());

}

###

You don’t need GoogleApiClient –

first in gradle add –

implementation 'com.google.android.gms:play-services-location:15.0.0'

In Android Manifest –

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

than create a service to get location update as –

public class LocationUpdateService extends Service {

    private FusedLocationProviderClient client;
    private LocationRequest locationRequest;


    @Override
    public void onCreate() {
        super.onCreate();
        client = LocationServices.getFusedLocationProviderClient(this);
        locationRequest = LocationRequest.create();
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        locationRequest.setInterval(0);
        locationRequest.setFastestInterval(0);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        try {
            client.requestLocationUpdates(locationRequest, locationCallback, null);
        } catch (SecurityException ignore) {
            Log.e("AppLocationService", "SecurityException - " + ignore.toString(), ignore);
        }
        return START_STICKY;
    }

    private final LocationCallback locationCallback = new LocationCallback() {

        @Override
        public void onLocationResult(LocationResult locationResult) {
            List<Location> locationList = locationResult.getLocations();
            if (locationList.size() != 0) {
                Location location = locationList.get(0);
                Log.e("AppLocationService", "Latitude  - " +location.getLatitude()+", longitude  - " +location.getLongitude() );
            }
        }
    };


    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        return null;
    }


}

To get update in activity you can use LocalBroadCast OR same code you can use in Activity

NOTE : don’t forget to take permission above 23

###

This implementation in Java works in a service class, after the fusedLocationClient has been initialized:

fusedLocationClient.getLastLocation().addOnCompleteListener(new OnCompleteListener<Location>() {
            @Override
            public void onComplete(@NonNull Task<Location> task) {
                Location last_known_loction = task.getResult();
                latitude = last_known_loction.getLatitude();
                longitude = last_known_loction.getLongitude();
            }
        });

Leave a Reply

Your email address will not be published. Required fields are marked *