Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google Play Services or Android Location Services

I am wanting to implement location based functionality in my app. I have been reading a bit and I find my self a bit confused.

When googling for tutorial almost every result comes back with an example using Android Location API.

However when reading the android developer guidelines they state the following:

The Google Play services location APIs are preferred over the Android framework location APIs (android.location) as a way of adding location awareness to your app. If you are currently using the Android framework location APIs, you are strongly encouraged to switch to the Google Play services location APIs as soon as possible.

Android Docs

So this is telling me not to go for the simpler route of just implementing a Location Listener.

So my question is, what is the difference between the two? Why would I use one and not the other?

Where can I find a decent tutorial on how to safely and accurately access the Google play services location API properly.

I have tried this so far (as suggested on the Android site), However none of my Call Backs are being called.

public class LocationManager implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {

private Context mContext;
private GoogleApiClient mGoogleApiClient;
private Location mLastLocation;

public LocationManager(Context context) {
    mContext = context;
    //
    if (checkIfGooglePlayServicesAreAvailable()) {
        //Get Access to the google service api
        buildGoogleApiClient();
    } else {
        //Use Android Location Services
        //TODO:
    }
}

public Location getCoarseLocation() {
    if (mLastLocation != null) {
        return mLastLocation;
    } else return null;
}

private synchronized void buildGoogleApiClient() {
    mGoogleApiClient = new GoogleApiClient.Builder(mContext)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();
}

private boolean checkIfGooglePlayServicesAreAvailable() {
    int errorCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(mContext);
    if (errorCode != ConnectionResult.SUCCESS) {
        GooglePlayServicesUtil.getErrorDialog(errorCode, (MainActivity) mContext, 0).show();
        return false;
    }
    return true;
}


@Override
public void onConnected(Bundle bundle) {
    Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
    if (location != null) {
        mLastLocation = location;
        Toast.makeText(mContext, location.getLongitude() + " , " + location.getLatitude() + " : " + location.getAccuracy(), Toast.LENGTH_LONG).show();
    }
}

@Override
public void onConnectionSuspended(int i) {
    Toast.makeText(mContext, "suspended", Toast.LENGTH_LONG).show();
}

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
    Toast.makeText(mContext, connectionResult.toString(), Toast.LENGTH_LONG).show();
}
}

I then call my LocationManager From My Activity:

LocationManager locationManager = new LocationManager(this);
Location location = locationManager.getCoarseLocation();
//Use Location

I want to make a helper class which I can simply call from any activity or fragment. However when I run the following, the constructor executes successfully. However none of my breakpoints in the callbacks get hit. even after 1 or 2 minutes.

like image 367
Zapnologica Avatar asked Mar 18 '23 10:03

Zapnologica


1 Answers

Google Play Services Api uses a callback method public void onConnected(Bundle bundle) which is called only when a connection is established. It is only then that the LocationServices.FusedLocationApi.getLastLocation(googleApiClient) method call will be able to return the correct Location.

You have constructed a helper class to obtain this location but you should understand that the connection is not established instantly. Therefore simply an async call to a helper class or it's method might return a null object as the connection might not have been made.

You could obtain the Location in the following ways.

1) Broadcast the location and receive it through a BroadcastReceiver to carry out the subsequent operations from within the public void onConnected(Bundle bundle). This worked for me.

private boolean flag = false;

@Override
public void onConnected(Bundle connectionHint) {
    location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
    if (location != null && !flag) {
        flag = true;
        Intent intent = new Intent(LOCATION_BROADCAST_ACTION);
        intent.putExtra(INTENT_EXTRA_LOCATION, location);
        LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
        Log.i(TAG, "Sending Location Broadcast");
        Log.i(TAG, location.toString());
    } else if (location == null){
        Toast.makeText(mContext, R.string.no_location_detected, Toast.LENGTH_LONG).show();
        Log.e(TAG, "No Location Detected");
    }
}

2) Create a public Location object in the calling Activity or Fragment and update its value from within the public void onConnected(Bundle bundle) method.

@Override
public void onConnected(Bundle connectionHint) {
    location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
    if (location != null) {
        MyActivity.location = location; // update the Location object of you caller activity or fragment
        Log.i(TAG, "location updated");
    }
}

Moreover, you should connect to Google Play Services Location Api after building GoogleApiClient. Just add the method call mGoogleApiClient.connect() after your buildGoogleApiClient(); method call in your constructor. You don't need to check if Google Play Services are available or not.

You could also add the method call googleApiClient.connect(); in your implementation of public void onConnectionSuspended(int i).

like image 168
Rahul Parida Avatar answered Mar 31 '23 15:03

Rahul Parida