Служба Android не обновляет местоположение

Мне нужно обновлять плавное местоположение каждую 1 минуту и ​​на каждые 5 метров смещения (я знаю, что это плохая практика, но ради тестирования и отображения в журнале), и я запускаю службу с помощью кнопки. Нажатие, как только кнопка нажата, я получил местоположение в logcat, но только один раз. В соответствии с классом обслуживания onLocationChanged должен вызываться каждую минуту, но он никогда не вызывается снова, даже мой GPS включается почти каждую минуту, а затем выключается через некоторое время, но местоположение все равно отсутствует. Обновление в Logcat. Мне нужен класс обслуживания, чтобы сохранить местоположение обновления, не влияя на пользовательский интерфейс или основной поток.

Вот logcat, который показывает обновление местоположения только один раз

09-16 03:13:37.125 10419-10419/com.example.com.pro_working1 D/===Location Service===: Service onConnected Calling
09-16 03:13:37.125 10419-10419/com.example.com.pro_working1 D/===Location Service===: Start Location Update is Calling
09-16 03:13:38.315 10419-10419/com.example.com.pro_working1 D/===Location Service===: Service OnLocationChanged Calling
09-16 03:13:38.315 10419-10419/com.example.com.pro_working1 D/===Location Service===: Here is Updated Locations: Latitude 28.5XXXXX Longitude 77.2XXXXX
09-16 03:13:38.315 10419-10419/com.example.com.pro_working1 D/===Location Service===: Sending Location Starting  Accuracy is: 37.5

Вот мой класс обслуживания

public class Location_Service_background extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
    public static final String TAG = "===Location Service===";
    GoogleApiClient apiClient;
    Location mCurrentLocation;
    LocationRequest locationRequest;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        GoogleApiSetup();
        RequestLocationUpdates();
        Log.d(TAG,"OnStartCommand Is Calling ");
        return START_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }



    @Override
    public void onCreate() {
        super.onCreate();

    }


    @Override
    public void onDestroy() {
        super.onDestroy();
        if (apiClient.isConnected()){
            Log.d(TAG,"Service On Destroy Calling and apiClient is Connected");
            StopLocationUpdates();
            apiClient.disconnect();
        }
    }

    @Override
    public void onLowMemory() {
        super.onLowMemory();
    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {
        Log.d(TAG,"Service onConnected Calling");
        if (mCurrentLocation != null) {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                return;
            }
             mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(apiClient);

        }
        else {
            Log.d(TAG,"Start Location Update is Calling");
            StartLocationUpdate();
        }
    }

    @Override
    public void onConnectionSuspended(int i) {
        Log.d(TAG,"Service OnConnectionSuspended Calling");
        apiClient.connect();
    }

    @Override
    public void onLocationChanged(Location location) {
        Log.d(TAG,"Service OnLocationChanged Calling");
        mCurrentLocation=location;
        Log.d(TAG,"Here is Updated Locations: Latitude "+mCurrentLocation.getLatitude()+"Longitude "+mCurrentLocation.getLongitude());
        String Latitude= String.valueOf(mCurrentLocation.getLatitude());
        String Longitude=String.valueOf(mCurrentLocation.getLongitude());
        String Accuracy=String.valueOf(mCurrentLocation.getAccuracy());
        Log.d(TAG,"Sending Location Starting"+" "+" Accuracy is: "+mCurrentLocation.getAccuracy());


    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        Log.d(TAG,"Connection Failed Called "+connectionResult);
    }



    private synchronized  void GoogleApiSetup() {
        apiClient = new GoogleApiClient.Builder(this)
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();
        apiClient.connect();
    }

    private void RequestLocationUpdates() {
        locationRequest = new LocationRequest();
        //1 Min = 60 seconds AND 1000 milliseconds in 1 second
        locationRequest.setInterval(60 * 1000);//5 Min 300 x 1000=300000
        locationRequest.setFastestInterval(60 * 1000);//2 Min
        locationRequest.setSmallestDisplacement(5);
        locationRequest.setMaxWaitTime(60*1000);
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    }

    private void StopLocationUpdates() {
        LocationServices.FusedLocationApi.removeLocationUpdates(apiClient, this);
    }

    private void StartLocationUpdate() {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

            return;
        }
        if (apiClient.isConnected()) {
            LocationServices.FusedLocationApi.requestLocationUpdates(apiClient, locationRequest, this);
        }
        else {
            Log.d(TAG,"GoogleApiClient is not connected yet.Please Try Again");
            apiClient.connect();
        }
    }


}

