Как получить текущее местоположение GPS программно в Android?

716

Мне нужно получить мое текущее местоположение с помощью GPS программно. Как я могу этого достичь?

mudit
источник

Ответы:

432

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

Полный пример исходного кода находится в координатах Get Current Location, название города - в Android .


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

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

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
  • И создайте экземпляр 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) {}
}

swiftBoy
источник
36
Это означает, что вам нужно переехать до того, как произойдет обновление местоположения? Почему он не показывает ваше текущее местоположение с первой попытки после установки?
Nii Laryea
15
@NiiLaryea, потому что я получаю Location с помощью метода " onLocationChanged () ", который дает каждый раз новое местоположение во время вашего перемещения, но если вы хотите только один раз, вам нужно вызвать " getLastKnownLocation () "
swiftBoy
Если в adressesстроке только один адрес, начинающийся с, cityName =произойдет сбой с исключением. Использование скобок это исправит.
Carrotman42
2
Я слышал, что люди говорят, getLastKnownLocation()что это более "несвежее" место - почему это? Разве звонки getLastKnownLocation()не получают последние GPS-чтения телефона GPS?
Дон Чидл
9
@mmcrae Нет, это не так. GPS не всегда работает. getLastKnownLocation не включает его. Он получает последнее местоположение с момента последнего включения. шляпа может быть действительно свежей, часом или даже нулевой.
Гейб Сечан
139

Вот дополнительная информация для других ответов.

Поскольку Android имеет

GPS_PROVIDER and NETWORK_PROVIDER

Вы можете зарегистрироваться в обоих и начать получать события onLocationChanged(Location location)из двух одновременно. Все идет нормально. Теперь вопрос, нужны ли нам два результата или мы должны взять лучшее. Как я знаю, GPS_PROVIDERрезультаты имеют лучшую точность, чем NETWORK_PROVIDER.

Определим Locationполе:

private Location currentBestLocation = null;

Прежде чем мы начнем прослушивать Изменение местоположения, мы реализуем следующий метод. Этот метод возвращает последнее известное местоположение между GPS и сетью. Для этого метода новее лучше.

/**
 * @return the last know best location
 */
private Location getLastBestLocation() {
    Location locationGPS = mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
    Location locationNet = mLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

    long GPSLocationTime = 0;
    if (null != locationGPS) { GPSLocationTime = locationGPS.getTime(); }

    long NetLocationTime = 0;

    if (null != locationNet) {
        NetLocationTime = locationNet.getTime();
    }

    if ( 0 < GPSLocationTime - NetLocationTime ) {
        return locationGPS;
    }
    else {
        return locationNet;
    }
}

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

...
static final int TWO_MINUTES = 1000 * 60 * 2;
...

Я добавляю новый метод для onLocationChanged:

@Override
public void onLocationChanged(Location location) {

    makeUseOfNewLocation(location);

    if(currentBestLocation == null){
        currentBestLocation = location;
    }

    ....
}


/**
 * This method modify the last know good location according to the arguments.
 *
 * @param location The possible new location.
 */
void makeUseOfNewLocation(Location location) {
    if ( isBetterLocation(location, currentBestLocation) ) {
        currentBestLocation = location;
    }
}

....

/** Determines whether one location reading is better than the current location fix
 * @param location  The new location that you want to evaluate
 * @param currentBestLocation  The current location fix, to which you want to compare the new one.
 */
protected boolean isBetterLocation(Location location, Location currentBestLocation) {
    if (currentBestLocation == null) {
        // A new location is always better than no location
        return true;
    }

    // Check whether the new location fix is newer or older
    long timeDelta = location.getTime() - currentBestLocation.getTime();
    boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
    boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
    boolean isNewer = timeDelta > 0;

    // If it's been more than two minutes since the current location, use the new location,
    // because the user has likely moved.
    if (isSignificantlyNewer) {
        return true;
        // If the new location is more than two minutes older, it must be worse.
    } else if (isSignificantlyOlder) {
        return false;
    }

    // Check whether the new location fix is more or less accurate
    int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
    boolean isLessAccurate = accuracyDelta > 0;
    boolean isMoreAccurate = accuracyDelta < 0;
    boolean isSignificantlyLessAccurate = accuracyDelta > 200;

    // Check if the old and new location are from the same provider
    boolean isFromSameProvider = isSameProvider(location.getProvider(),
                                                currentBestLocation.getProvider());

    // Determine location quality using a combination of timeliness and accuracy
    if (isMoreAccurate) {
        return true;
    } else if (isNewer && !isLessAccurate) {
        return true;
    } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
        return true;
    }
    return false;
}

// Checks whether two providers are the same
private boolean isSameProvider(String provider1, String provider2) {
    if (provider1 == null) {
        return provider2 == null;
    }
    return provider1.equals(provider2);
}

....
Максим Шустин
источник
Привет, это хороший пример ... но не могли бы вы дать мне более полный пример? У меня проблемы с интеграцией в существующий код. Кроме того, я использую только GPS в качестве поставщика.
beerBear
1
@quantumstates Я думаю, это довольно полно. Просто создайте поле private Location currentBestLocation = null;и добавьте `makeUseOfNewLocation (location);` к методу onLocationChanged (..)
Максим Шустин
Спасибо Максим. У меня вопрос. Где вы используете метод getLastBestLocation?
SeyedPooya Soofbaf
@SeyyedPuyaSoofbaf Как правило, новое местоположение мы получаем примерно через 30 секунд. Если мы зарегистрировались у обоих Менеджеров, мы можем сразу получить 2 последних известных местоположения и решить, кто из них новее.
Максим Шустин
Я не понимаю, в чем разница между getLastBestLocation и isBetterLocation? Эти два метода были использованы для сравнения двух мест.
SeyedPooya Soofbaf
84

Вы можете найти местоположение либо по GPS_PROVIDER or NETWORK_PROVIDER .

Обзор услуг определения местоположения в Android.

Вот один пример, который пытается найти местоположение с помощью GPS. Если ваш GPS недоступен, попробуйте использовать сеть для поиска местоположения.

