How to get real time current location update as we walk - java

I want to discuss if there is possibility of getting real time current location update as we move, I tried with FusedLocationProviderClient to request for current location update every 2 minutes
What can we do to achieve this, implement detectActivity for walk and request current location update every 2 minutes or less in it?
or there is on location change listener thing in FusedLocationProviderClient? so that we can listen for if there is change in location and get latlng in real time and display in textview in application? the location change listener is available on GoogleMap object but isn't recommended to use now, am I right?
or should i stick to requestupdate of FusedLocationProviderClient?
Thanks beforehand
Also tell me if i move my phone from one room to another, will there be change in latlng?

You can use this class that i created :
public class LocationFetcher implements com.google.android.gms.location.LocationListener, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
public GoogleApiClient googleApiClient;
Context context;
private LocationRequest locationRequest;
public LocationFetcher(Context context) {
this.context = context;
googleApiClient = new GoogleApiClient.Builder(context)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
locationRequest = new LocationRequest();
}
public void connectGps() {
googleApiClient.connect();
}
public void requestLocationUpdate() {
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 100);
} else {
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
//Getting location every 3 seconds. You can change this.
locationRequest.setInterval(3000);
locationRequest.setFastestInterval(3000);
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
}
}
public boolean isConnected() {
return googleApiClient.isConnected();
}
#Override
public void onLocationChanged(Location location) {
//You will get location updates here.
}
#Override
public void onConnected(#Nullable Bundle bundle) {
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest);
builder.setAlwaysShow(true);
PendingResult result = LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build());
if (result != null) {
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
#Override
public void onResult(LocationSettingsResult locationSettingsResult) {
final Status status = locationSettingsResult.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
requestLocationUpdate();
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
try {
if (status.hasResolution()) {
status.startResolutionForResult((Activity) context, 1000);
}
} catch (IntentSender.SendIntentException e) {
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
break;
}
}
});
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
DialogPopup.getInstance().showLocationSettingsAlert(context);
}
public void removeLocationUpdates() {
if (googleApiClient.isConnected()){
LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient, this);
}
}
public void disconnectGps() {
googleApiClient.disconnect();
}
}
In onStart of your activity call this :
LocationFetcher locationFetcher = new LocationFetcher(this);
locationFetcher.connectGps();
And in onStop use this:
locationFetcher.disconnectGps();
You will get the location updates in the onLocationChangedMethod of the class.
You have to add this dependency too:
compile 'com.google.android.gms:play-services-location:10.2.1'
Hope this helps.

Related

onLocationChanged not called in Android 6.0 API 23

