2

I want to fetch user's current city name in my Android application but as per some of my research (this, this, and this) it is a pretty complicated task and require switching between network providers and fetch location updates after some time.

My application is not some location-based app to require an accurate and up-to-date location of a user using the app. I just need a city name from NETWORK_PROVIDER (or any other provider for that matter) but if it is unable to fetch the city name, that's fine, too. It's just one feature in the application and doesn't matter if it fails to fetch the city name in some cases.

I'm using following code but it always shows both latitude and longitude to be 0.0.

Location location = new Location(LocationManager.NETWORK_PROVIDER);
Geocoder geocoder = new Geocoder(context, Locale.getDefault());
try {
    Log.d("Lat-Lng", location.getLatitude()+","+location.getLongitude());
    // Doesn't really return anything as both latitude and longitude is 0.0.
    List<Address> address = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1);
} catch(Exception e) {

}
Community
  • 1
  • 1
Basit
  • 1,830
  • 2
  • 31
  • 50

1 Answers1

2

Well all you are doing here is creating a new Location object whose initial values for latitude and longitude are zero by default.

What you need to do is connect that location to the GPS information of the user.

// Getting LocationManager object from System Service LOCATION_SERVICE
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

// Creating a criteria object to retrieve provider
Criteria criteria = new Criteria();

// Getting the name of the best provider
String provider = locationManager.getBestProvider(criteria, true);

// Getting Current Location From GPS
Location location = locationManager.getLastKnownLocation(provider);

if(location != null) {
    Log.d("Lat-Lng", location.getLatitude()+","+location.getLongitude());
    getUserGeoInfo(location.getLatitude(), location.getLongitude());
}

// Define a listener that responds to location updates
LocationListener locationListener = new LocationListener() {

    public void onLocationChanged(Location location) {
        // Called when a new location is found by the network location provider.
        Log.d("Lat-Lng", location.getLatitude()+","+location.getLongitude());
        getUserGeoInfo(location.getLatitude(), location.getLongitude());  
    }

    public void onStatusChanged(String provider, int status, Bundle extras) {}

    public void onProviderEnabled(String provider) {}

    public void onProviderDisabled(String provider) {}
};

// Set how often you want to request location updates and where you want to receive them
locationManager.requestLocationUpdates(provider, 20000, 0, locationListener);

// ...

void getUserGeoInfo(double lat, double lon) {
    Geocoder geoCoder = new Geocoder(context, Locale.getDefault());
    if (Geocoder.isPresent()) {
        List<Address> addresses = geoCoder.getFromLocation(lat, lon, 1);
        if (addresses.size() > 0) {
            // obtain all information from addresses.get(0)
        }
    }
}

The LocationListener interface can, for example, also be implemented by the Activity that holds this code and then you would only pass that activity's context as the third parameter in locationManager.requestLocationUpdates(provider, 20000, 0, context);. Of course, as with any interface implementation, you will have to override all the methods same way as in above code.

As far as the requestLocationUpdates() method, you can read more about it here

As far as general techniques for obtaining user location on Android, this is a definite read

nem035
  • 34,790
  • 6
  • 87
  • 99
  • Sounds simple enough. How do I implement `YOUR_LOCATION_LISTENER`? – Basit Sep 21 '14 at 05:11
  • well, let's say you have an `Activity` declared as `class LocationActivity extends Activity` that contains all of this code. Just put `LocationActivity extends Activity implements LocationListener` and you will have access to `onLocationChanged` method. This means that in the `requestLocationUpdates` method, third parameter would be `this`. Read more about this method on the link I provided, it has a lot to it – nem035 Sep 21 '14 at 05:13
  • @BasitSaeed please read this link. http://developer.android.com/reference/android/location/LocationListener.html – SilentKiller Sep 21 '14 at 05:14
  • @nem Can I create a separate `class` and use the code inside a function and return it to an activity? I'd just have to `implement` `LocationListener` in that `class`, right? – Basit Sep 21 '14 at 05:21
  • 1
    Yessir. Keep in mind though, my answer only shows you one way out of many to achieve this. Check out the google documentation for android about these methods and interfaces to see all the options you have. – nem035 Sep 21 '14 at 05:24
  • @nem Yes, I gave it a read and it made it work. Thank you again! – Basit Sep 21 '14 at 05:48
  • @nem Just a question: what if I don't want to receive periodic location updates? I just want it one-time in an AsyncTask after I load a specific activity. How can I achieve that? Appreciate your help. – Basit Sep 21 '14 at 06:32
  • well than you can use the last know location obtained from `locationManager.getLastKnownLocation(provider)` and don't type this part `locationManager.requestLocationUpdates(provider, 20000, 0, locationListener)` and also delete the `LocationListener`. If for whatever reason `getLastKnownLocation` returns `null`, then you would have to use the `LocationListener` once and store that information. Then call `locationManager.removeUpdates(locationListener)` to remove the listener you previously added – nem035 Sep 21 '14 at 06:39
  • @nem Can you please add it to the answer? I'm kind of new to Android world and have already spent countless hours on this problem. THank you :) – Basit Sep 21 '14 at 07:10