GPSTracker.java

 public class GPSTracker extends Service implements LocationListener {

    private final Context mContext;

    // Flag for GPS status
    boolean isGPSEnabled = false;

    // Flag for network status
    boolean isNetworkEnabled = false;

    // Flag for GPS status
    boolean canGetLocation = false;

    Location location; // Location
    double latitude; // Latitude
    double longitude; // Longitude

    // The minimum distance to change Updates in meters
    private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10 meters

    // The minimum time between updates in milliseconds
    private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1; // 1 minute

    // Declaring a Location Manager
    protected LocationManager locationManager;

    public GPSTracker(Context context) {
        this.mContext = context;
        getLocation();
    }

    public Location getLocation() {
        try {
            locationManager = (LocationManager) mContext
                    .getSystemService(LOCATION_SERVICE);

            // Getting GPS status
            isGPSEnabled = locationManager
                    .isProviderEnabled(LocationManager.GPS_PROVIDER);

            // Getting network status
            isNetworkEnabled = locationManager
                    .isProviderEnabled(LocationManager.NETWORK_PROVIDER);

            if (!isGPSEnabled && !isNetworkEnabled) {
                // No network provider is enabled
            } else {
                this.canGetLocation = true;
                if (isNetworkEnabled) {
                    locationManager.requestLocationUpdates(
                            LocationManager.NETWORK_PROVIDER,
                            MIN_TIME_BW_UPDATES,
                            MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                    Log.d("Network", "Network");
                    if (locationManager != null) {
                        location = locationManager
                                .getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                        if (location != null) {
                            latitude = location.getLatitude();
                            longitude = location.getLongitude();
                        }
                    }
                }
                // If GPS enabled, get latitude/longitude using GPS Services
                if (isGPSEnabled) {
                    if (location == null) {
                        locationManager.requestLocationUpdates(
                                LocationManager.GPS_PROVIDER,
                                MIN_TIME_BW_UPDATES,
                                MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                        Log.d("GPS Enabled", "GPS Enabled");
                        if (locationManager != null) {
                            location = locationManager
                                    .getLastKnownLocation(LocationManager.GPS_PROVIDER);
                            if (location != null) {
                                latitude = location.getLatitude();
                                longitude = location.getLongitude();
                            }
                        }
                    }
                }
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }

        return location;
    }


    /**
     * Stop using GPS listener
     * Calling this function will stop using GPS in your app.
     * */
    public void stopUsingGPS(){
        if(locationManager != null){
            locationManager.removeUpdates(GPSTracker.this);
        }
    }


    /**
     * Function to get latitude
     * */
    public double getLatitude(){
        if(location != null){
            latitude = location.getLatitude();
        }

        // return latitude
        return latitude;
    }


    /**
     * Function to get longitude
     * */
    public double getLongitude(){
        if(location != null){
            longitude = location.getLongitude();
        }

        // return longitude
        return longitude;
    }

    /**
     * Function to check GPS/Wi-Fi enabled
     * @return boolean
     * */
    public boolean canGetLocation() {
        return this.canGetLocation;
    }


    /**
     * Function to show settings alert dialog.
     * On pressing the Settings button it will launch Settings Options.
     * */
    public void showSettingsAlert(){
        AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);

        // Setting Dialog Title
        alertDialog.setTitle("GPS is settings");

        // Setting Dialog Message
        alertDialog.setMessage("GPS is not enabled. Do you want to go to settings menu?");

        // On pressing the Settings button.
        alertDialog.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog,int which) {
                Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                mContext.startActivity(intent);
            }
        });

        // On pressing the cancel button
        alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
            dialog.cancel();
            }
        });

        // Showing Alert Message
        alertDialog.show();
    }


    @Override
    public void onLocationChanged(Location location) {
    }


    @Override
    public void onProviderDisabled(String provider) {
    }


    @Override
    public void onProviderEnabled(String provider) {
    }


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


    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }
}

Activity -AndroidGPSTrackingActivity.java

    public class AndroidGPSTrackingActivity extends Activity {

    Button btnShowLocation;

    // GPSTracker class
    GPSTracker gps;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        btnShowLocation = (Button) findViewById(R.id.btnShowLocation);

        // Show location button click event
        btnShowLocation.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // Create class object
                gps = new GPSTracker(AndroidGPSTrackingActivity.this);

                // Check if GPS enabled
                if(gps.canGetLocation()) {

                    double latitude = gps.getLatitude();
                    double longitude = gps.getLongitude();

                    // \n is for new line
                    Toast.makeText(getApplicationContext(), "Your Location is - \nLat: " + latitude + "\nLong: " + longitude, Toast.LENGTH_LONG).show();
                } else {
                    // Can't get location.
                    // GPS or network is not enabled.
                    // Ask user to enable GPS/network in settings.
                    gps.showSettingsAlert();
                }
            }
        });
    }
}

Layout- main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <Button android:id="@+id/btnShowLocation"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Show Location"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true"/>
</RelativeLayout>

AndroidManifest.xml

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
Нирав Ранпара
источник
4
Я думаю, что в этом примере есть проблема, вы никогда не используете слушатель местоположения. Всегда используется GetLastKnownLocation (), который может быть не последним
Madhur Ahuja
16
Приходится понижать голос за переоценку. Код здесь неплохой, но его используют многие люди, которые его не понимают, и у него есть некоторые недостатки в использовании getLastKnownLocation - мы получаем много вопросов от людей, использующих его и получающих устаревшие местоположения, не зная они несвежие Также значение canGetLocation является неправильным, вы устанавливаете его в зависимости от того, включен ли поставщик, но не проверяете, возвращает ли getLastKnownLocation реальное значение - вы просто предполагаете, что это так. Я думаю, что это можно сделать хорошо, но я бы не советовал никому использовать его как есть.
Гейб Сечан
1
Разрешения ACCESS_FINE_LOCATION достаточно в соответствии с документацией для Android: если вы используете и NETWORK_PROVIDER, и GPS_PROVIDER, то вам нужно запросить только разрешение ACCESS_FINE_LOCATION, поскольку оно включает разрешение для обоих провайдеров. (Разрешение для ACCESS_COARSE_LOCATION включает разрешение только для NETWORK_PROVIDER.)
англ. Самер Т
Я попытался этот код и его предоставление не точное местоположение.
misha312
Это не правильная версия кода, это не дает правильное местоположение
Moeez
45

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

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

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

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

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

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;
        } startLocationUpdates();
        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 на вашем устройстве перед запуском приложения.

Парсания Хардик
источник
Я использовал ваш метод для отображения координат, но я не могу увидеть координаты, не могли бы вы посмотреть на мой вопрос ?
Moeez
1
mLocationвсегда дает ноль. Я попробовал так же, как упомянуто
dharanbro
Перейдите по этой ссылке: demonuts.com/2016/12/30/get-current-gps-location-android-studio и загрузите оттуда исходный код и проверьте, работает ли исходный код на вашем компьютере или нет
Parsania Hardik
5
Это должен быть принятый ответ. А для компактности вы можете использовать compile 'com.google.android.gms:play-services-location:11.0.4'вместо добавления всех служб Google Play в свое приложение.
Моррис Франкен
37

Поскольку мне не понравился код из других ответов, вот мое простое решение. Это решение предназначено для использования в деятельности или службе для отслеживания местоположения. Он гарантирует, что никогда не вернет слишком устаревшие данные, если вы явно не запросите устаревшие данные. Он может быть запущен либо в режиме обратного вызова, чтобы получать обновления по мере их поступления, либо в режиме опроса для опроса самой последней информации.

Общий интерфейс LocationTracker. Позволяет нам иметь несколько типов трекеров местоположения и легко подключать соответствующий:

package com.gabesechan.android.reusable.location;

import android.location.Location;

public interface LocationTracker {
    public interface LocationUpdateListener{
        public void onUpdate(Location oldLoc, long oldTime, Location newLoc, long newTime);
    }

    public void start();
    public void start(LocationUpdateListener update);

    public void stop();

    public boolean hasLocation();

    public boolean hasPossiblyStaleLocation();

    public Location getLocation();

    public Location getPossiblyStaleLocation();

}

ProviderLocationTracker - этот класс будет отслеживать местоположение для GPS или NETWORK.

package com.gabesechan.android.reusable.location;

import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;

public class ProviderLocationTracker implements LocationListener, LocationTracker {

    // The minimum distance to change Updates in meters
    private static final long MIN_UPDATE_DISTANCE = 10; 

    // The minimum time between updates in milliseconds
    private static final long MIN_UPDATE_TIME = 1000 * 60; 

    private LocationManager lm;

    public enum ProviderType{
        NETWORK,
        GPS
    };    
    private String provider;

    private Location lastLocation;
    private long lastTime;

    private boolean isRunning;

    private LocationUpdateListener listener;

    public ProviderLocationTracker(Context context, ProviderType type) {
        lm = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
        if(type == ProviderType.NETWORK){
            provider = LocationManager.NETWORK_PROVIDER;
        }
        else{
            provider = LocationManager.GPS_PROVIDER;
        }
    }