I'm trying to get the current location using this code and it works when launching the app and when bringing it to the foreground. The toasts show up in both cases, but otherwise they don't. Can anybody tell me where I messed up?
public class LocationFragment extends Fragment implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {
double oldLon,oldLat;
private static final String TAG = MainActivity.class.getSimpleName(); // LogCat tag
private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 1000;
private static final int MY_PERMISSIONS_REQUEST_FINE_LOCATION = 100;
private Location mLastLocation;
private GoogleApiClient mGoogleApiClient;
private FusedLocationProviderClient mFusedLocationClient;
private LocationRequest mLocationRequest;
// Location updates intervals in sec
private static int UPDATE_INTERVAL = 10000; // 10 sec
private static int FATEST_INTERVAL = 5000; // 5 sec
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
// First we need to check availability of play services
if (checkPlayServices()) {
buildGoogleApiClient();
createLocationRequest();
}
}
#Override
public void onDetach() {
mCallback = null; // => avoid leaking
super.onDetach();
}
public interface InterfaceTextClicked {
public void sendText(String text);
}
private boolean checkPermission(){
if(ActivityCompat.checkSelfPermission(getContext(),
ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED){
System.out.println("We have been granted.");
return true;}
else return false;
}
private void requestPermission(){
ActivityCompat.requestPermissions(getActivity(),new String[]
{ACCESS_FINE_LOCATION},MY_PERMISSIONS_REQUEST_FINE_LOCATION);
}
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_FINE_LOCATION: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay!
System.out.println("Permission Granted!");
} else {
// permission denied, boo!
System.out.println("Permission Denied!");
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
if(shouldShowRequestPermissionRationale(ACCESS_FINE_LOCATION)){
new AlertDialog.Builder(getActivity())
.setMessage("Permission needed to access your location.")
.setPositiveButton("OK", new DialogInterface.OnClickListener(){
#Override
public void onClick(DialogInterface dialog,int which){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
requestPermissions(new String[]{ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_FINE_LOCATION);
}
}
})
.setNegativeButton("Cancel", null)
.create()
.show();
return;
}
}
}
// return;
}
}
}
private void displayLocation(){
System.out.println("Inside displayLocation");
requestPermission();
if(checkPermission()){
mLastLocation = LocationServices.FusedLocationApi
.getLastLocation(mGoogleApiClient);
}
if (mLastLocation != null) {
double latitude = mLastLocation.getLatitude();
double longitude = mLastLocation.getLongitude();
System.out.println("Location1: "+latitude+" "+longitude);
if(Double.compare(oldLat,latitude)==0 || Double.compare(oldLon,longitude)==0){
Toast.makeText(getContext(), "Location didn't change! "+latitude+ " "+ longitude,
Toast.LENGTH_LONG).show();
}else{
Toast.makeText(getContext(), "Location changed! NEW: "+latitude+ " "+ longitude+" OLD: "+oldLat+ " "+oldLon,
Toast.LENGTH_LONG).show();
}
// mCallback.sendText(latitude+" "+longitude);
oldLon = longitude;
oldLat = latitude;
} else {
System.out.println("Couldn't get coordinates");
if(mGoogleApiClient.isConnected()){
System.out.println("Client connected");
}else{
System.out.println("Client NOT connected");
}
}
}
/**
* Creating google api client object
* */
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(getContext())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
}
/**
* Method to verify google play services on the device
* */
private boolean checkPlayServices() {
GoogleApiAvailability googleAPI = GoogleApiAvailability.getInstance();
int resultCode = googleAPI.isGooglePlayServicesAvailable(getContext());
if (resultCode != ConnectionResult.SUCCESS) {
if(googleAPI.isUserResolvableError(resultCode)){
googleAPI.getErrorDialog(getActivity(),resultCode,
PLAY_SERVICES_RESOLUTION_REQUEST).show();
} else {
Toast.makeText(getContext(),
"This device is not supported.", Toast.LENGTH_LONG)
.show();
getActivity().finish();
}
return false;
}
return true;
}
#Override
public void onStart() {
super.onStart();
if (mGoogleApiClient != null) {
mGoogleApiClient.connect();
}
}
#Override
public void onResume() {
super.onResume();
if (mGoogleApiClient != null && !mGoogleApiClient.isConnected()) {
mGoogleApiClient.connect();
}
checkPlayServices();
}
#Override
public void onStop() {
super.onStop();
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
/**
* Creating location request object
* */
protected void createLocationRequest() {
mLocationRequest = LocationRequest.create();
mLocationRequest.setInterval(UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(FATEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); }
/**
* Starting the location updates
* */
protected void startLocationUpdates() {
System.out.println("Inside startLocationUpdates");
requestPermission();
if(checkPermission()){
if ((mGoogleApiClient != null) && (mGoogleApiClient.isConnected())){
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
}
}
/**
* Google api callback methods
*/
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = "
+ result.getErrorCode());
}
#Override
public void onConnected(Bundle arg0){
startLocationUpdates();
// Once connected with google api, get the location
displayLocation();
}
#Override
public void onConnectionSuspended(int arg0) {
mGoogleApiClient.connect();
}
#Override
public void onPause() {
super.onPause();
stopLocationUpdates();
}
/**
* Stopping location updates
*/
protected void stopLocationUpdates() {
if ((mGoogleApiClient != null) && (mGoogleApiClient.isConnected())) {
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
}
}
#Override
public void onLocationChanged(Location location) {
// Assign the new location
mLastLocation = location;
Toast.makeText(getContext(), "******Location changed!",
Toast.LENGTH_SHORT).show();
// Displaying the new location on UI
displayLocation();
}
}
Sorry to put so much code up there, I thought my mistake could be anywhere so didn't want to cut out anything.
The Log shows the following:
10-14 01:10:27.408 14485-14485/com.android.wy.parkingauthoritytickingsystem I/System.out: Inside startLocationUpdates
10-14 01:10:27.536 14485-14485/com.android.wy.parkingauthoritytickingsystem I/System.out: We have been granted.
10-14 01:10:27.610 14485-14485/com.android.wy.parkingauthoritytickingsystem I/System.out: Inside displayLocation
10-14 01:10:27.617 14485-14485/com.android.wy.parkingauthoritytickingsystem I/System.out: We have been granted.
10-14 01:10:27.641 14485-14485/com.android.wy.parkingauthoritytickingsystem I/System.out: Location1: 40.4868602 -74.4388156
I don't see anything obviously wrong with your code, though it is making its API calls through the deprecated versions of the location APIs rather than the new FusedLocationProviderClient interface.
While you declare a new-style FusedLocationProviderClient:
private FusedLocationProviderClient mFusedLocationClient;
you never initialize it or use it at runtime; rather you call through FusedLocationApi (the old method):
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
You might try using the new API, which has a slightly more robust interface, to shed some light on your problem. You can get the new API interface with:
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
Then you'll just need to tweak your class to add an onLocationAvailability callback as per the documentation before attaching your listener:
mFusedLocationClient.requestLocationUpdates(mLocationRequest,
mLocationCallback,
null /* Looper */);

