Какой самый простой и надежный способ узнать текущее местоположение пользователя на Android? - PullRequest
771 голосов
/ 30 июня 2010

API LocationManager на Android кажется немного трудным для приложения, которое требует лишь приблизительного и приблизительного определения местоположения пользователя.

Приложение, над которым я сейчас работаюЭто действительно приложение для определения местоположения само по себе, но оно действительно должно получить местоположение пользователя, чтобы отобразить список близлежащих предприятий.Не нужно беспокоиться о том, перемещается ли пользователь или что-то в этом роде.

Вот что я хотел бы сделать:

  1. Показать пользователю список ближайшихместоположения.
  2. Предварительно загрузите местоположение пользователя, чтобы к моменту, когда оно понадобится, в Activity X, оно было доступно.
  3. Меня не особо заботит точность или частота обновления.Достаточно просто захватить одно место, пока оно не далеко.Возможно, если я захочу проявить фантазию, я буду обновлять местоположение каждые несколько минут или около того, но это не является огромным приоритетом.
  4. Работайте на любом устройстве, если оно имеет либо GPS, либо поставщика сетевого расположения..

Кажется, что это не должно быть так сложно, но мне кажется, что я должен раскрутить двух разных провайдеров местоположения (GPS и NETWORK) и управлять жизненным циклом каждого из них.Не только это, но я должен дублировать один и тот же код в нескольких действиях, чтобы удовлетворить # 2.Я пытался использовать getBestProvider() в прошлом, чтобы сократить решение до использования только одного провайдера местоположения, но это, кажется, дает вам только лучшего «теоретического» провайдера, а не провайдера, который фактически даст вам лучшие результаты.

Есть ли более простой способ сделать это?

Ответы [ 26 ]

918 голосов
/ 30 июня 2010

Вот что я делаю:

  1. Прежде всего я проверяю, какие провайдеры включены. Некоторые могут быть отключены на устройстве, некоторые могут быть отключены в манифесте приложения.
  2. Если какой-либо провайдер доступен, я запускаю прослушиватели местоположения и таймер таймаута. В моем примере 20 секунд может быть недостаточно для GPS, поэтому вы можете увеличить его.
  3. Если я получаю обновление от слушателя местоположения, я использую предоставленное значение. Я останавливаю слушателей и таймер.
  4. Если я не получаю никаких обновлений и таймеров, я должен использовать последние известные значения.
  5. Я беру последние известные значения от доступных провайдеров и выбираю самые последние из них.

Вот как я использую свой класс:

LocationResult locationResult = new LocationResult(){
    @Override
    public void gotLocation(Location location){
        //Got the location!
    }
};
MyLocation myLocation = new MyLocation();
myLocation.getLocation(this, locationResult);

А вот класс MyLocation:

import java.util.Timer;
import java.util.TimerTask;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;

public class MyLocation {
    Timer timer1;
    LocationManager lm;
    LocationResult locationResult;
    boolean gps_enabled=false;
    boolean network_enabled=false;

    public boolean getLocation(Context context, LocationResult result)
    {
        //I use LocationResult callback class to pass location value from MyLocation to user code.
        locationResult=result;
        if(lm==null)
            lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

        //exceptions will be thrown if provider is not permitted.
        try{gps_enabled=lm.isProviderEnabled(LocationManager.GPS_PROVIDER);}catch(Exception ex){}
        try{network_enabled=lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);}catch(Exception ex){}

        //don't start listeners if no provider is enabled
        if(!gps_enabled && !network_enabled)
            return false;