    public void start(){
        if(isRunning){
            //Already running, do nothing
            return;
        }

        //The provider is on, so start getting updates.  Update current location
        isRunning = true;
        lm.requestLocationUpdates(provider, MIN_UPDATE_TIME, MIN_UPDATE_DISTANCE, this);
        lastLocation = null;
        lastTime = 0;
        return;
    }

    public void start(LocationUpdateListener update) {
        start();
        listener = update;

    }


    public void stop(){
        if(isRunning){
            lm.removeUpdates(this);
            isRunning = false;
            listener = null;
        }
    }

    public boolean hasLocation(){
        if(lastLocation == null){
            return false;
        }
        if(System.currentTimeMillis() - lastTime > 5 * MIN_UPDATE_TIME){
            return false; //stale
        }
        return true;
    }

    public boolean hasPossiblyStaleLocation(){
        if(lastLocation != null){
            return true;
        }
        return lm.getLastKnownLocation(provider)!= null;
    }

    public Location getLocation(){
        if(lastLocation == null){
            return null;
        }
        if(System.currentTimeMillis() - lastTime > 5 * MIN_UPDATE_TIME){
            return null; //stale
        }
        return lastLocation;
    }

    public Location getPossiblyStaleLocation(){
        if(lastLocation != null){
            return lastLocation;
        }
        return lm.getLastKnownLocation(provider);
    }

    public void onLocationChanged(Location newLoc) {
        long now = System.currentTimeMillis();
        if(listener != null){
            listener.onUpdate(lastLocation, lastTime, newLoc, now);
        }
        lastLocation = newLoc;
        lastTime = now;
    }

    public void onProviderDisabled(String arg0) {

    }

    public void onProviderEnabled(String arg0) {

    }

    public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
    }
}

Это FallbackLocationTracker, который будет отслеживать как GPS, так и NETWORK, и использовать любое местоположение, более точное.

package com.gabesechan.android.reusable.location;

import android.content.Context;
import android.location.Location;
import android.location.LocationManager;

public class FallbackLocationTracker  implements LocationTracker, LocationTracker.LocationUpdateListener {


    private boolean isRunning;

    private ProviderLocationTracker gps;
    private ProviderLocationTracker net;

    private LocationUpdateListener listener;

    Location lastLoc;
    long lastTime;

    public FallbackLocationTracker(Context context) {
        gps = new ProviderLocationTracker(context, ProviderLocationTracker.ProviderType.GPS);
        net = new ProviderLocationTracker(context, ProviderLocationTracker.ProviderType.NETWORK);
    }

    public void start(){
        if(isRunning){
            //Already running, do nothing
            return;
        }

        //Start both
        gps.start(this);
        net.start(this);
        isRunning = true;
    }

    public void start(LocationUpdateListener update) {
        start();
        listener = update;
    }


    public void stop(){
        if(isRunning){
            gps.stop();
            net.stop();
            isRunning = false;
            listener = null;
        }
    }

    public boolean hasLocation(){
        //If either has a location, use it
        return gps.hasLocation() || net.hasLocation();
    }

    public boolean hasPossiblyStaleLocation(){
        //If either has a location, use it
        return gps.hasPossiblyStaleLocation() || net.hasPossiblyStaleLocation();
    }

    public Location getLocation(){
        Location ret = gps.getLocation();
        if(ret == null){
            ret = net.getLocation();
        }
        return ret;
    }

    public Location getPossiblyStaleLocation(){
        Location ret = gps.getPossiblyStaleLocation();
        if(ret == null){
            ret = net.getPossiblyStaleLocation();
        }
        return ret;
    }

    public void onUpdate(Location oldLoc, long oldTime, Location newLoc, long newTime) {
        boolean update = false;

        //We should update only if there is no last location, the provider is the same, or the provider is more accurate, or the old location is stale
        if(lastLoc == null){
            update = true;
        }
        else if(lastLoc != null && lastLoc.getProvider().equals(newLoc.getProvider())){
            update = true;
        }
        else if(newLoc.getProvider().equals(LocationManager.GPS_PROVIDER)){
            update = true;
        }
        else if (newTime - lastTime > 5 * 60 * 1000){
            update = true;
        }

        if(update){
            if(listener != null){
                listener.onUpdate(lastLoc, lastTime, newLoc, newTime);                  
            }
            lastLoc = newLoc;
            lastTime = newTime;
        }

    }
}

Поскольку оба реализуют интерфейс LocationTracker, вы можете легко передумать, какой использовать. Чтобы запустить класс в режиме опроса, просто вызовите start (). Чтобы запустить его в режиме обновления, вызовите start (Listener).

Также взгляните на мой пост в блоге по коду

Гейб Сечан
источник
Для любого любопытного - причина, по которой я не использую время, встроенное в объект Location, заключается в том, что API не существует до API 17. Поскольку я хочу сохранить совместимость до 14, я просто использую текущее время. Вот почему я не вызываю getLastKnownLocation на раннем этапе, потому что мы не можем получить от него время и посмотреть, не устарело ли оно.
Гейб Сечан
Ваш код - лучшее и наиболее полное решение, которое я нашел за последние два дня поиска по этой теме. Он работает без ошибок и, как шарм, впечатляет. Я изменил FallbackLocationTracker (контекстный контекст, тип ProviderType) на публичный FallbackLocationTracker (контекстный контекст), поскольку нам не нужно отправлять провайдера в этот класс, он учитывает как GPS, так и сеть, я прав?
Зеешан
@zeeshan Вы правы, и я обновил код здесь. Я сделаю это в своем блоге в следующий раз, когда найду время (трудно найти ресурс для меня в эти дни). Как вы, вероятно, догадались, я создал запасной вариант, вставив копию из другого класса, и никогда не выполнял эту очистку.
Гейб Сечан
12
лучшее решение ... но не хватает только одного ... новичок не может его реализовать .. в нем тоже должен быть пример использования ...
Заффар Саффе
1
Здравствуйте @GabeSechan Я реализовал ваш метод, но каждый раз, когда я включаю GPS в настройках на моем устройстве Android и оставляю сеть включенной, он всегда возвращает нуль в методе getLocation. FallbackLocationTracker fallbackLocationTracker = new FallbackLocationTracker(mContext); fallbackLocationTracker.start(); if (fallbackLocationTracker.hasLocation()) { return fallbackLocationTracker.getLocation(); }
neteot
18

Получить местоположение GPS по -

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

LocationListener locationListener = new LocationListener() 
{

            @Override
            public void onStatusChanged(String provider, int status, Bundle extras) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onProviderEnabled(String provider) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onProviderDisabled(String provider) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onLocationChanged(Location location) {
                // TODO Auto-generated method stub
                double latitude = location.getLatitude();
                double longitude = location.getLongitude();
                double speed = location.getSpeed(); //spedd in meter/minute
                speed = (speed*3600)/1000;      // speed in km/minute               Toast.makeText(GraphViews.this, "Current speed:" + location.getSpeed(),Toast.LENGTH_SHORT).show();
            }
        };

        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);

}
Акшай Паливал
источник
2
Цель всегда состоит в том, чтобы сделать код менее точным и не переборщить с простой проверкой местоположения, как многие другие ответы. Спасибо, что действительно ответили на заданный вопрос.
SmulianJulian
Как получить местоположение каждую 1 секунду
Ruchir Baronia
Спасибо за простой способ получить GPS, он работает! Микробаг: location.getSpeed()возвращает скорость в метре / сек (не метре / мин).
Спекторский
16

Вы должны использовать последние / новейшие

GoogleApiClient Api

В основном, что вам нужно сделать, это:

private GoogleApiClient mGoogleApiClient;
mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();

затем