Hidden fragment to isolate code

My question is how custom it is to isolate certain functionality required by an activity into a hidden fragment, in this case Location Services.
My initial thought was to pass the boilerplate callbacks that are related to Location Services into a separate plain Java utility class, and only keep the listener for onLocationChangedin the Activity. This would be much cleaner.
The problem is that this results in circular dependencies, because the pojo would require a reference to the activity context for certain calls, and the Activity would have a reference to the utility class resulting in a circular dependency, which results in tight coupling.
Therefore my thought was to make a hidden fragment and store the code there; this would keep the code in the main activity clean.
What is the usual way to do this?
The current code that I use:
public class HomeActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, com.google.android.gms.location.LocationListener{
private static final String TAG = "HOME_ACTIVITY"; // Logging
private GoogleApiClient mGoogleApiClient;
private Location mLocation;
private LocationManager mLocationManager;
private LocationRequest mLocationRequest;
private com.google.android.gms.location.LocationListener listener;
private double mLatCurLoc;
private double mLngCurLoc;
private float MIN_DISTANCE = 200.0f;
private long UPDATE_INTERVAL = 2 * 1000; /* 10 secs */
private long FASTEST_INTERVAL = 2000; /* 2 sec */
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mLocationManager = (LocationManager)this.getSystemService(Context.LOCATION_SERVICE);
}
#Override
protected void onResume(){
super.onResume();
}
#Override
public void onBackPressed() {
moveTaskToBack(true);
}
#Override
public void onConnected(Bundle bundle) {
// Android Studio complains that we should check the permissions before getting last location
// However, we have already checked permissions in the previous activity
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
startLocationUpdates();
mLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if(mLocation == null){
startLocationUpdates();
}
if (mLocation != null) {
} else {
Toast.makeText(this, "Location not Detected", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onConnectionSuspended(int i) {
Log.i(TAG, "Connection Suspended");
mGoogleApiClient.connect();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.i(TAG, "Connection failed. Error: " + connectionResult.getErrorCode());
}
#Override
protected void onStart() {
super.onStart();
if (mGoogleApiClient != null) {
mGoogleApiClient.connect();
}
}
#Override
protected void onStop() {
super.onStop();
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
protected void startLocationUpdates() {
// Create the location request
mLocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(UPDATE_INTERVAL)
.setSmallestDisplacement(MIN_DISTANCE)
.setFastestInterval(FASTEST_INTERVAL);
// Request location updates
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,
mLocationRequest, this);
}
#Override
public void onLocationChanged(Location location) {
mLatCurLoc = location.getLatitude();
mLngCurLoc = location.getLongitude();
String msg = "Updated Location: " +
Double.toString(location.getLatitude()) + "," +
Double.toString(location.getLongitude());
Log.i("LOCATION_CHANGED", msg);
}
}
I think that's the beauty of inheritance in OOP. You'd just have an activity which will deal with location services, and make your other activities who want to deal with locations extend e.g. LocationAwareActivity. The moment one of those activities is not interested in locations you'd just change the parent class, and vice versa, the moment one of your activities would like to be aware of locations - it will extend LocationAwareActivity.

Google api is not connected in onConnected method

I am working on a new open source library, called Galileo, that helps developers using location api from Google in a single line.
However, when I resume my app, in OnConnected I get the exception that the client is not yet connected. The problem is, that using their methods, everything works fine, but I can't get to work my implementation. Here is what I got so far:
Galileo.java:
public class Galileo {
static volatile Galileo singleton;
private GoogleApiClient mGoogleApiClient;
private LocationManager locationManager;
private LocationListener locationListener;
Galileo (GoogleApiClient mGoogleApiClient, LocationListener locationListener){
this.mGoogleApiClient = mGoogleApiClient;
this.locationListener = locationListener;
}
public static Galileo with(#NonNull GoogleApiClient mGoogleApiClient, #NonNull LocationListener locationListener ) {
if (mGoogleApiClient == null || locationListener==null) {
throw new IllegalArgumentException("context == null");
}
if (singleton == null) {
synchronized (Galileo.class) {
if (singleton == null) {
singleton = new Builder(mGoogleApiClient, locationListener).build();
}
}
}
return singleton;
}
public LocationRequest load(){
return new LocationRequest(this);
}
LocationListener getLocationListener(){
return this.locationListener;
}
GoogleApiClient getmGoogleApiClient(){
return this.mGoogleApiClient;
}
public static class Builder {
private final GoogleApiClient mGoogleApiClient;
private final LocationListener locationListener;
public Builder(#NonNull GoogleApiClient mGoogleApiClient, #NonNull LocationListener locationListener) {
if (mGoogleApiClient == null || locationListener == null) {
throw new IllegalArgumentException("Context must not be null.");
}
this.mGoogleApiClient = mGoogleApiClient;
this.locationListener = locationListener;
}
/**
* Toggle whether debug logging is enabled.
* <p>
* <b>WARNING:</b> Enabling this will result in excessive object allocation. This should be only
* be used for debugging purposes. Do NOT pass {#code BuildConfig.DEBUG}.
*/
public Galileo build() {
GoogleApiClient mGoogleApiClient = this.mGoogleApiClient;
LocationListener locationListener = this.locationListener;
return new Galileo(mGoogleApiClient, locationListener);
}
}
}
LocationRequest.java:
public class LocationRequest {
private LocationListener locationListener;
private GoogleApiClient mGoogleApiClient;
private float mDistance;
private int mTime;
private int priority;
private boolean askForGPS;
private com.google.android.gms.location.LocationRequest mLocationRequest;
LocationRequest(Galileo galileo) {
this.mGoogleApiClient = galileo.getmGoogleApiClient();
this.locationListener = galileo.getLocationListener();
this.mTime = 10000;
this.priority = com.google.android.gms.location.LocationRequest.PRIORITY_HIGH_ACCURACY;
this.askForGPS = false;
}
public LocationRequest time(int mTime){
this.mTime = mTime;
return this;
}
public LocationRequest distance(float mDistance){
this.mDistance = mDistance;
return this;
}
public void go(){
createLocationRequest();
startLocationUpdates();
}
public void stop(){
stopLocationUpdates();
}
protected void stopLocationUpdates() {
// It is a good practice to remove location requests when the activity is in a paused or
// stopped state. Doing so helps battery performance and is especially
// recommended in applications that request frequent location updates.
// The final argument to {#code requestLocationUpdates()} is a LocationListener
// (http://developer.android.com/reference/com/google/android/gms/location/LocationListener.html).
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, locationListener);
}
protected void startLocationUpdates() {
// The final argument to {#code requestLocationUpdates()} is a LocationListener
// (http://developer.android.com/reference/com/google/android/gms/location/LocationListener.html).
System.out.print(mGoogleApiClient.isConnected());
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest , locationListener);
}
protected void createLocationRequest() {
mLocationRequest = new com.google.android.gms.location.LocationRequest();
// Sets the desired interval for active location updates. This interval is
// inexact. You may not receive updates at all if no location sources are available, or
// you may receive them slower than requested. You may also receive updates faster than
// requested if other applications are requesting location at a faster interval.
mLocationRequest.setInterval(mTime);
// Sets the fastest rate for active location updates. This interval is exact, and your
// application will never receive updates faster than this value.
mLocationRequest.setFastestInterval(mTime/2);
mLocationRequest.setPriority(priority);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(mLocationRequest);
builder.setAlwaysShow(true);
PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
#Override
public void onResult(#NonNull LocationSettingsResult result) {
final Status status = result.getStatus();
final LocationSettingsStates state = result.getLocationSettingsStates();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
// All location settings are satisfied. The client can initialize location
// requests here.
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
// Location settings are not satisfied. But could be fixed by showing the user
// a dialog.
/*try {
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
//status.startResolutionForResult(MapsActivity.this, 1000);
} catch (IntentSender.SendIntentException e) {
// Ignore the error.
}*/
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
// Location settings are not satisfied. However, we have no way to fix the
// settings so we won't show the dialog.
break;
}
}
});
}
}
and MapsActivity.java:
protected synchronized void buildGoogleApiClient() {
Log.i(TAG, "Building GoogleApiClient");
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
//createLocationRequest();
}
protected void stopLocationUpdates() {
// It is a good practice to remove location requests when the activity is in a paused or
// stopped state. Doing so helps battery performance and is especially
// recommended in applications that request frequent location updates.
// The final argument to {#code requestLocationUpdates()} is a LocationListener
// (http://developer.android.com/reference/com/google/android/gms/location/LocationListener.html).
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
protected void startLocationUpdates() {
// The final argument to {#code requestLocationUpdates()} is a LocationListener
// (http://developer.android.com/reference/com/google/android/gms/location/LocationListener.html).
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
// Sets the desired interval for active location updates. This interval is
// inexact. You may not receive updates at all if no location sources are available, or
// you may receive them slower than requested. You may also receive updates faster than
// requested if other applications are requesting location at a faster interval.
mLocationRequest.setInterval(10000);
// Sets the fastest rate for active location updates. This interval is exact, and your
// application will never receive updates faster than this value.
mLocationRequest.setFastestInterval(5000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(mLocationRequest);
builder.setAlwaysShow(true);
PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
#Override
public void onResult(#NonNull LocationSettingsResult result) {
final Status status = result.getStatus();
final LocationSettingsStates state = result.getLocationSettingsStates();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
// All location settings are satisfied. The client can initialize location
// requests here.
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
// Location settings are not satisfied. But could be fixed by showing the user
// a dialog.
try {
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
status.startResolutionForResult(
MapsActivity.this, 1000);
} catch (IntentSender.SendIntentException e) {
// Ignore the error.
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
// Location settings are not satisfied. However, we have no way to fix the
// settings so we won't show the dialog.
break;
}
}
});
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(48.162253, 17.0463122), 15));
MarkerOptions marker = new MarkerOptions().position(new LatLng(48.162253, 17.0463122)).title("Hello Maps ");
mMap.addMarker(marker);
mMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
#Override
public boolean onMarkerClick(Marker marker) {
behavior.setState(BottomSheetBehaviorGoogleMapsLike.STATE_COLLAPSED);
String imageURL = "https://maps.googleapis.com/maps/api/streetview?size=400x400&location="+String.valueOf(marker.getPosition().latitude)+","+String.valueOf(marker.getPosition().longitude);
Picasso.with(MapsActivity.this).load(imageURL).into(imageView);
bottomSheetTextView.setText(marker.getTitle());
currentMarker = marker;
Geocoder geocoder;
List<Address> addresses;
String address;
geocoder = new Geocoder(MapsActivity.this, Locale.getDefault());
try {
addresses = geocoder.getFromLocation(marker.getPosition().latitude, marker.getPosition().longitude, 1); // Here 1 represent max location result to returned, by documents it recommended 1 to 5
address = addresses.get(0).getAddressLine(0);
} catch (IOException e) {
address = "";
e.printStackTrace();
}
addressView.setText(address);
return false;
}
});
mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
#Override
public void onMapClick(LatLng latLng) {
if (behavior.getState() == BottomSheetBehaviorGoogleMapsLike.STATE_COLLAPSED) {
behavior.setState(BottomSheetBehaviorGoogleMapsLike.STATE_HIDDEN);
}
currentMarker = null;
}
});
mMap.setOnMapLongClickListener(new GoogleMap.OnMapLongClickListener() {
#Override
public void onMapLongClick(LatLng latLng) {
MarkerOptions marker = new MarkerOptions().position(latLng).title("Hello Maps ");
mMap.addMarker(marker);
}
});
}
#Override
protected void onStart() {
super.onStart();
String[] LOCATION_PERMISSIONS = {Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION};
Permission.PermissionBuilder permissionBuilder =
new Permission.PermissionBuilder(LOCATION_PERMISSIONS, 1000, new Permission.PermissionCallback() {
#Override
public void onPermissionGranted(int i) {
buildGoogleApiClient();
mGoogleApiClient.connect();
}
#Override
public void onPermissionDenied(int i) {
}
#Override
public void onPermissionAccessRemoved(int i) {
}
});
requestAppPermissions(permissionBuilder.build());
}
#Override
public void onResume() {
super.onResume();
// Within {#code onPause()}, we pause location updates, but leave the
// connection to GoogleApiClient intact. Here, we resume receiving
// location updates if the user has requested them.
if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
Galileo.with(mGoogleApiClient,this).load().go();
}
}
#Override
protected void onPause() {
super.onPause();
// Stop location updates to save battery, but don't disconnect the GoogleApiClient object.
if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
Galileo.with(mGoogleApiClient,this).load().stop();
}
}
#Override
protected void onStop() {
if (mGoogleApiClient != null) {
mGoogleApiClient.disconnect();
}
super.onStop();
}
#Override
public void onConnected(#Nullable Bundle bundle) {
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if(mLastLocation!=null){
Log.d("Lat, lon", String.valueOf(mLastLocation.getLatitude()) + " ," + String.valueOf(mLastLocation.getLongitude()));
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(mLastLocation.getLatitude(), mLastLocation.getLongitude()), 15));
}
//Log.d(TAG, String.valueOf(mGoogleApiClient.isConnected()));
if(mGoogleApiClient.isConnected()){
Galileo.with(mGoogleApiClient,this).load().go();}
}
#Override
public void onConnectionSuspended(int i) {
Log.i(TAG, "Connection suspended");
mGoogleApiClient.connect();
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = " + connectionResult.getErrorCode());
}
#Override
public void onLocationChanged(Location location) {
if(mLastLocation==null){
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location.getLatitude(), location.getLongitude()), 15));
}
mLastLocation = location;
Log.d("Lat, lon", String.valueOf(mLastLocation.getLatitude()) + " ," + String.valueOf(mLastLocation.getLongitude()));
//mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(mLastLocation.getLatitude(), mLastLocation.getLongitude()), 15));
}