        if(gps_enabled)
            lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListenerGps);
        if(network_enabled)
            lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListenerNetwork);
        timer1=new Timer();
        timer1.schedule(new GetLastLocation(), 20000);
        return true;
    }

    LocationListener locationListenerGps = new LocationListener() {
        public void onLocationChanged(Location location) {
            timer1.cancel();
            locationResult.gotLocation(location);
            lm.removeUpdates(this);
            lm.removeUpdates(locationListenerNetwork);
        }
        public void onProviderDisabled(String provider) {}
        public void onProviderEnabled(String provider) {}
        public void onStatusChanged(String provider, int status, Bundle extras) {}
    };

    LocationListener locationListenerNetwork = new LocationListener() {
        public void onLocationChanged(Location location) {
            timer1.cancel();
            locationResult.gotLocation(location);
            lm.removeUpdates(this);
            lm.removeUpdates(locationListenerGps);
        }
        public void onProviderDisabled(String provider) {}
        public void onProviderEnabled(String provider) {}
        public void onStatusChanged(String provider, int status, Bundle extras) {}
    };

    class GetLastLocation extends TimerTask {
        @Override
        public void run() {
             lm.removeUpdates(locationListenerGps);
             lm.removeUpdates(locationListenerNetwork);

             Location net_loc=null, gps_loc=null;
             if(gps_enabled)
                 gps_loc=lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
             if(network_enabled)
                 net_loc=lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

             //if there are both values use the latest one
             if(gps_loc!=null && net_loc!=null){
                 if(gps_loc.getTime()>net_loc.getTime())
                     locationResult.gotLocation(gps_loc);
                 else
                     locationResult.gotLocation(net_loc);
                 return;
             }

             if(gps_loc!=null){
                 locationResult.gotLocation(gps_loc);
                 return;
             }
             if(net_loc!=null){
                 locationResult.gotLocation(net_loc);
                 return;
             }
             locationResult.gotLocation(null);
        }
    }

    public static abstract class LocationResult{
        public abstract void gotLocation(Location location);
    }
}

Кто-то может также захотеть изменить мою логику. Например, если вы получаете обновление от сетевого провайдера, не останавливайте слушателей, а продолжайте ждать. GPS дает более точные данные, поэтому стоит подождать. Если время истекло, и вы получили обновление от сети, но не от GPS, вы можете использовать значение, предоставленное из сети.

Еще один подход заключается в использовании LocationClient http://developer.android.com/training/location/retrieve-current.html. Но для этого требуется, чтобы на пользовательском устройстве был установлен apk Google Play Services.

39 голосов
/ 17 июня 2011

После поиска лучшей реализации, как получить точное точное местоположение пользователя, мне удалось объединить все лучшие методы и создать следующий класс:

/**
 * Retrieve accurate location from GPS or network services. 
 * 
 *
 * Class usage example:
 * 
 * public void onCreate(Bundle savedInstanceState) {
 *      ...
 *      my_location = new MyLocation();
 *      my_location.init(main.this, locationResult);
 * }
 * 
 * 
 * public LocationResult locationResult = new LocationResult(){
 *      @Override
 *      public void gotLocation(final Location location){
 *          // do something
 *          location.getLongitude();
 *          location.getLatitude();
 *      }
 *  };
 */
class MyLocation{

    /**
     * If GPS is enabled. 
     * Use minimal connected satellites count.
     */
    private static final int min_gps_sat_count = 5;

    /**
     * Iteration step time.
     */
    private static final int iteration_timeout_step = 500;

    LocationResult locationResult;
    private Location bestLocation = null;
    private Handler handler = new Handler();
    private LocationManager myLocationManager; 
    public Context context;

    private boolean gps_enabled = false;

    private int counts    = 0;
    private int sat_count = 0;

    private Runnable showTime = new Runnable() {

         public void run() {
            boolean stop = false;
            counts++;
            System.println("counts=" + counts);

            //if timeout (1 min) exceeded, stop tying
            if(counts > 120){
                stop = true;
            }

            //update last best location
            bestLocation = getLocation(context);

            //if location is not ready or don`t exists, try again
            if(bestLocation == null && gps_enabled){
                System.println("BestLocation not ready, continue to wait");
                handler.postDelayed(this, iteration_timeout_step);
            }else{
                //if best location is known, calculate if we need to continue to look for better location
                //if gps is enabled and min satellites count has not been connected or min check count is smaller then 4 (2 sec)  
                if(stop == false && !needToStop()){
                    System.println("Connected " + sat_count + " sattelites. continue waiting..");
                    handler.postDelayed(this, iteration_timeout_step);
                }else{
                    System.println("#########################################");
                    System.println("BestLocation finded return result to main. sat_count=" + sat_count);
                    System.println("#########################################");

                    // removing all updates and listeners
                    myLocationManager.removeUpdates(gpsLocationListener);
                    myLocationManager.removeUpdates(networkLocationListener);    
                    myLocationManager.removeGpsStatusListener(gpsStatusListener);
                    sat_count = 0;

                    // send best location to locationResult
                    locationResult.gotLocation(bestLocation);
                }
            }
         }
    };

    /**
     * Determine if continue to try to find best location
     */
    private Boolean needToStop(){

        if(!gps_enabled){
                          return true;
                     }
          else if(counts <= 4){
                return false;
            }
            if(sat_count < min_gps_sat_count){
                //if 20-25 sec and 3 satellites found then stop
                if(counts >= 40 && sat_count >= 3){
                    return true;
                }
                return false;
            }
        }
        return true;
    }

    /**
     * Best location abstract result class
     */
    public static abstract class LocationResult{
         public abstract void gotLocation(Location location);
     }

    /**
     * Initialize starting values and starting best location listeners
     * 
     * @param Context ctx
     * @param LocationResult result
     */
    public void init(Context ctx, LocationResult result){
        context = ctx;
        locationResult = result;

        myLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

        gps_enabled = (Boolean) myLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);

        bestLocation = null;
        counts = 0;

        // turning on location updates
        myLocationManager.requestLocationUpdates("network", 0, 0, networkLocationListener);
        myLocationManager.requestLocationUpdates("gps", 0, 0, gpsLocationListener);
        myLocationManager.addGpsStatusListener(gpsStatusListener);

        // starting best location finder loop
        handler.postDelayed(showTime, iteration_timeout_step);
    }

    /**
     * GpsStatus listener. OnChainged counts connected satellites count.
     */
    public final GpsStatus.Listener gpsStatusListener = new GpsStatus.Listener() {
        public void onGpsStatusChanged(int event) {

             if(event == GpsStatus.GPS_EVENT_SATELLITE_STATUS){
                try {
                    // Check number of satellites in list to determine fix state
                     GpsStatus status = myLocationManager.getGpsStatus(null);
                     Iterable<GpsSatellite>satellites = status.getSatellites();

                     sat_count = 0;

                     Iterator<GpsSatellite>satI = satellites.iterator();
                     while(satI.hasNext()) {
                         GpsSatellite satellite = satI.next();
                         System.println("Satellite: snr=" + satellite.getSnr() + ", elevation=" + satellite.getElevation());                         
                         sat_count++;
                     }
                } catch (Exception e) {
                    e.printStackTrace();
                    sat_count = min_gps_sat_count + 1;
                }

                 System.println("#### sat_count = " + sat_count);
             }
         }
    };

    /**
     * Gps location listener.
     */
    public final LocationListener gpsLocationListener = new LocationListener(){
        @Override
         public void onLocationChanged(Location location){

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

    /**
     * Network location listener.
     */
    public final LocationListener networkLocationListener = new LocationListener(){
        @Override
         public void onLocationChanged(Location location){

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


    /**
     * Returns best location using LocationManager.getBestProvider()
     * 
     * @param context
     * @return Location|null
     */
    public static Location getLocation(Context context){
        System.println("getLocation()");

        // fetch last known location and update it
        try {
            LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

            Criteria criteria = new Criteria();
            criteria.setAccuracy(Criteria.ACCURACY_FINE);
             criteria.setAltitudeRequired(false);
             criteria.setBearingRequired(false);
             criteria.setCostAllowed(true);
             String strLocationProvider = lm.getBestProvider(criteria, true);

             System.println("strLocationProvider=" + strLocationProvider);
             Location location = lm.getLastKnownLocation(strLocationProvider);
             if(location != null){
                return location;
             }
             return null;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

Этот класс пытается подключиться к min_gps_sat_count спутникам, еслиGPS включен.Остальное возвращает LocationManager.getBestProvider() местоположение.Проверьте код!

28 голосов
/ 21 марта 2012

С решением Федора я испытал многократное выполнение обратного вызова gotLocation.Кажется, это происходит из-за условия гонки в переопределенном методе LocationListener.onLocationChanged, когда метод gotLocation 'достаточно длинный' .Я не уверен, но я предполагаю, что removeUpdates предотвращает постановку в очередь новых сообщений в очереди Looper, но не удаляет те, которые уже помещены в очередь, но еще не использованы.Следовательно, условие гонки.

Чтобы уменьшить вероятность этого неправильного поведения, можно вызвать removeUpdates до запуска события onLocationChanged, но все же у нас есть условие гонки.заменить requestLocationUpdates на requestSingleUpdate.

Это моя версия, основанная на решении Федора, использующая обработчик для отправки сообщения в поток сообщения:

public class LocationResolver {
    private Timer timer;
    private LocationManager locationManager;
    private LocationResult locationResult;
    private boolean gpsEnabled = false;
    private boolean networkEnabled = false;
    private Handler locationTimeoutHandler;

    private final Callback locationTimeoutCallback = new Callback() {
        public boolean handleMessage(Message msg) {
            locationTimeoutFunc();
            return true;
        }

        private void locationTimeoutFunc() {   
            locationManager.removeUpdates(locationListenerGps);
            locationManager.removeUpdates(locationListenerNetwork);

            Location networkLocation = null, gpsLocation = null;
            if (gpsEnabled)
                gpsLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
            if (networkEnabled)
                networkLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

            // if there are both values use the latest one
            if (gpsLocation != null && networkLocation != null) {
                if (gpsLocation.getTime() > networkLocation.getTime())
                    locationResult.gotLocation(gpsLocation);
                else
                    locationResult.gotLocation(networkLocation);
                return;
            }

            if (gpsLocation != null) {
                locationResult.gotLocation(gpsLocation);
                return;
            }
            if (networkLocation != null) {
                locationResult.gotLocation(networkLocation);
                return;
            }
            locationResult.gotLocation(null);           
        }
    };
    private final LocationListener locationListenerGps = new LocationListener() {
        public void onLocationChanged(Location location) {              
            timer.cancel();
            locationResult.gotLocation(location);
            locationManager.removeUpdates(this);
            locationManager.removeUpdates(locationListenerNetwork);
        }

        public void onProviderDisabled(String provider) {
        }

        public void onProviderEnabled(String provider) {
        }

        public void onStatusChanged(String provider, int status, Bundle extras) {
        }
    };
    private final LocationListener locationListenerNetwork = new LocationListener() {
        public void onLocationChanged(Location location) {    
            timer.cancel(); 
            locationResult.gotLocation(location);
            locationManager.removeUpdates(this);
            locationManager.removeUpdates(locationListenerGps);
        }

        public void onProviderDisabled(String provider) {
        }

        public void onProviderEnabled(String provider) {
        }

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

    public void prepare() {
        locationTimeoutHandler = new Handler(locationTimeoutCallback);
    }

    public synchronized boolean getLocation(Context context, LocationResult result, int maxMillisToWait) {
        locationResult = result;
        if (locationManager == null)
            locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

        // exceptions will be thrown if provider is not permitted.
        try {
            gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        } catch (Exception ex) {
        }
        try {
            networkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
        } catch (Exception ex) {
        }

        // don't start listeners if no provider is enabled
        if (!gpsEnabled && !networkEnabled)
            return false;

        if (gpsEnabled)
            locationManager.requestSingleUpdate(LocationManager.GPS_PROVIDER, locationListenerGps, Looper.myLooper());
            //locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListenerGps);
        if (networkEnabled)
            locationManager.requestSingleUpdate(LocationManager.NETWORK_PROVIDER, locationListenerNetwork, Looper.myLooper());
            //locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListenerNetwork);

        timer = new Timer();
        timer.schedule(new GetLastLocationTask(), maxMillisToWait);
        return true;
    }

    private class GetLastLocationTask extends TimerTask {
        @Override
        public void run() { 
            locationTimeoutHandler.sendEmptyMessage(0);
        }
    }

    public static abstract class LocationResult {
        public abstract void gotLocation(Location location);
    }
}

Я использую этокласс из настраиваемого потока петлителя, подобный следующему:

public class LocationGetter {
    private final Context context;
    private Location location = null;
    private final Object gotLocationLock = new Object();
    private final LocationResult locationResult = new LocationResult() {            
        @Override
        public void gotLocation(Location location) {
            synchronized (gotLocationLock) {
                LocationGetter.this.location = location;
                gotLocationLock.notifyAll();
                Looper.myLooper().quit();
            }
        }
    };

    public LocationGetter(Context context) {
        if (context == null)
            throw new IllegalArgumentException("context == null");

        this.context = context;
    }

    public synchronized Coordinates getLocation(int maxWaitingTime, int updateTimeout) {
        try {
            final int updateTimeoutPar = updateTimeout;
            synchronized (gotLocationLock) {            
                new Thread() {
                    public void run() {
                        Looper.prepare();
                        LocationResolver locationResolver = new LocationResolver();
                        locationResolver.prepare();
                        locationResolver.getLocation(context, locationResult, updateTimeoutPar);
                        Looper.loop();
                    }
                }.start();

                gotLocationLock.wait(maxWaitingTime);
            }
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }

        if (location != null)
            coordinates = new Coordinates(location.getLatitude(), location.getLongitude());
        else
            coordinates = Coordinates.UNDEFINED;
        return coordinates; 
    }
}

, где Coordinates - это простой класс с двумя свойствами: широта и долгота.

16 голосов
/ 13 июля 2012

Я создал небольшое приложение с пошаговым описанием, чтобы получить координаты GPS текущего местоположения.

enter image description here

Полный пример исходного кода в URL ниже:


Получить координаты текущего местоположения, название города - в Android


Смотрите, как это работает:

  • Все, что нам нужно сделать, это добавить это разрешение в файл манифеста

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION">  
    </uses-permission>
    
  • и создайте экземпляр LocationManager следующим образом

    LocationManager locationManager = (LocationManager) 
                                      getSystemService(Context.LOCATION_SERVICE);
    
  • Проверьте, включен GPS или нет

  • затем реализуйте LocationListener и получите координаты

    LocationListener locationListener = new MyLocationListener();  
    locationManager.requestLocationUpdates(  
    LocationManager.GPS_PROVIDER, 5000, 10, locationListener);
    
  • вот пример кода


/*----------Listener class to get coordinates ------------- */
private class MyLocationListener implements LocationListener {

    @Override
    public void onLocationChanged(Location loc) {
        editLocation.setText("");
        pb.setVisibility(View.INVISIBLE);
        Toast.makeText(
            getBaseContext(),
            "Location changed: Lat: " + loc.getLatitude() + " Lng: "
                + loc.getLongitude(), Toast.LENGTH_SHORT).show();
        String longitude = "Longitude: " + loc.getLongitude();
        Log.v(TAG, longitude);
        String latitude = "Latitude: " + loc.getLatitude();
        Log.v(TAG, latitude);
        /*-------to get City-Name from coordinates -------- */
        String cityName = null;
        Geocoder gcd = new Geocoder(getBaseContext(), Locale.getDefault());
        List<Address> addresses;
        try {
            addresses = gcd.getFromLocation(loc.getLatitude(),
                loc.getLongitude(), 1);
            if (addresses.size() > 0)
                System.out.println(addresses.get(0).getLocality());
            cityName = addresses.get(0).getLocality();
        } catch (IOException e) {
            e.printStackTrace();
        }
        String s = longitude + "\n" + latitude + "\n\nMy Current City is: "
            + cityName;
        editLocation.setText(s);
    }

    @Override
    public void onProviderDisabled(String provider) {}

    @Override
    public void onProviderEnabled(String provider) {}

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {}
}
12 голосов
/ 30 июня 2010

Вы всегда можете просто использовать LocationManager.getLastKnownLocation () , но, как говорится, он может быть устаревшим.

И простым способом получить общее местоположение может быть регистрация в сети (обычно довольно быстрая).

LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(
     LocationManager.NETWORK_PROVIDER, 1000, 1000, this);

и затем делает

locationManager.removeUpdates(this);

в методе onLocationChanged() слушателя.

7 голосов
/ 30 апреля 2016

Я написал подробное руководство, охватывающее текущее местоположение здесь на demonuts.com . Вы можете найти больше описания здесь, а также вы можете скачать весь исходный код демо для лучшего понимания. *

Там уже много ответов, но я хочу показать последний способ определения местоположения с помощью Google API, чтобы новые программисты могли использовать новый метод:

Прежде всего, поместите это в файл Gradle

compile 'com.google.android.gms:play-services:8.4.0'

затем реализовать необходимые интерфейсы

public class MainActivity  extends BaseActivitiy implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, com.google.android.gms.location.LocationListener

объявить экземпляры

  private GoogleApiClient mGoogleApiClient;
  private Location mLocation;
  private LocationManager locationManager;
  private LocationRequest mLocationRequest;

вставьте это в onCreate()

 mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

Наконец, переопределите необходимые методы

 @Override
    public void onConnected(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) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return;
        }
        mLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
        if(mLocation == null){
            startLocationUpdates();
        }
        if (mLocation != null) {
            double latitude = mLocation.getLatitude();
            double longitude = mLocation.getLongitude();
        } else {
            // Toast.makeText(this, "Location not Detected", Toast.LENGTH_SHORT).show();
        }
    }

    protected void startLocationUpdates() {
        // Create the location request
        mLocationRequest = LocationRequest.create()
                .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
                .setInterval(UPDATE_INTERVAL)
                .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) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return;
        }
        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,
                mLocationRequest, this);
        Log.d("reque", "--->>>>");
    }

    @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
    public void onStart() {
        super.onStart();
        mGoogleApiClient.connect();
    }

    @Override
    public void onStop() {
        super.onStop();
        if (mGoogleApiClient.isConnected()) {
            mGoogleApiClient.disconnect();
        }
    }
    @Override
    public void onLocationChanged(Location location) {

    }

Не забудьте запустить GPS на вашем устройстве перед запуском приложения.

5 голосов
/ 30 июня 2010

Я не уверен, что Службы на основе определения местоположения могут получить местоположение из других инфраструктур, кроме GPS, но согласно этой статье это представляется возможным:

Приложения могут вызывать любой из нескольких типов методов позиционирования.

Использование сети мобильной телефонной связи: текущий идентификатор ячейки можно использовать для идентификации базовой приемопередающей станции (BTS), с которой устройство связывается, и местоположениячто БТС.Понятно, что точность этого метода зависит от размера ячейки и может быть довольно неточной.Ячейка GSM может иметь диаметр от 2 до 20 километров.Другие методы, используемые вместе с идентификатором соты, позволяют достичь точности в пределах 150 м.

Использование спутников: Глобальная система определения местоположения (GPS), контролируемая Министерством обороны США, использует созвездие из 24 спутников, вращающихся вокруг Земли.GPS определяет положение устройства, вычисляя разницу во времени, которое сигналы с разных спутников принимают на приемник.Сигналы GPS кодируются, поэтому мобильное устройство должно быть оснащено приемником GPS.Возможно, GPS является наиболее точным методом (от 4 до 40 метров, если у приемника GPS есть четкое изображение неба), но у него есть некоторые недостатки: дополнительное оборудование может быть дорогостоящим, потреблять батарею во время использования и требует некоторого тепла.после холодного старта, чтобы получить начальное исправление на видимых спутниках.Он также страдает от "эффектов каньона" в городах, где видимость спутника прерывистая.

Использование радиомаяков ближнего действия: в относительно небольших районах, например в одном здании, локальная сеть может предоставлять местоположения наряду с другими службами.Например, соответствующим образом оборудованные устройства могут использовать Bluetooth для позиционирования на короткие расстояния.

5 голосов
/ 15 июня 2012

Используйте приведенный ниже код, это даст лучший доступный поставщик:

String locCtx = Context.LOCATION_SERVICE; 

LocationManager locationMgr = (LocationManager) ctx.getSystemService(locCtx);

Criteria criteria  = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setAltitudeRequired(false);
criteria.setBearingRequired(false);
criteria.setCostAllowed(true);
criteria.setPowerRequirement(Criteria.POWER_LOW);

String provider = locationMgr.getBestProvider(criteria, true);

System.out.println("Best Available provider::::"+provider);
5 голосов
/ 18 ноября 2010

На самом деле мы можем использовать двух провайдеров (GPS и сеть).И они просто используют общий слушатель:

locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 10 * 1000, (float) 10.0, listener);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 90 * 1000, (float) 10.0, listener);

Это необходимо, потому что метод OnLocationChanged() всегда нужно вызывать вовремя.

4 голосов
/ 18 июня 2014

Рекомендованный способ сделать это - использовать LocationClient:

Сначала определите значения интервала обновления местоположения. Отрегулируйте это в соответствии со своими потребностями.

private static final int MILLISECONDS_PER_SECOND = 1000;
private static final long UPDATE_INTERVAL = MILLISECONDS_PER_SECOND * UPDATE_INTERVAL_IN_SECONDS;
private static final int FASTEST_INTERVAL_IN_SECONDS = 1;
private static final long FASTEST_INTERVAL = MILLISECONDS_PER_SECOND * FASTEST_INTERVAL_IN_SECONDS;

Пусть ваш Activity агрегат GooglePlayServicesClient.ConnectionCallbacks, GooglePlayServicesClient.OnConnectionFailedListener и LocationListener.

public class LocationActivity extends Activity implements 
GooglePlayServicesClient.ConnectionCallbacks, GooglePlayServicesClient.OnConnectionFailedListener, LocationListener {}

Затем установите LocationClient в методе onCreate() вашего Activity:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mLocationClient = new LocationClient(this, this, this);

    mLocationRequest = LocationRequest.create();
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    mLocationRequest.setInterval(UPDATE_INTERVAL);
    mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
}

Добавьте необходимые методы к вашему Activity; onConnected() - это метод, который вызывается при подключении LocationClient. onLocationChanged() - это место, где вы сможете найти самое актуальное местоположение.

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
    Log.w(TAG, "Location client connection failed");
}

@Override
public void onConnected(Bundle dataBundle) {
    Log.d(TAG, "Location client connected");
    mLocationClient.requestLocationUpdates(mLocationRequest, this); 
}

@Override
public void onDisconnected() {
    Log.d(TAG, "Location client disconnected");
}

@Override
public void onLocationChanged(Location location) {
    if (location != null) {
        Log.d(TAG, "Updated Location: " + Double.toString(location.getLatitude()) + "," + Double.toString(location.getLongitude()));
    } else {
        Log.d(TAG, "Updated location NULL");
    } 
}     

Обязательно подключайте / отключайте LocationClient, чтобы использовать только дополнительную батарею, когда это абсолютно необходимо, и чтобы GPS не работал бесконечно. LocationClient должен быть подключен для получения данных из него.

public void onResume() {
    super.onResume();
    mLocationClient.connect();
}

public void onStop() {
    if (mLocationClient.isConnected()) {
        mLocationClient.removeLocationUpdates(this);
    }
    mLocationClient.disconnect();
    super.onStop();
}

Получить местоположение пользователя. Сначала попробуйте использовать LocationClient; если это не поможет, вернитесь к LocationManager.

public Location getLocation() {
    if (mLocationClient != null && mLocationClient.isConnected()) {
        return mLocationClient.getLastLocation();
    } else {
        LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
        if (locationManager != null) {
            Location lastKnownLocationGPS = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
            if (lastKnownLocationGPS != null) {
                return lastKnownLocationGPS;
            } else {
                return locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
            }
        } else {
            return null;
        }
    }
}
...