@Override
    public void onConnected(Bundle connectionHint) {
        mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
                mGoogleApiClient);
        if (mLastLocation != null) {
            mLatitudeText.setText(String.valueOf(mLastLocation.getLatitude()));
            mLongitudeText.setText(String.valueOf(mLastLocation.getLongitude()));
        }
    }

для наиболее точного и надежного местоположения. Смотрите мой пост здесь:

https://stackoverflow.com/a/33599228/2644905

Не используйте LocationListener, который не является точным и имеет задержку ответа. Если честно, это легче реализовать. Также ознакомьтесь с документацией: https://developers.google.com/android/reference/com/google/android/gms/common/api/GoogleApiClient.

omersem
источник
1
Это лучший ответ для новейшего API.
драмзи
1
Да. Это правильный способ сделать это, в наши дни. @nickfox предоставил несколько хороших ссылок в своем втором ответе на этот вопрос от первоначальных создателей API Location Services, которые стоит проверить.
gMale
11
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 the 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(), 5000);
        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);
    }
}

Я надеюсь, что это поможет вам...

Аристо Майкл
источник
1
Не забудьте добавить следующую строку в ваш файл AndroidManifest:<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Доктор Файлов
7

Теперь, когда сервисы определения местоположения в Google Play уже здесь, я рекомендую разработчикам начать использовать нового провайдера. Вам будет проще и точнее пользоваться. Пожалуйста, посмотрите видео Google I / O Beyond the Blue Dot: новые функции в Android Location от двух парней, которые создали новый API сервисов определения местоположения Google Play.

Я работал с API определения местоположения на многих мобильных платформах, и я думаю, что эти два парня действительно революционны. Он избавился от огромного количества сложностей использования различных провайдеров. Переполнение стека изобилует вопросами о том, какого поставщика использовать, использовать ли последнее известное местоположение, как установить другие свойства в LocationManager и т. Д. Этот новый API, который они создали, устраняет большинство этих неопределенностей и делает службы определения местоположения удовольствием использовать.

Я написал приложение для Android, которое периодически получает местоположение, используя службы определения местоположения Google Play, и отправляет это местоположение на веб-сервер, где оно хранится в базе данных и может быть просмотрено в Google Maps . Я написал как клиентское программное обеспечение (для Android, iOS, Windows Phone и Java ME ), так и серверное программное обеспечение (для ASP.NET и SQL Server или PHP и MySQL ). Программное обеспечение написано на родном языке для каждой платформы и работает в фоновом режиме на каждой. Наконец, программное обеспечение имеет лицензию MIT . Вы можете найти клиент Android здесь:

https://github.com/nickfox/GpsTracker/tree/master/phoneClients/android

nickfox
источник
7

Проще всего найти

   package com.javapapers.android.geolocationfinder;

    import android.os.Bundle;
    import android.app.Activity;
    import android.content.Context;
    import android.location.Location;
    import android.location.LocationListener;
    import android.location.LocationManager;
    import android.widget.TextView;

    import android.util.Log;

    public class MainActivity extends Activity implements LocationListener{
    protected LocationManager locationManager;
    protected LocationListener locationListener;
    protected Context context;
    TextView txtLat;
    String lat;
    String provider;
    protected String latitude,longitude; 
    protected boolean gps_enabled,network_enabled;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    txtLat = (TextView) findViewById(R.id.textview1);

    locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
    }
    @Override
    public void onLocationChanged(Location location) {
    txtLat = (TextView) findViewById(R.id.textview1);
    txtLat.setText("Latitude:" + location.getLatitude() + ", Longitude:" + location.getLongitude());
    }

    @Override
    public void onProviderDisabled(String provider) {
    Log.d("Latitude","disable");
    }

    @Override
    public void onProviderEnabled(String provider) {
    Log.d("Latitude","enable");
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
    Log.d("Latitude","status");
    }
    }
Дирадж Кумар
источник
6

LocationManager - это класс, который предоставляет встроенные методы для получения последнего известного местоположения

ШАГ 1. Создайте объект LocationManager, как показано ниже

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

ШАГ 2: Добавить критерии

*Criteria is use for setting accuracy*

Criteria criteria = new Criteria();
int currentapiVersion = android.os.Build.VERSION.SDK_INT;

if (currentapiVersion >= android.os.Build.VERSION_CODES.HONEYCOMB) {

    criteria.setSpeedAccuracy(Criteria.ACCURACY_HIGH);
    criteria.setAccuracy(Criteria.ACCURACY_FINE);
    criteria.setAltitudeRequired(true);
    criteria.setBearingRequired(true);
    criteria.setSpeedRequired(true);

}

ШАГ 3: ПОЛУЧИТЕ Avaliable Provider

Есть два типа провайдера GPS и сети

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

ШАГ 4: Получите последнюю информацию о местоположении

Location location = locationManager.getLastKnownLocation(provider);

ШАГ 5: Получить широту и долготу

Если объект location имеет значение null, не пытайтесь вызывать метод ниже s

getLatitude and getLongitude is methods which returns double values

user3131373
источник
6

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

  • Проверка доступности сервисов Google Play,
  • Обновите Сервис Google play, если он старый или недоступен
  • Диалог Создание GoogleApiClient и его обратных вызовов, связанных, отключенных и т. Д.
  • Остановка и освобождение ресурсов для обновления местоположения
  • Обработка сценариев разрешения местоположения
  • Проверка местоположения услуги включены или выключены
  • Получить последнее известное местоположение тоже не так просто
  • Откат к последнему известному местоположению, если оно не получено через определенное время

Чтобы облегчить все эти шаги, я создал Android-EasyLocation (небольшая библиотека Android) которая позаботится обо всем этом, и вы сможете сосредоточиться на бизнес-логике.

Все, что вам нужно, это расширить EasyLocationActivity и это

requestSingleLocationFix(easyLocationRequest);

или

requestLocationUpdates(easyLocationRequest);

Пример приложения для заказа и необходимые шаги здесь по адресу https://github.com/akhgupta/Android-EasyLocation

Akhil
источник
5

Я сделал проект, из которого мы можем получить точное местоположение с помощью Google Play Services, GPS и сетевых провайдеров. Этот проект можно найти здесь .

Стратегия поиска наилучшего местоположения заключается в том, чтобы сначала получить местоположение из сервисов Google Play, если местоположение найдено, затем проверить, лучше ли оно или нет, если найденное местоположение пусто, перезапустите сервисы Google Play и попробуйте получить местоположение из Android Location API. Зарегистрируйте местоположение на слушателях изменений, и когда когда-либо будет найдено лучшее местоположение, обратный вызов возвращает его в основное действие.

Он очень прост в использовании и реализации в коде только два класса , мы должны внедрить ИЭ LocationManagerInterfaceи SmartLocationManager, LocationActivityреализуют интерфейс и использование SmartLocationManager для извлечения местоположения.

/**
 * Created by Syed Raza Mehdi Naqvi on 8/10/2016.
 */
public interface LocationManagerInterface {
    String TAG = LocationManagerInterface.class.getSimpleName();

    void locationFetched(Location mLocation, Location oldLocation, String time, String locationProvider);

}

вот класс менеджера локаций

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;

import java.text.DateFormat;
import java.util.Date;

/**
 * Created by Syed Raza Mehdi Naqvi on 8/9/2016.
 */