Waiting until location is on after turning it on through location services alert

I am having a problem where if my phone's location services is turned off, I want to set an alert to open the location services settings and turn it on there. This works fine but the issue is when I navigate back to my application after turning it on. It seems like when I click back, the onResume of my activity is called but the location is still not set correctly there until onResume is completed. Here is my code:
Comments.java:
#Override
public void onResume() {
super.onResume();
locationManager = (LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE);
Location location = LocationService.getLastLocation();
if(location == null) {
if(getLastKnownLocation() == null) {
if(checkLocationEnabled()); {
location = getLastKnownLocation();
}
}
}
if(location != null) {
progressOverlay = fragmentView.findViewById(R.id.progress_overlay);
AndroidUtils.animateView(progressOverlay, View.VISIBLE, 0.9f, 200);
//Within this function call, the progress overlay is set to View.GONE.
databaseQuery.getPublicPosts(location, progressOverlay, fragmentView, getContext());
} else {
//We need to handle an error saying that location is not enabled for this device and exit them out of the app
}
}
private Location getLastKnownLocation() {
locationManager = (LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE);
List<String> providers = locationManager.getProviders(true);
Location bestLocation = null;
for (String provider : providers) {
if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return null;
} else {
Location l = locationManager.getLastKnownLocation(provider);
if (bestLocation == null || l.getAccuracy() < bestLocation.getAccuracy()) {
// Found best last known location: %s", l);
bestLocation = l;
}
}
}
return bestLocation;
}
public boolean checkLocationEnabled() {
try {
gps_enabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch(Exception ex) {
}
try {
network_enabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} catch(Exception ex) {
}
if(!gps_enabled && !network_enabled) {
// notify user
AlertDialog.Builder dialog = new AlertDialog.Builder(getContext());
dialog.setMessage(getContext().getResources().getString(R.string.gpsNetworkNotEnabled));
dialog.setPositiveButton(getContext().getResources().getString(R.string.openLocationSettings), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface paramDialogInterface, int paramInt) {
Intent myIntent = new Intent( Settings.ACTION_LOCATION_SOURCE_SETTINGS);
getContext().startActivity(myIntent);
//get gps
}
});
dialog.setNegativeButton(getContext().getString(R.string.cancel), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface paramDialogInterface, int paramInt) {
}
});
dialog.show();
}
return gps_enabled || network_enabled;
}
What I do is when the phone location services is off, I set up an alert that takes you to the location services screen. When the user turns on the location services screen, if he or she clicks "back" on his or her phone, they should be taken back to the initial screen that showed that their location services was off alert. However, when navigating back to that screen, my progressOverlay variable is still visible because the progressOverlay is set to View.GONE when the databaseQuery.getPublicPosts call goes through. That doesn't seem to happen because the if(location != null) statement is probably false right when we navigate back to the screen, but is probably set to true after the phone waits a few seconds and fully obtains the phone's location. It's interesting because if I put a debugger anywhere in that code, the location services will be set correctly and my progressOverlay will go away because the location gets set while I am debugging the code. Is there any way I can "wait" or continue to show the loading screen until the location services is fully on before calling databaseQuery.getPublicPosts? Any help would be appreciated.
hi why trying to use getLastKnownLocation.It return your previous latitude and longitude and it might take some time to update lastknown location.
Most probably it retrun you null after on your location.
I'm just referring you google Fused api for location any kind of updation or current.Its very accurate.
How you can fused api in your project.See i'll give you small example.
Step 1. Make this class GoogleLocationService.java
public class GoogleLocationService {
private GoogleServicesCallbacks callbacks = new GoogleServicesCallbacks();
LocationUpdateListener locationUpdateListener;
Context activity;
protected GoogleApiClient mGoogleApiClient;
protected LocationRequest mLocationRequest;
public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 30000;
public GoogleLocationService(Context activity, LocationUpdateListener locationUpdateListener) {
this.locationUpdateListener = locationUpdateListener;
this.activity = activity;
buildGoogleApiClient();
}
protected synchronized void buildGoogleApiClient() {
//Log.i(TAG, "Building GoogleApiClient");
mGoogleApiClient = new GoogleApiClient.Builder(activity)
.addConnectionCallbacks(callbacks)
.addOnConnectionFailedListener(callbacks)
.addApi(LocationServices.API)
.build();
createLocationRequest();
mGoogleApiClient.connect();
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
private class GoogleServicesCallbacks implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
#Override
public void onConnected(Bundle bundle) {
startLocationUpdates();
}
#Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
if (connectionResult.getErrorCode() == ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED) {
Toast.makeText(activity, "Google play service not updated", Toast.LENGTH_LONG).show();
}
locationUpdateListener.cannotReceiveLocationUpdates();
}
#Override
public void onLocationChanged(Location location) {
if (location.hasAccuracy()) {
if (location.getAccuracy() < 30) {
locationUpdateListener.updateLocation(location);
}
}
}
}
private static boolean locationEnabled(Context context) {
boolean gps_enabled = false;
LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
try {
gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch (Exception ex) {
ex.printStackTrace();
}
return gps_enabled;
}
private boolean servicesConnected(Context context) {
return isPackageInstalled(GooglePlayServicesUtil.GOOGLE_PLAY_STORE_PACKAGE, context);
}
private boolean isPackageInstalled(String packagename, Context context) {
PackageManager pm = context.getPackageManager();
try {
pm.getPackageInfo(packagename, PackageManager.GET_ACTIVITIES);
return true;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return false;
}
}
public void startUpdates() {
/*
* Connect the client. Don't re-start any requests here; instead, wait
* for onResume()
*/
if (servicesConnected(activity)) {
if (locationEnabled(activity)) {
locationUpdateListener.canReceiveLocationUpdates();
startLocationUpdates();
} else {
locationUpdateListener.cannotReceiveLocationUpdates();
Toast.makeText(activity, "Unable to get your location.Please turn on your device Gps", Toast.LENGTH_LONG).show();
}
} else {
locationUpdateListener.cannotReceiveLocationUpdates();
Toast.makeText(activity, "Google play service not available", Toast.LENGTH_LONG).show();
}
}
//stop location updates
public void stopUpdates() {
stopLocationUpdates();
}
//start location updates
private void startLocationUpdates() {
if (checkSelfPermission(activity, ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && checkSelfPermission(activity, ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, callbacks);
}
}
public void stopLocationUpdates() {
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, callbacks);
}
}
public void startGoogleApi() {
mGoogleApiClient.connect();
}
public void closeGoogleApi() {
mGoogleApiClient.disconnect();
}
}
Step2. Make this interface
LocationUpdateListener.java
public interface LocationUpdateListener {
/**
* Called immediately the service starts if the service can obtain location
*/
void canReceiveLocationUpdates();
/**
* Called immediately the service tries to start if it cannot obtain location - eg the user has disabled wireless and
*/
void cannotReceiveLocationUpdates();
/**
* Called whenever the location has changed (at least non-trivially)
* #param location
*/
void updateLocation(Location location);
/**
* Called when GoogleLocationServices detects that the device has moved to a new location.
* #param localityName The name of the locality (somewhere below street but above area).
*/
void updateLocationName(String localityName, Location location);
}
Step 3. Use this piece of code where you want to get location
public class MainActivity extends ActionBarActivity {
private GoogleLocationService googleLocationService;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
googleLocationService = new GoogleLocationService(context, new LocationUpdateListener() {
#Override
public void canReceiveLocationUpdates() {
}
#Override
public void cannotReceiveLocationUpdates() {
}
//update location to our servers for tracking purpose
#Override
public void updateLocation(Location location) {
if (location != null ) {
Timber.e("updated location %1$s %2$s", location.getLatitude(), location.getLongitude());
}
}
#Override
public void updateLocationName(String localityName, Location location) {
googleLocationService.stopLocationUpdates();
}
});
googleLocationService.startUpdates();
}
#Override
public void onDestroy() {
super.onDestroy();
if (googleLocationService != null) {
googleLocationService.stopLocationUpdates();
}
}
}
Updated answer
how to send and receive lat lng through broadcast
call this onlocationchanged
Intent sendBroadIntentPND = new Intent("COORD_BROADCAST_FILTER");
sendBroadIntentPND.putExtra("LOC_LAT", location.getLatitude());
sendBroadIntentPND.putExtra("LOC_LON", location.getLongitude());
getApplicationContext().sendBroadcast(sendBroadIntentPND);
then where you want to receive the location call this way
// declear global variable
private final String COORD_BROADCAST_FILTER = "COORD_BROADCAST_FILTER";
private Location newLocation;
private BroadcastReceiver coordinateReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
try {
newLocation.setLatitude(intent.getDoubleExtra("LOC_LAT", 0.0));
newLocation.setLongitude(intent.getDoubleExtra("LOC_LON", 0.0));
} catch (Exception e) {
e.printStackTrace();
}
}
};
Register you receiver oncreate,
getActivity().registerReceiver(coordinateReceiver, new IntentFilter(COORD_BROADCAST_FILTER));
unregister your receiver ondestroy
getActivity().unregisterReceiver(coordinateReceiver);
Thanks hope this help you.
First you have an unwanted semi-colon in if(checkLocationEnabled()); which acts as an empty statement causing the second call to getLastKnownLocation() to always execute (this will most probably not affect the problem).
The LocationManager class has a constant KEY_STATUS_CHANGED that is the key of a bundle extra that is passed when a status change is broadcast. See the documentation related to the constant. To trigger this change you need to call [LocationManager.requestLocationUpdates](https://developer.android.com/reference/android/location/LocationManager.html#requestLocationUpdates(long, float, android.location.Criteria, android.app.PendingIntent)) so that the location manager receives such a status update.
From the documentation of this method, you can either use a BroadcastReceiver to receive the update by filtering on the above constant. Here is a related post that does this. Or you can use another overloaded version of the request updates method that takes a LocationListener which has an onStatusChanged callback.
A similar update exists when a location provider is enabled, with the KEY_PROVIDER_ENABLED. You can try listening for both updates if the status update didn't work.
Note that when requesting location updates for providers, in order to include updates for all providers including disabled ones, you should retrieve them using LocationManager.getProviders(false).
Once you receive the appropriate update events, you can call removeUpdates to remove the update requests.
Please take note that
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.

FusedLocationProviderAPI always returns null when trying to get current location

For countless hours, I have been trying to get the user's current location upon launching my app, but then every approach I have tried has returned null.
My instantiation of the GoogleApiClient takes place in "onCreate"
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EventBus.getDefault().register(this);
FirebaseMessagingHelper.registerDevice(this, FirebaseInstanceId.getInstance().getToken());
activity = this;
//xaxaxa
driverMapView = (MapView) findViewById(R.id.googleMapObject);
driverMapView.onCreate(savedInstanceState);
driverMapView.getMapAsync(this);
getUserToEnableCameraUsage();
if (googleApiClient == null)
{
googleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
googleApiClient.connect();
Here is the code in my project (extremely similar to the code provided in the api's tutorial:
#Override
public void onConnected(#Nullable Bundle bundle)
{
int LOCATION_ALLOWED = ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION);
if (LOCATION_ALLOWED != PackageManager.PERMISSION_GRANTED)
{
lastLocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
if (lastLocation != null)
{
driverGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(lastLocation.getLatitude(), lastLocation.getLongitude()), 16));
testHelper.setDriverLatLngLocation(new LatLng(lastLocation.getLatitude(), lastLocation.getLongitude()));
}
}
}
protected void createLocationRequest()
{
locationRequest = new LocationRequest();
locationRequest.setInterval(1000);
locationRequest.setFastestInterval(500);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationSettingsRequest.Builder locationSettingsRequestBuilder = new LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest);
PendingResult<LocationSettingsResult> pendingResult = LocationServices
.SettingsApi
.checkLocationSettings(googleApiClient, locationSettingsRequestBuilder.build());
pendingResult.setResultCallback(new ResultCallback<LocationSettingsResult>() {
#Override
public void onResult(#NonNull LocationSettingsResult locationSettingsResult)
{
Status result = locationSettingsResult.getStatus();
if (result.getStatusCode() == LocationSettingsStatusCodes.SUCCESS)
{
requestingLocationUpdates = true;
startLocationUpdates();
Toast.makeText(MainActivity.this, "Gucci", Toast.LENGTH_SHORT).show();
}
if (result.getStatusCode() == LocationSettingsStatusCodes.RESOLUTION_REQUIRED)
{
requestingLocationUpdates = false;
Toast.makeText(MainActivity.this, "Please enable location services", Toast.LENGTH_SHORT).show();
}
if (result.getStatusCode() == LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE)
{
requestingLocationUpdates = false;
Toast.makeText(MainActivity.this, "App cannot access settings", Toast.LENGTH_SHORT).show();
}
}
});
}
protected void startLocationUpdates()
{
int LOCATION_ALLOWED = ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION);
if (LOCATION_ALLOWED != PackageManager.PERMISSION_GRANTED)
{
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult)
{
}
#Override
public void onLocationChanged(Location location)
{
driverGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location.getLatitude(), location.getLongitude()), 16));
testHelper.setDriverLatLngLocation(new LatLng(location.getLatitude(), location.getLongitude()));
Toast.makeText(MainActivity.this, "It's working", Toast.LENGTH_SHORT).show();
}
protected void stopLocationUpdates()
{
LocationServices.FusedLocationApi.removeLocationUpdates(
googleApiClient, this);
requestingLocationUpdates = false;
}
I instantiate "createLocationRequest here:
public void onMapReady(GoogleMap googleMap)
{
//Setting map starts here
int LOCATION_ALLOWED = ContextCompat.checkSelfPermission(this.getApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION);
if (LOCATION_ALLOWED == PackageManager.PERMISSION_GRANTED)
{
googleMap.setMyLocationEnabled(true);
}
createLocationRequest();
The instantiation of "createLocationRequest()" takes place before the block of code that needs it and it is null?
I have looked over multiple solutions, but they've all not helped me. I was hoping that maybe someone could help me out as this has been really bothering me and has halted the development of my app.

Categories

Resources