FileDocCategorySizeDatePackage
LocationBasedCountryDetector.javaAPI DocAndroid 5.1 API8616Thu Mar 12 22:22:42 GMT 2015com.android.server.location

LocationBasedCountryDetector

public class LocationBasedCountryDetector extends CountryDetectorBase
This class detects which country the user currently is in through the enabled location providers and the GeoCoder

Use {@link #detectCountry} to start querying. If the location can not be resolved within the given time, the last known location will be used to get the user country through the GeoCoder. The IllegalStateException will be thrown if there is a ongoing query.

The current query can be stopped by {@link #stop()}

hide

Fields Summary
private static final String
TAG
private static final long
QUERY_LOCATION_TIMEOUT
protected Timer
mTimer
Used for canceling location query
protected Thread
mQueryThread
The thread to query the country from the GeoCoder.
protected List
mLocationListeners
private android.location.LocationManager
mLocationManager
private List
mEnabledProviders
Constructors Summary
public LocationBasedCountryDetector(android.content.Context ctx)


       
        super(ctx);
        mLocationManager = (LocationManager) ctx.getSystemService(Context.LOCATION_SERVICE);
    
Methods Summary
public synchronized android.location.CountrydetectCountry()
Start detecting the country.

Queries the location from all location providers, then starts a thread to query the country from GeoCoder.

        if (mLocationListeners  != null) {
            throw new IllegalStateException();
        }
        // Request the location from all enabled providers.
        List<String> enabledProviders = getEnabledProviders();
        int totalProviders = enabledProviders.size();
        if (totalProviders > 0) {
            mLocationListeners = new ArrayList<LocationListener>(totalProviders);
            for (int i = 0; i < totalProviders; i++) {
                String provider = enabledProviders.get(i);
                if (isAcceptableProvider(provider)) {
                    LocationListener listener = new LocationListener () {
                        @Override
                        public void onLocationChanged(Location location) {
                            if (location != null) {
                                LocationBasedCountryDetector.this.stop();
                                queryCountryCode(location);
                            }
                        }
                        @Override
                        public void onProviderDisabled(String provider) {
                        }
                        @Override
                        public void onProviderEnabled(String provider) {
                        }
                        @Override
                        public void onStatusChanged(String provider, int status, Bundle extras) {
                        }
                    };
                    mLocationListeners.add(listener);
                    registerListener(provider, listener);
                }
            }

            mTimer = new Timer();
            mTimer.schedule(new TimerTask() {
                @Override
                public void run() {
                    mTimer = null;
                    LocationBasedCountryDetector.this.stop();
                    // Looks like no provider could provide the location, let's try the last
                    // known location.
                    queryCountryCode(getLastKnownLocation());
                }
            }, getQueryLocationTimeout());
        } else {
            // There is no provider enabled.
            queryCountryCode(getLastKnownLocation());
        }
        return mDetectedCountry;
    
protected java.lang.StringgetCountryFromLocation(android.location.Location location)

return
the ISO 3166-1 two letters country code from the location

        String country = null;
        Geocoder geoCoder = new Geocoder(mContext);
        try {
            List<Address> addresses = geoCoder.getFromLocation(
                    location.getLatitude(), location.getLongitude(), 1);
            if (addresses != null && addresses.size() > 0) {
                country = addresses.get(0).getCountryCode();
            }
        } catch (IOException e) {
            Slog.w(TAG, "Exception occurs when getting country from location");
        }
        return country;
    
protected java.util.ListgetEnabledProviders()

        if (mEnabledProviders == null) {
            mEnabledProviders = mLocationManager.getProviders(true);
        }
        return mEnabledProviders;
    
protected android.location.LocationgetLastKnownLocation()

return
the last known location from all providers

        List<String> providers = mLocationManager.getAllProviders();
        Location bestLocation = null;
        for (String provider : providers) {
            Location lastKnownLocation = mLocationManager.getLastKnownLocation(provider);
            if (lastKnownLocation != null) {
                if (bestLocation == null ||
                        bestLocation.getElapsedRealtimeNanos() <
                        lastKnownLocation.getElapsedRealtimeNanos()) {
                    bestLocation = lastKnownLocation;
                }
            }
        }
        return bestLocation;
    
protected longgetQueryLocationTimeout()

return
the timeout for querying the location.

        return QUERY_LOCATION_TIMEOUT;
    
protected booleanisAcceptableProvider(java.lang.String provider)

        // We don't want to actively initiate a location fix here (with gps or network providers).
        return LocationManager.PASSIVE_PROVIDER.equals(provider);
    
private synchronized voidqueryCountryCode(android.location.Location location)
Start a new thread to query the country from Geocoder.

        if (location == null) {
            notifyListener(null);
            return;
        }
        if (mQueryThread != null) return;
        mQueryThread = new Thread(new Runnable() {
            @Override
            public void run() {
                String countryIso = null;
                if (location != null) {
                    countryIso = getCountryFromLocation(location);
                }
                if (countryIso != null) {
                    mDetectedCountry = new Country(countryIso, Country.COUNTRY_SOURCE_LOCATION);
                } else {
                    mDetectedCountry = null;
                }
                notifyListener(mDetectedCountry);
                mQueryThread = null;
            }
        });
        mQueryThread.start();
    
protected voidregisterListener(java.lang.String provider, android.location.LocationListener listener)
Register a listener with a provider name

        mLocationManager.requestLocationUpdates(provider, 0, 0, listener);
    
public synchronized voidstop()
Stop the current query without notifying the listener.

        if (mLocationListeners != null) {
            for (LocationListener listener : mLocationListeners) {
                unregisterListener(listener);
            }
            mLocationListeners = null;
        }
        if (mTimer != null) {
            mTimer.cancel();
            mTimer = null;
        }
    
protected voidunregisterListener(android.location.LocationListener listener)
Unregister an already registered listener

        mLocationManager.removeUpdates(listener);