简体   繁体   中英

Unable to get location using Google's fused location API

I am trying to get my location using Google's fused location API.For this I have created two classes. One is MainActivity and second is FusedLocationService in which MainActivity is the main class . But I am getting longitude and latitude as 0.0. So please help me.

Here is my code of MainActivity:-

public class MainActivity extends AppCompatActivity {

TextView tvLocation;
FusedLocationService fusedLocationService;
double latitude;
double longitude;

String locationResult = "";
Location location;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    tvLocation = (TextView) findViewById(R.id.tvLocation);
    fusedLocationService = new FusedLocationService(this);
    location = fusedLocationService.getLocation();

    if (null != location) {
        latitude = location.getLatitude();
        longitude = location.getLongitude();
        locationResult = "Latitude: " + latitude + "\n" +
                "Longitude: " + longitude + "\n";
    } else {
        Timber.e("-error-%s", "Location Not Available!");
        locationResult = "Location Not Available!";
    }

    Log.e("Lati ", String.valueOf(latitude));
    Log.e("longi ", String.valueOf(longitude));
    tvLocation.setText(locationResult);
   }
 }

Here is my FusedLocationService class:-

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

private static final long INTERVAL = 1000 * 30; //30sec
private static final long FASTEST_INTERVAL = 1000 * 5; // 5sec

Activity mActivity;
public LocationRequest locationRequest;
public GoogleApiClient googleApiClient;
public Location location;
public FusedLocationProviderApi fusedLocationProviderApi = LocationServices.FusedLocationApi;

public FusedLocationService(Activity activity) {

    Timber.plant(new Timber.DebugTree());
    locationRequest = LocationRequest.create();
    locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    locationRequest.setInterval(INTERVAL);
    locationRequest.setFastestInterval(FASTEST_INTERVAL);
    mActivity = activity;
    googleApiClient = new GoogleApiClient.Builder(mActivity)
            .addApi(LocationServices.API)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .build();

    if (googleApiClient != null) {
        googleApiClient.connect();
    }

}

@Override
public void onConnected(Bundle connectionHint) {
    Log.e("-onConnected-", "connected now");
    location = fusedLocationProviderApi.getLastLocation(googleApiClient);
    fusedLocationProviderApi.requestLocationUpdates(googleApiClient, locationRequest, this);
}

@Override
public void onLocationChanged(Location location) {
}

public Location getLocation() {
    return location;
}

@Override
public void onConnectionSuspended(int i) {
}

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
  }
}

I have included permissions in the manifests and lib in the gradle folder. So please help. Thank you in advance

A reference to the new location is missing:

@Override
public void onLocationChanged(Location location) {
    this.location = location;
}

Also the location updates are asynchronously . So you need something like a callback to the activity.

edit:

also check if Google Play Services is available. You can create a method like this:

public boolean checkPlayServices() {
   return GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context) == ConnectionResult.SUCCESS;
}

See Google documentation

Short explanation

your are getting default values of your global latitude and longitude variables

double latitude;
double longitude;

Long explanation

When you instantiate FusedLocationService class

fusedLocationService = new FusedLocationService(this);

It builds google api client then attempts to connect

public FusedLocationService(Activity activity) {
    ...
    googleApiClient = new GoogleApiClient.Builder(mActivity)
        .addApi(LocationServices.API)
        .addConnectionCallbacks(this)
        .addOnConnectionFailedListener(this)
        .build();

    if (googleApiClient != null) {
        googleApiClient.connect();
    }
}

And after successfully connection, making location request

@Override
public void onConnected(Bundle connectionHint) {
    Log.e("-onConnected-", "connected now");
    location = fusedLocationProviderApi.getLastLocation(googleApiClient);
    fusedLocationProviderApi.requestLocationUpdates(googleApiClient, locationRequest, this);
}

Connecting google api, and receiving locations are asynchronous operations.

It means, you must tend to their callbacks

But your are using the latitude longitude variables after initializing FusedLocationService class. So this is why you getting 0.0 as latitude and longitude.

Log.e("Lati ", String.valueOf(latitude));
Log.e("longi ", String.valueOf(longitude));
tvLocation.setText(locationResult);

EDIT -- Finishing touches

Firstly, you could remove or move these code. You are dealing with asynchronous operations.

Log.e("Lati ", String.valueOf(latitude));
Log.e("longi ", String.valueOf(longitude));
tvLocation.setText(locationResult);

When google api connected, check the previously received location and update your ui if any

@Override
public void onConnected(Bundle connectionHint) {
    ...
    Location location = fusedLocationProviderApi.getLastLocation(googleApiClient);
    // Provider could return null, because it tries to get location if any 
    if(location != null){
        // UPDATE YOUR UI
    }
    fusedLocationProviderApi.requestLocationUpdates(googleApiClient, locationRequest, this);
}