person androidXP    schedule 15.09.2016    source источник
comment
Попробуйте без использования setsmalestdisplacement и посмотрите, что получится.   -  person Nerdy Bunz    schedule 16.09.2016
comment
Он показывает вызовы на onLocationUpdate без setsmallestdisplacement , но как я могу использовать регулярное обновление с наименьшим смещением. Спасибо за помощь   -  person androidXP    schedule 16.09.2016


Ответы (3)


Надеюсь, это поможет спасти кого-то от разочарования, которое я пережил по этой проблеме. Я использую FusedLocationAPI для запроса обновлений местоположения и GoogleApiClient. Я также делаю это из службы.

Вы не получаете никаких обновлений местоположения в заданный интервал времени, потому что setSmallestDisplacement() имеет абсолютный приоритет над другими параметрами. Так что даже если у вас есть

locationRequestTimeInterval = LocationRequest.create()
    .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
    .setInterval(1)    
    .setFastestInterval(1)    
    .setMaxWaitTime(1)    
    .setSmallestDisplacement(5);

это НИКОГДА не будет запущено, пока не будет выполнен параметр наименьшего смещения.

Решение этой проблемы состоит в том, чтобы создать два отдельных запроса LocationRequest... один, который связан только с расстоянием, и один, который связан только со временем, и использовать свой единственный GoogleApiClient для создания двух команд requestLocationUpdates, одного с использованием Time LocationRequest и другой с помощью Distance LocationRequest.

Итак, ваши 2 LocationRequests выглядят так:

locationRequestDistanceInterval = LocationRequest.create()
            .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
            .setFastestInterval(0) // This MUST be set, otherwise no updates
            .setSmallestDisplacement(LOCATION_REQUEST_MIN_DISTNACE);

locationRequestTimeInterval = LocationRequest.create()
            .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
            .setInterval(PROVIDER_GPS_UPDATE_TIME_INTERVAL)
            .setFastestInterval(PROVIDER_GPS_UPDATE_TIME_INTERVAL);
  • обратите внимание, что значение setFastestInterval() ДОЛЖНО быть установлено в запросе расстояния, иначе запрос расстояния не будет запущен. Это не обязательно должно быть 0, но это поле должно быть установлено.

Затем в вашем GoogleApiClients onConnected() вы можете добавить два вызова requestLocationUpdates().

LocationServices.FusedLocationApi.requestLocationUpdates(
    mLocationClient, 
    locationRequestDistanceInterval, 
    new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {
            // Handle your Distance based updates
        }
    }
);

LocationServices.FusedLocationApi.requestLocationUpdates(
    mLocationClient, 
    locationRequestTimeInterval, 
    new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {
            // Handle your Time based updates
        }
    }
);  

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

person RH201    schedule 11.05.2017
comment
.setFastestInterval(0) // This MUST be set, otherwise no updates Спасибо за это, smallDisplacement не сработал, и в документах об этом не упоминается. - person laszlo; 09.03.2020

Предполагая, что вы на самом деле перемещаете устройство более чем на 5 метров между ожидаемыми обновлениями, я думаю, что может быть проблема с классом LocationRequest, где метод setSmallestDisplacement() просто не работает должным образом... или, по крайней мере, это не работает, как ожидалось. (Я видел эти проблемы в других сообщениях).

Вы всегда можете проверить расстояние самостоятельно, удалив setSmallestDisplacement() и вместо этого выполнив:

onLocationChanged() {
    double distance = // [ calculate distance between current lat/long and previous lat/long ]
    if (distance > 5 meters) {
        // do your normal onLocationChanged() code here
    }
}

Также существует вероятность того, что по какой-то причине FusedLocationProvider не может получить доступ к вашему GPS и вместо этого использует Wi-Fi или сотовую вышку... в этом случае 5 м слишком мало для указания расстояния. В ваших журналах указано, что точность составляет 37,5 метра, так что это не кажется достаточно точным, чтобы измерять 5 метров. Итак... может быть, в вашем манифесте не установлено разрешение на доступ FINE?

Также может быть проблема в том, что разрешения во время выполнения не выполняются должным образом? Вы можете временно установить целевой SDK на 22, чтобы проверить это.

person Nerdy Bunz    schedule 16.09.2016
comment
Я проверяю его в помещении, поэтому точность такая высокая, и у меня есть разрешение на точное определение местоположения, поэтому GPS включен, грубое местоположение не имеет доступа к GPS. Если я установлю обновление своего местоположения на 5 метров, это не должно останавливать обновление местоположения каждый 1 минута. Это похоже на обновление местоположения каждые 1 минуту или каждые 5 метров. Если 5 метров не пересекаются, то нужно обновлять каждую 1 минуту, но оно не обновляется, когда я использую setsmallestdisplacement , и, как вы предлагаете, рассчитать расстояние между 2 точками невозможно - person androidXP; 16.09.2016
comment
Потому что в реальных условиях я должен установить интервал длиной 10 или 15 минут, и что, если пользователь переместится на несколько миль за этот период времени, я потеряю местоположение, которое он путешествовал между этими периодами времени, поэтому мне нужно придерживаться метода API для отправки местоположения после этого х метров - person androidXP; 16.09.2016
comment
К сожалению, я не понял, что вы понимаете, как работает метод setdisplacement. Насколько я понимаю, этот метод означает: запускать метод onLocationChanged только в том случае, если пользователь прошел не менее X метров с момента предыдущего запуска. Это НЕ означает: стрелять каждые 5 метров, потому что это потребует от телефона постоянного мониторинга/вычисления местоположения, чего вы пытаетесь избежать, чтобы сэкономить заряд батареи, создав интервал. - person Nerdy Bunz; 17.09.2016
comment
Установите минимальное смещение между обновлениями местоположения в метрах. Эта строка взята из официальной документации Android. Установите минимальное смещение между обновлением местоположения пользователя/устройства, и вам также следует проверить Last API под названием Location Manager для получения дополнительной информации о том, как Android отправляет обновляет ПРОЧИТАЙТЕ эту строку там третье - минимальное изменение расстояния - person androidXP; 19.09.2016
comment
? Я не знаю, как еще это объяснить. Если вы заставите его работать так, как вы намеревались, пожалуйста, обновите здесь. - person Nerdy Bunz; 19.09.2016

небольшая помощь, кто знает, что это может быть использовано

    int jarak = 10;
    int interval = 5;


    LocationRequest request = new LocationRequest();
    request.setInterval(interval*1000); //update lokasi 10 detik
    request.setFastestInterval(interval*1000); //dapat update dari aplikasi lain yg lebih cepat 10 detik
    //request.setSmallestDisplacement(1); //diupdate jika berpindah 1 meter
    request.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);


    FusedLocationProviderClient client = LocationServices.getFusedLocationProviderClient(this);
    int permission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
    if(permission == PackageManager.PERMISSION_GRANTED) {



        client.requestLocationUpdates(request, new LocationCallback() {

            @Override
            public void onLocationResult(LocationResult locationResult) {
                List<Location> locationList = locationResult.getLocations();
                if (locationList.size() > 0) {
                    Location locationCurrent = locationList.get(locationList.size() - 1);


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

                    double lastlatitude = Double.parseDouble(prefs.getString("lastlatitude","0"));
                    double lastlongitude = Double.parseDouble(prefs.getString("lastlongitude","0"));

                    Location startPoint=new Location("LokasiA");
                    startPoint.setLatitude(latitude);
                    startPoint.setLongitude(longitude);

                    Location endPoint = new Location("LokasiB");
                    endPoint.setLatitude(lastlatitude);
                    endPoint.setLongitude(lastlongitude);

                    double distance = startPoint.distanceTo(endPoint);

                    Log.d(tag, "location update last " + endPoint);
                    if(distance > jarak) {
                        Log.d(tag, "location update new" + startPoint);
                        Log.d(tag, "location dest " + distance);

                        SharedPreferences.Editor editor = prefs.edit();
                        editor.putString("lastlatitude", String.valueOf(latitude));
                        editor.putString("lastlongitude", String.valueOf(longitude));
                        editor.apply();



                        Log.i("getLatitude:",String.valueOf(locationCurrent.getLatitude()) );
                        Log.i("getLongitude:",String.valueOf(locationCurrent.getLongitude()) );


                    }

                }


            }
        },null);
    }
person EKO HENDRATNO    schedule 05.04.2021