public class SmartLocationManager implements
        GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {

    private static final String TAG = SmartLocationManager.class.getSimpleName();

    private static final int TWO_MINUTES = 1000 * 60 * 2;
    private static final int PERMISSION_REQUEST_CODE = 1000;
    private static final int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;

    // default value is false but user can change it
    private String mLastLocationUpdateTime;                                                         // fetched location time
    private String locationProvider;                                                                // source of fetched location

    private Location mLastLocationFetched;                                                          // location fetched
    private Location mLocationFetched;                                                              // location fetched
    private Location networkLocation;
    private Location gpsLocation;

    private int mLocationPiority;
    private long mLocationFetchInterval;
    private long mFastestLocationFetchInterval;

    private Context mContext;                                                                       // application context
    private Activity mActivity;                                                                     // activity context
    private LocationRequest mLocationRequest;
    private GoogleApiClient mGoogleApiClient;
    private LocationManagerInterface mLocationManagerInterface;

    private android.location.LocationManager locationManager;
    private android.location.LocationListener locationListener;

    boolean isGPSEnabled;
    boolean isNetworkEnabled;

    private int mProviderType;
    public static final int NETWORK_PROVIDER = 1;
    public static final int ALL_PROVIDERS = 0;
    public static final int GPS_PROVIDER = 2;

//    private final double STANDARD_LOCATION_ACCURACY = 100.0;
//    private final double STANDARD_LOCATION_SEED_LIMIT = 6.95;

    public static final int LOCATION_PROVIDER_ALL_RESTICTION = 1;
    public static final int LOCATION_PROVIDER_RESTRICTION_NONE = 0;
    public static final int LOCATION_PROVIDER_GPS_ONLY_RESTICTION = 2;
    public static final int LOCATION_PROVIDER_NETWORK_ONLY_RESTICTION = 3;
    private int mForceNetworkProviders = 0;

    public SmartLocationManager(Context context, Activity activity, LocationManagerInterface locationInterface, int providerType, int locationPiority, long locationFetchInterval, long fastestLocationFetchInterval, int forceNetworkProviders) {
        mContext = context;
        mActivity = activity;
        mProviderType = providerType;

        mLocationPiority = locationPiority;
        mForceNetworkProviders = forceNetworkProviders;
        mLocationFetchInterval = locationFetchInterval;
        mFastestLocationFetchInterval = fastestLocationFetchInterval;

        mLocationManagerInterface = locationInterface;

        initSmartLocationManager();
    }


    public void initSmartLocationManager() {

        // 1) ask for permission for Android 6 above to avoid crash
        // 2) check if gps is available
        // 3) get location using awesome strategy

        askLocationPermission();                            // for android version 6 above
        checkNetworkProviderEnable(mForceNetworkProviders);                       //

        if (isGooglePlayServicesAvailable())                // if googleplay services available
            initLocationObjts();                            // init obj for google play service and start fetching location
        else
            getLocationUsingAndroidAPI();                   // otherwise get location using Android API
    }

    private void initLocationObjts() {
        // Create the LocationRequest object
        mLocationRequest = LocationRequest.create()
                .setPriority(mLocationPiority)
                .setInterval(mLocationFetchInterval)                    // 10 seconds, in milliseconds
                .setFastestInterval(mFastestLocationFetchInterval);     // 1 second, in milliseconds

        if (mGoogleApiClient == null) {
            mGoogleApiClient = new GoogleApiClient.Builder(mActivity)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .addApi(LocationServices.API)
                    .build();
        }

        startLocationFetching();                                        // connect google play services to fetch location
    }

    @Override
    public void onConnected(Bundle connectionHint) {
        Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
        startLocationUpdates();
        if (location == null) {
            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
            getLocationUsingAndroidAPI();
        } else {
            setNewLocation(getBetterLocation(location, mLocationFetched), mLocationFetched);
        }
    }

    @Override
    public void onLocationChanged(Location location) {
        if (location == null) {
            getLastKnownLocation();
        } else {
            setNewLocation(getBetterLocation(location, mLocationFetched), mLocationFetched);
        }
    }

    @Override
    public void onConnectionSuspended(int i) {
        Log.i(TAG, "Connection suspended");
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        if (connectionResult.hasResolution()) {
            try {
                connectionResult.startResolutionForResult(mActivity, CONNECTION_FAILURE_RESOLUTION_REQUEST); // Start an Activity that tries to resolve the error
                getLocationUsingAndroidAPI();                                                                // try to get location using Android API locationManager
            } catch (IntentSender.SendIntentException e) {
                e.printStackTrace();
            }
        } else {
            Log.i(TAG, "Location services connection failed with code " + connectionResult.getErrorCode());
        }
    }

    private void setNewLocation(Location location, Location oldLocation) {
        if (location != null) {
            mLastLocationFetched = oldLocation;
            mLocationFetched = location;
            mLastLocationUpdateTime = DateFormat.getTimeInstance().format(new Date());
            locationProvider = location.getProvider();
            mLocationManagerInterface.locationFetched(location, mLastLocationFetched, mLastLocationUpdateTime, location.getProvider());
        }
    }

    private void getLocationUsingAndroidAPI() {
        // Acquire a reference to the system Location Manager
        locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);

        setLocationListner();
        captureLocation();
    }

    public void captureLocation() {
        if (Build.VERSION.SDK_INT >= 23 &&
                ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        try {
            if (mProviderType == SmartLocationManager.GPS_PROVIDER) {
                locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
            } else if (mProviderType == SmartLocationManager.NETWORK_PROVIDER) {
                locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
            } else {
                locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
                locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
            }
        } catch (Exception e) {
            Log.e(TAG, e.getMessage());
        }
    }

    private void setLocationListner() {
        // Define a listener that responds to location updates
        locationListener = new android.location.LocationListener() {
            public void onLocationChanged(Location location) {
                // Called when a new location is found by the network location provider.
                if (location == null) {
                    getLastKnownLocation();
                } else {
                    setNewLocation(getBetterLocation(location, mLocationFetched), mLocationFetched);
//                    if (isLocationAccurate(location) && location.getAccuracy() < STANDARD_LOCATION_ACCURACY && location.getSpeed() < STANDARD_LOCATION_SEED_LIMIT) {// no use of this if
//                        setNewLocation(getBetterLocation(location, mLocationFetched), mLocationFetched);
//                    } else {
//                        setNewLocation(getBetterLocation(location, mLocationFetched), mLocationFetched);
//                    }
                }
            }

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

            public void onProviderEnabled(String provider) {
            }

            public void onProviderDisabled(String provider) {
            }
        };
    }

    public Location getAccurateLocation() {
        if (Build.VERSION.SDK_INT >= 23 &&
                ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return null;
        }
        try {
            gpsLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
            networkLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
            Location newLocalGPS, newLocalNetwork;
            if (gpsLocation != null || networkLocation != null) {
                newLocalGPS = getBetterLocation(mLocationFetched, gpsLocation);
                newLocalNetwork = getBetterLocation(mLocationFetched, networkLocation);
                setNewLocation(getBetterLocation(newLocalGPS, newLocalNetwork), mLocationFetched);
            }
        } catch (Exception ex) {
            Log.e(TAG, ex.getMessage());
        }
        return mLocationFetched;
    }

    protected void startLocationUpdates() {
        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
    }

    public void startLocationFetching() {
        mGoogleApiClient.connect();
        if (mGoogleApiClient.isConnected()) {
            startLocationUpdates();
        }
    }

    public void pauseLocationFetching() {
        if (mGoogleApiClient.isConnected()) {
            LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
            mGoogleApiClient.disconnect();
        }

    }

    public void abortLocationFetching() {
        mGoogleApiClient.disconnect();

        // Remove the listener you previously added
        if (locationManager != null && locationListener != null) {
            if (Build.VERSION.SDK_INT >= 23 &&
                    ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                    ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                return;
            }
            try {
                locationManager.removeUpdates(locationListener);
                locationManager = null;
            } catch (Exception ex) {
                Log.e(TAG, ex.getMessage());

            }
        }
    }

    public void resetLocation() {
        mLocationFetched = null;
        mLastLocationFetched = null;
        networkLocation = null;
        gpsLocation = null;
    }

    //  Android M Permission check
    public void askLocationPermission() {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {


            if (ContextCompat.checkSelfPermission(mActivity, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
                    || ContextCompat.checkSelfPermission(mActivity, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                    ) {
                if (ActivityCompat.shouldShowRequestPermissionRationale(mActivity, Manifest.permission.ACCESS_COARSE_LOCATION)
                        || ActivityCompat.shouldShowRequestPermissionRationale(mActivity, Manifest.permission.ACCESS_FINE_LOCATION)) {

                    final AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
                    builder.setMessage("Please allow all permissions in App Settings for additional functionality.")
                            .setCancelable(false)
                            .setPositiveButton("Allow", new DialogInterface.OnClickListener() {
                                public void onClick(@SuppressWarnings("unused") final DialogInterface dialog, @SuppressWarnings("unused") final int id) {
                                    Toast.makeText(mContext, "Welcome", Toast.LENGTH_SHORT).show();
                                }
                            })
                            .setNegativeButton("Deny", new DialogInterface.OnClickListener() {
                                public void onClick(final DialogInterface dialog, @SuppressWarnings("unused") final int id) {
                                    mActivity.finish();
                                }
                            });
                    final AlertDialog alert = builder.create();
                    alert.show();

                } else
                    ActivityCompat.requestPermissions(mActivity, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION
                            , Manifest.permission.ACCESS_FINE_LOCATION
                    }, PERMISSION_REQUEST_CODE);

            }
        }
    }

    public void checkNetworkProviderEnable(int enforceActive) {
        locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);

        isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

        if (!isGPSEnabled && !isNetworkEnabled) {
            buildAlertMessageTurnOnLocationProviders("Your location providers seems to be disabled, please enable it", "OK", "Cancel");
        } else if (!isGPSEnabled && mForceNetworkProviders == LOCATION_PROVIDER_GPS_ONLY_RESTICTION) {
            buildAlertMessageTurnOnLocationProviders("Your GPS seems to be disabled, please enable it", "OK", "Cancel");
        } else if (!isNetworkEnabled && mForceNetworkProviders == LOCATION_PROVIDER_NETWORK_ONLY_RESTICTION) {
            buildAlertMessageTurnOnLocationProviders("Your Network location provider seems to be disabled, please enable it", "OK", "Cancel");
        }
        // getting network status

        if (!isGPSEnabled && !isNetworkEnabled) {
            Toast.makeText(mContext, "Location can't be fetched!", Toast.LENGTH_SHORT).show(); // show alert
            mActivity.finish();
        }
    }

    private void buildAlertMessageTurnOnLocationProviders(String message, String positiveButtonText, String negativeButtonText) {
        final AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
        builder.setMessage(message)
                .setCancelable(false)
                .setPositiveButton(positiveButtonText, new DialogInterface.OnClickListener() {
                    public void onClick(@SuppressWarnings("unused") final DialogInterface dialog, @SuppressWarnings("unused") final int id) {
                        Intent mIntent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                        mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        mContext.startActivity(mIntent);
                    }
                })
                .setNegativeButton(negativeButtonText, new DialogInterface.OnClickListener() {
                    public void onClick(final DialogInterface dialog, @SuppressWarnings("unused") final int id) {
                        mActivity.finish();
                    }
                });
        final AlertDialog alert = builder.create();
        alert.show();
    }


    public Location getLastKnownLocation() {
        locationProvider = LocationManager.NETWORK_PROVIDER;
        Location lastKnownLocation = null;
        // Or use LocationManager.GPS_PROVIDER
        if (Build.VERSION.SDK_INT >= 23 &&
                ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return lastKnownLocation;
        }
        try {
            lastKnownLocation = locationManager.getLastKnownLocation(locationProvider);
            return lastKnownLocation;
        } catch (Exception e) {
            Log.e(TAG, e.getMessage());
        }
        return lastKnownLocation;
    }

    public boolean isGooglePlayServicesAvailable() {
        int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(mContext);

        if (status == ConnectionResult.SUCCESS) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Determines whether one Location reading is better than the current Location fix
     *
     * @param location            The new Location that you want to evaluate
     * @param currentBestLocation The current Location fix, to which you want to compare the new one
     */
    protected Location getBetterLocation(Location location, Location currentBestLocation) {
        if (currentBestLocation == null) {
            // A new location is always better than no location
            return location;
        }

        // Check whether the new location fix is newer or older
        long timeDelta = location.getTime() - currentBestLocation.getTime();
        boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
        boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
        boolean isNewer = timeDelta > 0;

        // If it's been more than two minutes since the current location, use the new location
        // because the user has likely moved
        if (isSignificantlyNewer) {
            return location;
            // If the new location is more than two minutes older, it must be worse
        } else if (isSignificantlyOlder) {
            return currentBestLocation;
        }

        // Check whether the new location fix is more or less accurate
        int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
        boolean isLessAccurate = accuracyDelta > 0;
        boolean isMoreAccurate = accuracyDelta < 0;
        boolean isSignificantlyLessAccurate = accuracyDelta > 200;

        // Check if the old and new location are from the same provider
        boolean isFromSameProvider = isSameProvider(location.getProvider(),
                currentBestLocation.getProvider());

        // Determine location quality using a combination of timeliness and accuracy
        if (isMoreAccurate) {
            return location;
        } else if (isNewer && !isLessAccurate) {
            return location;
        } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
            return location;
        }
        return currentBestLocation;
    }

    /**
     * Checks whether two providers are the same
     */

    private boolean isSameProvider(String provider1, String provider2) {
        if (provider1 == null) {
            return provider2 == null;
        }
        return provider1.equals(provider2);
    }

    public boolean isLocationAccurate(Location location) {
        if (location.hasAccuracy()) {
            return true;
        } else {
            return false;
        }
    }

    public Location getStaleLocation() {
        if (mLastLocationFetched != null) {
            return mLastLocationFetched;
        }
        if (Build.VERSION.SDK_INT >= 23 &&
                ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return null;
        }
        if (mProviderType == SmartLocationManager.GPS_PROVIDER) {
            return locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
        } else if (mProviderType == SmartLocationManager.NETWORK_PROVIDER) {
            return locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
        } else {
            return getBetterLocation(locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER), locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER));
        }
    }
}

мы можем использовать это с активностью или фрагментом, здесь я использую это с активностью

import android.location.Location;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
import android.widget.Toast;

import com.example.raza.locationaware.location.LocationManagerInterface;
import com.example.raza.locationaware.location.SmartLocationManager;
import com.google.android.gms.location.LocationRequest;

public class LocationActivity extends AppCompatActivity implements LocationManagerInterface {

    public static final String TAG = LocationActivity.class.getSimpleName();

    SmartLocationManager mLocationManager;
    TextView mLocalTV, mLocationProviderTV, mlocationTimeTV;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_location);
        mLocationManager = new SmartLocationManager(getApplicationContext(), this, this, SmartLocationManager.ALL_PROVIDERS, LocationRequest.PRIORITY_HIGH_ACCURACY, 10 * 1000, 1 * 1000, SmartLocationManager.LOCATION_PROVIDER_RESTRICTION_NONE); // init location manager
        mLocalTV = (TextView) findViewById(R.id.locationDisplayTV);
        mLocationProviderTV = (TextView) findViewById(R.id.locationProviderTV);
        mlocationTimeTV = (TextView) findViewById(R.id.locationTimeFetchedTV);
    }

    protected void onStart() {
        super.onStart();
        mLocationManager.startLocationFetching();
    }

    protected void onStop() {
        super.onStop();
        mLocationManager.abortLocationFetching();
    }

    @Override
    protected void onPause() {
        super.onPause();
        mLocationManager.pauseLocationFetching();
    }

    @Override
    public void locationFetched(Location mLocal, Location oldLocation, String time, String locationProvider) {
        Toast.makeText(getApplication(), "Lat : " + mLocal.getLatitude() + " Lng : " + mLocal.getLongitude(), Toast.LENGTH_LONG).show();
        mLocalTV.setText("Lat : " + mLocal.getLatitude() + " Lng : " + mLocal.getLongitude());
        mLocationProviderTV.setText(locationProvider);
        mlocationTimeTV.setText(time);
    }
}

Надеюсь, это поможет, если вы можете предложить какие-либо улучшения, пожалуйста, напишите об этом на git . Спасибо.

Сайед Раза Мехди
источник
5

В GoogleSamples есть подробный пример с использованием последней версии FusedLocationProviderApi. К сожалению, большинство проголосовавших ответов устарели.

Следуйте приведенным ниже примерам для реализации сервисов определения местоположения с использованием FusedLocationProviderApi

https://github.com/googlesamples/android-play-location/tree/master/LocationUpdates

https://github.com/googlesamples/android-play-location/blob/master/LocationUpdates/app/src/main/java/com/google/android/gms/location/sample/locationupdates/MainActivity.java

karthikdivi
источник
3

Если вы создаете новые локационные проекты для Android, вы должны использовать новый Google Play местоположения в . Это намного точнее и намного проще в использовании.

Я работаю над проектом GPS трекера с открытым исходным кодом , GpsTracker, в течение нескольких лет. Я недавно обновил его для обработки периодических обновлений с мобильных телефонов Android, iOS, Windows Phone и Java ME . Он полностью функционален и делает то, что вам нужно, и имеет лицензию MIT .

Проект Android в GpsTracker использует новые сервисы Google Play, а также есть два серверных стека ( ASP.NET и PHP ), которые позволяют отслеживать эти телефоны.

nickfox
источник
3
Проблема в том, что не на всех устройствах есть Сервисы Google Play, включая любые нестандартные ПЗУ, которые его не используют. Если вы собираетесь использовать его, подготовьте запасной вариант к LocationManager.
Гейб Сечан
3

Для проверки местоположения вы можете использовать следующий код. Вы можете поместить его в свой onStart () основного действия и отобразить диалоговое окно с предупреждением, если return имеет значение false.

private boolean isLocationAccurate()
    {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
        {
            String provider = Settings.Secure
                    .getString(getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
            if (provider != null && !provider.contains("gps"))
            {
                return false;
            }
        }
        else
        {
            try
            {
                int status = Settings.Secure
                        .getInt(this.getContentResolver(), Settings.Secure.LOCATION_MODE);
                if (status != Settings.Secure.LOCATION_MODE_HIGH_ACCURACY)
                {
                    return false;
                }
            }
            catch (Settings.SettingNotFoundException e)
            {
                Log.e(TAG, e.getMessage());
            }
        }

        return true;
    }
Hesam
источник
3

Я получил очень точное местоположение с помощью FusedLocationProviderClient
( требуются сервисы Google Play )

Требуются разрешения

android.permission.ACCESS_FINE_LOCATION

android.permission.ACCESS_COARSE_LOCATION

зависимость

'Com.google.android.gms: игры-сервисы Откуда: 15.0.0'

Код Котлина

val client = FusedLocationProviderClient(this)
val location = client.lastLocation
location.addOnCompleteListener {
    // this is a lambda expression and we get an 'it' iterator to access the 'result'
    // it.result.latitude gives the latitude
    // it.result.longitude gives the longitude 
    val geocoder = Geocoder(applicationContext, Locale.getDefault())
    val address = geocoder.getFromLocation(it.result.latitude, it.result.longitude, 1)
    if (address != null && address.size > 0) {
        // Get the current city
        city = address[0].locality
    }
}
location.addOnFailureListener {
    // Some error in getting the location, let's log it
    Log.d("xtraces", it.message)
}
Палкеш Джайн
источник
3

Лучший способ получить местоположение ниже

// put dependancy
 implementation 'com.google.android.gms:play-services-location:11.0.4'

// PUT permissions in Menifest
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> 


// create a Java file as below

public class SingleShotLocationProvider {

  public static interface LocationCallback {
      public void onNewLocationAvailable(GPSCoordinates location);
  }

   // calls back to calling thread, note this is for low grain: if you want higher precision, swap the
   // contents of the else and if. Also be sure to check gps permission/settings are allowed.
   // call usually takes <10ms

  public static void requestSingleUpdate(final Context context, final LocationCallback callback) {
    final LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
    boolean isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
    if (isNetworkEnabled) {
        Criteria criteria = new Criteria();
        criteria.setAccuracy(Criteria.ACCURACY_COARSE);
        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

            return;
        }
        locationManager.requestSingleUpdate(criteria, new LocationListener() {
            @Override
            public void onLocationChanged(Location location) {
                callback.onNewLocationAvailable(new GPSCoordinates(location.getLatitude(), location.getLongitude()));
            }

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

            @Override
            public void onProviderEnabled(String provider) {
            }

            @Override
            public void onProviderDisabled(String provider) {
            }
        }, null);
     } else {
        boolean isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        if (isGPSEnabled) {
            Criteria criteria = new Criteria();
            criteria.setAccuracy(Criteria.ACCURACY_FINE);
            locationManager.requestSingleUpdate(criteria, new LocationListener() {
                @Override
                public void onLocationChanged(Location location) {
                    callback.onNewLocationAvailable(new GPSCoordinates(location.getLatitude(), location.getLongitude()));
                }

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


  // consider returning Location instead of this dummy wrapper class
  public static class GPSCoordinates {
     public float longitude = -1;
     public float latitude = -1;

     public GPSCoordinates(float theLatitude, float theLongitude) {
        longitude = theLongitude;
        latitude = theLatitude;
     }

     public GPSCoordinates(double theLatitude, double theLongitude) {
        longitude = (float) theLongitude;
        latitude = (float) theLatitude;
     }
  }

}
// FILE FINISHED


// FETCH LOCATION FROM ACTIVITY AS BELOW
public void getLocation(Context context) {
    MyApplication.log(LOG_TAG, "getLocation() ");

    SingleShotLocationProvider.requestSingleUpdate(context,
            new SingleShotLocationProvider.LocationCallback() {
                @Override
                public void onNewLocationAvailable(SingleShotLocationProvider.GPSCoordinates loc) {
                    location = loc;
                    MyApplication.log(LOG_TAG, "getLocation() LAT: " + location.latitude + ", LON: " + location.longitude);               
                }
            });
}
Арви Шелке
источник
2

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

Вы можете проверить это здесь: https://github.com/julioromano/RxLocation и использовать его или его исходный код в качестве примеров для вашей реализации.

Марко Романо
источник
Это хорошее решение, но не лучшее, не работает большую часть времени. Я не получаю результаты сразу после нажатия кнопки.
Асиф Али
@AsifAli Если вы обнаружили ошибку, пожалуйста, откройте вопрос или отправьте PR.
Марко Романо
Эта библиотека, потому что в этой библиотеке отсутствует класс AbstractSafeParcelable
Викаш Параджули
2

Простой код поиска записи в методе определения местоположения

public void onLocationChanged(Location location) {
    if (mCurrLocationMarker != null) {
        mCurrLocationMarker.remove();
    }


    //Place current location marker
    LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
    MarkerOptions markerOptions = new MarkerOptions();
    markerOptions.position(latLng);
    markerOptions.title("Current Position");
    markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
    mCurrLocationMarker = mMap.addMarker(markerOptions);

    //move map camera
    mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
    mMap.animateCamera(CameraUpdateFactory.zoomTo(18));

    PolylineOptions pOptions = new PolylineOptions()
            .width(5)
            .color(Color.GREEN)
            .geodesic(true);
    for (int z = 0; z < routePoints.size(); z++) {
        LatLng point = routePoints.get(z);
        pOptions.add(point);
    }
    line = mMap.addPolyline(pOptions);
    routePoints.add(latLng);
}
Давал Шингала
источник
2

Я рекомендую использовать Smart Location Library
Очень проста в использовании, и она хорошо оборачивает логику расположения.

Для запуска службы определения местоположения:

SmartLocation.with(context).location()
    .start(new OnLocationUpdatedListener() { ... });

Если вы просто хотите получить одно местоположение (не периодическое), вы можете просто использовать модификатор oneFix. Пример:

SmartLocation.with(context).location()
    .oneFix()
    .start(new OnLocationUpdatedListener() { ... });
Мортен Холмгаард
источник
0

Простой и легкий способ,

Получить местоположение с помощью https://github.com/sachinvarma/EasyLocation .

Шаг 1: Просто позвоните

new EasyLocationInit(MainActivity.this, timeInterval, fastestTimeInterval, runAsBackgroundService);

временной интервал -> setInterval (long) (inMilliSeconds) означает - установить интервал, в котором вы хотите получить местоположения.

fastestTimeInterval -> setFastestInterval (long) (inMilliSeconds) означает - если местоположение доступно раньше, вы можете его получить. (т.е. другое приложение использует службы определения местоположения).

runAsBackgroundService = True -> (Служба будет работать в фоновом режиме и часто обновляется (в соответствии с timeInterval и fastestTimeInterval)) runAsBackgroundService = False -> (Служба getDestroyed после успешного обновления местоположения)

Шаг 2: Подготовьте подписчиков EventBus: объявите и аннотируйте свой метод подписки, при желании укажите режим потока:

например:

     @Override
     public void onStart() {
         super.onStart();
         EventBus.getDefault().register(this);
     }

     @Override
     public void onStop() {
         super.onStop();
         EventBus.getDefault().unregister(this);
     }

  @SuppressLint("SetTextI18n")
  @Subscribe
  public void getEvent(final Event event) {

    if (event instanceof LocationEvent) {
      if (((LocationEvent) event).location != null) {
        ((TextView) findViewById(R.id.tvLocation)).setText("The Latitude is "
          + ((LocationEvent) event).location.getLatitude()
          + " and the Longitude is "
          + ((LocationEvent) event).location.getLongitude());
      }
    }
  }

Это все.

Надеюсь, это поможет кому-то в будущем.

Сачин Варма
источник
0

Апрель 2020

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

Согласно официальной документации , последнее известное местоположение может быть нулевым в случае:

  • Расположение отключено в настройках устройства. Как это очищает кеш.
  • Устройство никогда не записывало свое местоположение. (Новое устройство)
  • Сервисы Google Play на устройстве перезапустились.

В этом случае вам необходимо requestLocationUpdates и получить новое местоположение в LocationCallback .

Следующими шагами ваше последнее известное местоположение никогда не будет нулевым.


Предварительное условие : библиотека EasyPermission


Шаг 1: В файле манифеста добавьте это разрешение

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Шаг 2:

    override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    //Create location callback when it's ready.
    createLocationCallback()

    //createing location request, how mant request would be requested.
    createLocationRequest()

    //Build check request location setting request
    buildLocationSettingsRequest()

    //FusedLocationApiClient which includes location 
    mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
    //Location setting client
    mSettingsClient = LocationServices.getSettingsClient(this)

    //Check if you have ACCESS_FINE_LOCATION permission
    if (!EasyPermissions.hasPermissions(
            this@MainActivity,
            Manifest.permission.ACCESS_FINE_LOCATION)) {
        requestPermissionsRequired()
    }
    else{
        //If you have the permission we should check location is opened or not
        checkLocationIsTurnedOn()
    }

}

Шаг 3: Создайте необходимые функции для вызова в onCreate ()

private fun requestPermissionsRequired() {
    EasyPermissions.requestPermissions(
        this,
        getString(R.string.location_is_required_msg),
        LOCATION_REQUEST,
        Manifest.permission.ACCESS_FINE_LOCATION
    )
}

private fun createLocationCallback() {
    //Here the location will be updated, when we could access the location we got result on this callback.
    mLocationCallback = object : LocationCallback() {
        override fun onLocationResult(locationResult: LocationResult) {
            super.onLocationResult(locationResult)
            mCurrentLocation = locationResult.lastLocation
        }
    }
}

private fun buildLocationSettingsRequest() {
    val builder = LocationSettingsRequest.Builder()
    builder.addLocationRequest(mLocationRequest!!)
    mLocationSettingsRequest = builder.build()
    builder.setAlwaysShow(true)
}

private fun createLocationRequest() {
    mLocationRequest = LocationRequest.create()
    mLocationRequest!!.interval = 0
    mLocationRequest!!.fastestInterval = 0
    mLocationRequest!!.numUpdates = 1
    mLocationRequest!!.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
}

public fun checkLocationIsTurnedOn() { // Begin by checking if the device has the necessary location settings.
    mSettingsClient!!.checkLocationSettings(mLocationSettingsRequest)
        .addOnSuccessListener(this) {
            Log.i(TAG, "All location settings are satisfied.")
            startLocationUpdates()
        }
        .addOnFailureListener(this) { e ->
            val statusCode = (e as ApiException).statusCode
            when (statusCode) {
                LocationSettingsStatusCodes.RESOLUTION_REQUIRED -> {
                    try {
                        val rae = e as ResolvableApiException
                        rae.startResolutionForResult(this@MainActivity, LOCATION_IS_OPENED_CODE)
                    } catch (sie: IntentSender.SendIntentException) {
                    }
                }
                LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE -> {
                    mRequestingLocationUpdates = false
                }
            }
        }
}

private fun startLocationUpdates() {
    mFusedLocationClient!!.requestLocationUpdates(
        mLocationRequest,
        mLocationCallback, null
    )
}

Шаг 4:

Обработайте обратные вызовы в onActivityResult () после того, как убедитесь, что местоположение открыто или пользователь принимает его.

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    when (requestCode) {
        LOCATION_IS_OPENED_CODE -> {
            if (resultCode == AppCompatActivity.RESULT_OK) {
                Log.d(TAG, "Location result is OK")
            } else {
                activity?.finish()
            }
        }
}

Шаг 5: Получить последнее известное местоположение из FusedClientApi

override fun onMapReady(map: GoogleMap) {
    mMap = map
    mFusedLocationClient.lastLocation.addOnSuccessListener {
        if(it!=null){
            locateUserInMap(it)
        }
    }

}
   private fun locateUserInMap(location: Location) {
    showLocationSafetyInformation()
    if(mMap!=null){
        val currentLocation = LatLng(location.latitude,location.longitude )
        addMarker(currentLocation)
    }
}


private fun addMarker(currentLocation: LatLng) {
    val cameraUpdate = CameraUpdateFactory.newLatLng(currentLocation)
    mMap?.clear()
    mMap?.addMarker(
        MarkerOptions().position(currentLocation)
            .title("Current Location")
    )
    mMap?.moveCamera(cameraUpdate)
    mMap?.animateCamera(cameraUpdate)
    mMap?.setMinZoomPreference(14.0f);
}

Я надеюсь, что это поможет.

Счастливое кодирование 🤓

MustafaKhaled
источник