When received new location, update you ui

@Override
public void onLocationChanged(Location location) {
    // You have received fresh location
    // UPDATE YOUR UI
}

Also check this link , you'll better understand the aspects that i mentioned.

I have created a class named LocationActivity

public class LocationActivitity extends AppCompatActivity
            implements LocationListener,
            GoogleApiClient.ConnectionCallbacks,
            GoogleApiClient.OnConnectionFailedListener {

        final String TAG = "GPS";
        private long UPDATE_INTERVAL = 2 * 1000;  /* 10 secs */
        private long FASTEST_INTERVAL = 2000; /* 2 sec */
        static final int MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 1;

        GoogleApiClient gac;
        LocationRequest locationRequest;
        public String tvLatitude, tvLongitude, tvTime;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            isGooglePlayServicesAvailable();

            if(!isLocationEnabled())
                showAlert();

            locationRequest = new LocationRequest();
            locationRequest.setInterval(UPDATE_INTERVAL);
            locationRequest.setFastestInterval(FASTEST_INTERVAL);
            locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
            gac = new GoogleApiClient.Builder(this)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .addApi(LocationServices.API)
                    .build();
        }

        @Override
        protected void onStart() {
            gac.connect();
            super.onStart();
        }

        @Override
        protected void onStop() {
            gac.disconnect();
            super.onStop();
        }

        @Override
        public void onLocationChanged(Location location) {
            if (location != null) {
                updateUI(location);
            }
        }

        @Override
        public void onConnected(@Nullable Bundle bundle) {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
                    != PackageManager.PERMISSION_GRANTED
                    && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
                    != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                        MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);

                return;
            }
            Log.d(TAG, "onConnected");

            Location ll = LocationServices.FusedLocationApi.getLastLocation(gac);
            Log.d(TAG, "LastLocation: " + (ll == null ? "NO LastLocation" : ll.toString()));

            LocationServices.FusedLocationApi.requestLocationUpdates(gac, locationRequest, this);
        }

        @Override
        public void onRequestPermissionsResult(
                int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

            switch (requestCode) {
                case MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION: {
                    // If request is cancelled, the result arrays are empty.
                    if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                        Toast.makeText(this, "Permission was granted!", Toast.LENGTH_LONG).show();

                        try{
                            LocationServices.FusedLocationApi.requestLocationUpdates(
                                    gac, locationRequest, this);
                        } catch (SecurityException e) {
                            Toast.makeText(this, "SecurityException:\n" + e.toString(), Toast.LENGTH_LONG).show();
                        }
                    } else {
                        Toast.makeText(this, "Permission denied!", Toast.LENGTH_LONG).show();
                    }
                    return;
                }
            }
        }

        @Override
        public void onConnectionSuspended(int i) {}

        @Override
        public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
            Toast.makeText(this, "onConnectionFailed: \n" + connectionResult.toString(),
                    Toast.LENGTH_LONG).show();
            Log.d("DDD", connectionResult.toString());
        }

        private void updateUI(Location loc) {
            Log.d(TAG, "updateUI");
            tvLatitude=loc.getLatitude()+"";
            tvLongitude=loc.getLongitude()+"";
            //tvTime.setText(DateFormat.getTimeInstance().format(loc.getTime()));
        }

        private boolean isLocationEnabled() {
            LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
            return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) ||
                    locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
        }

        private boolean isGooglePlayServicesAvailable() {
            final int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
            GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
            int resultCode = apiAvailability.isGooglePlayServicesAvailable(this);
            if (resultCode != ConnectionResult.SUCCESS) {
                if (apiAvailability.isUserResolvableError(resultCode)) {
                    apiAvailability.getErrorDialog(this, resultCode, PLAY_SERVICES_RESOLUTION_REQUEST)
                            .show();
                } else {
                    Log.d(TAG, "This device is not supported.");
                    finish();
                }
                return false;
            }
            Log.d(TAG, "This device is supported.");
            return true;
        }

        private void showAlert() {
            final AlertDialog.Builder dialog = new AlertDialog.Builder(this);
            dialog.setTitle("Enable Location")
                    .setMessage("Your Locations Settings is set to 'Off'.\nPlease Enable Location to " +
                            "use this app")
                    .setPositiveButton("Location Settings", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface paramDialogInterface, int paramInt) {

                            Intent myIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                            startActivity(myIntent);
                            finish();
                        }
                    })
                    .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface paramDialogInterface, int paramInt) {
                        }
                    });
            dialog.show();
        }
    }

Here is a method updateUI(Location loc) where you get location.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM