Reputation: 51
I've developed a simple weather app, but there is too much code in my WeatherActivity and two responsibilities for one class(handling weather JSON, and retrieving location info using googleapiclient). I tried to get the code that handles location out of the WeatherActivity class, but as I try to get any location in the onCreate method, it usually results in null, probably because it's not enough time to be updated. Is there any way to get users location outside of the activity? Or if you have another suggestion that might help in that situation?
Upvotes: 2
Views: 929
Reputation: 178
I have been looking for a solution to have an object to handle the current location but I didn't find anything. So I did it this way but it's a little bit tricky. Hope it helps you.
import android.Manifest;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
/**
* This class uses GoogleApiClient to track location changes.
* In order to connect the GoogleApiClient correctly, this class must be instanciated in onCreate callback.
*/
public class Locator implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
private static final String TAG = "Locator";
private Activity activity;
private GoogleApiClient googleApiClient;
private LocationRequest locationRequest;
private static final long UPDATE_INTERVAL = 60 * 1000;
private static final long FASTEST_UPDATE_INTERVAL = 10 * 1000;
private static final int LOCATION_REQUEST = 1;
private static boolean locationPermissionRequested = false;
private static boolean locationPermissionGranted = false;
private Location location;
/**
* Default constructor. Ex. Locator locator = new Locator(getActivity());
*
* @param activity The activity to instanciate from.
*/
public Locator(Activity activity) {
this.activity = activity;
if (activity != null) {
googleApiClient = new GoogleApiClient.Builder(activity)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).build();
locationRequest = new LocationRequest();
locationRequest.setInterval(UPDATE_INTERVAL);
locationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL);
locationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
googleApiClient.connect();
}
}
@Override
public void onConnected(@Nullable Bundle bundle) {
requestLocation();
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onLocationChanged(Location location) {
this.location = location;
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
}
/**
* Requests the current location to the GoogleApiClient.
* NB: If device os is Marshmallow or higher, il will also ask permission to acces location services.
*/
private void requestLocation() {
if (googleApiClient.isConnected()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
locationPermissionGranted = ActivityCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED;
if (!locationPermissionGranted) {
if (!locationPermissionRequested) {
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, LOCATION_REQUEST);
locationPermissionRequested = true;
requestLocation();
}
}
} else {
locationPermissionGranted = true;
}
if (locationPermissionGranted) {
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
} else {
}
}
}
/**
* Requests the current location et gets.
*
* @return The location.
*/
public Location getLocation() {
requestLocation();
return location;
}
/**
* Stops updating the location. (save battery power).
*/
public void removeUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient, this);
}
}
Upvotes: 4