Почему мой OnLocationChanged() никогда не вызван? - программирование
Подтвердить что ты не робот

Почему мой OnLocationChanged() никогда не вызван?

То, что я пытаюсь сделать:

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

В чем моя проблема:

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

location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER)

Но я не уверен, где проблема.

Связанный фрагмент кода:

В моем Activity у меня есть:

    locationDetector = new LocationDetector(MapSelectionActivity.this);
    // try to get the current location
    if (locationDetector.checkLocationServiceAvailability()) {
        location = locationDetector.getLocation();
        if (location != null) {
            latitude = location.getLatitude();
            longitude = location.getLongitude();
        }
        Log.d("MapSelectionActivity", latitude + " " + longitude);
        //locationDetector.stopLocalization(); // stop the localization to save the energy
    } else { // if no location service, requires the user to turn GPS on
        locationDetector.showSettingsAlert();
    }

Мой LocationDetector класс выглядит следующим образом:

public final class LocationDetector implements LocationListener {

    private final Context mContext;

    private boolean isNetworkEnabled = false;
    private boolean isGPSEnabled = false;
    private boolean canGetLocation = false;

    private Location location;
    private String providerUsed;

    // The minimum distance to change Updates in meters
    private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 0; // 0 meters
    // The minimum time between updates in milliseconds
    private static final long MIN_TIME_BW_UPDATES = (long) (1000 * 60 * 0.5); // 0.5 minute

    // Declaring a Location Manager
    protected LocationManager locationManager;

    // constructor
    public LocationDetector(Context context) {

        this.mContext = context;

        locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
    }

    // NOTE call  checkLocationServiceAvailability(); first before calling this!
    public Location getLocation() {
// I SUSPECT SOMETHING IS WRONG HERE
        if (isNetworkEnabled) { // use network

            locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
            Log.d("LocationDetector", "Using Network");
            if (locationManager != null) {
                location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
            }

            providerUsed = "Network";

        } else if (isGPSEnabled) { // use GPS

            if (location == null) {
                locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                Log.d("LocationDetector", "Using GPS");
                if (locationManager != null) {
                    location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                }
            }

            providerUsed = "GPS";

        } else { // neither the network nor the GPS is on

            providerUsed = null;

            Toast.makeText(mContext, "Location service is unavaliable", Toast.LENGTH_SHORT).show();
        }

        return location;
    }

    // call this to restart requesting the detecting
    public void startLocalization() {

        if (locationManager != null) {
            locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
            locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
        }
    }

    // call this to stop the detecting to save power
    public void stopLocalization() {

        if (locationManager != null) {
            locationManager.removeUpdates(LocationDetector.this);
        }
    }

    // check location service availability
    public boolean checkLocationServiceAvailability() {

        // check GPS on or off
        isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        // check Internet access
        ConnectivityManager connectivityManager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo netInfo = connectivityManager.getActiveNetworkInfo();
        if (netInfo != null && netInfo.isConnected()) {
            isNetworkEnabled = true;
        } else {
            isNetworkEnabled = false;
        }

        if (isGPSEnabled || isNetworkEnabled) {
            canGetLocation = true;
        } else {
            canGetLocation = false;
        }

        return canGetLocation;
    }

    public String getLocationProvider() {

        return providerUsed;
    }

    // show alert dialog to direct the users to the settings
    public void showSettingsAlert() {

        AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);

        // make it uncancellable
        alertDialog.setCancelable(false);

        // Setting Dialog Title
        alertDialog.setTitle("Forgot to turn GPS on?");

        // Setting Dialog Message
        alertDialog.setMessage("Currently there is no Internet access.\n\nLocalization requires GPS when Internet is unavailiable.\n\nDo you want to enable GPS so as to proceed?");

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

                Toast.makeText(mContext, "After enabling GPS, press the physical 'Back' button to return", Toast.LENGTH_LONG).show();
            }
        });

        // on pressing cancel button
        alertDialog.setNegativeButton("No", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                dialog.cancel();

                Toast.makeText(mContext, "No location service, please choose map manually", Toast.LENGTH_LONG).show();
            }
        });

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

    @Override
    public void onLocationChanged(Location _location) {
// IT NEVER GETS CALLED
        location = _location;

        // update the text view
        MapSelectionActivity.coordinatesTextView.setText("(" + Math.round(location.getLatitude() * 1000) / 1000.0 + ", " + Math.round(location.getLongitude() * 1000) / 1000.0 + ")");

        // update the marker on Google Maps
        MapSelectionActivity.googleMap.clear();
        MapSelectionActivity.googleMap.addMarker(new MarkerOptions().position(new LatLng(location.getLatitude(), location.getLongitude())).title("I am here!"));
        MapSelectionActivity.googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location.getLatitude(), location.getLongitude()), 15)); // 15 is the approporiate zooming level

        // re-suggest the map
        int recommendedMapSequenceNumber = MapSelectionActivity.mapDatabase.getMapSequenceNumber(location.getLatitude(), location.getLongitude());
        MapSelectionActivity.recommendedMapTextView.setTextColor(Color.parseColor("red"));
        if (recommendedMapSequenceNumber == -1) { // the so-called nearest is still too far

            Toast.makeText(mContext, "Please manually select one to proceed", Toast.LENGTH_LONG).show();
            MapSelectionActivity.recommendedMapTextView.setText("No recommended maps");
            MapSelectionActivity.autoSelectButton.setEnabled(false);
        } else { // suggest a map

            Toast.makeText(mContext, "One suitable map found", Toast.LENGTH_SHORT).show();
            MapSelectionActivity.recommendedMapTextView.setText(MapSelectionActivity.mapDatabase.getMapName(recommendedMapSequenceNumber));
        }

        Toast.makeText(mContext, "New location detected", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onProviderDisabled(String provider) {
    }

    @Override
    public void onProviderEnabled(String provider) {
    }

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

    }

}

Я никогда не вижу Toast в onLocationChanged(), а это значит, что он никогда не вызывается! Также с карты я вижу, что позиция не обновляется.

4b9b3361

Ответ 1

Это правильно, вы можете столкнуться с проблемой оборудования. Пожалуйста, установите на устройстве приложение: GPS STATUS, чтобы убедиться, что ваш GPS работает нормально!

Ответ 2

locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, это);

Для этой строки

MIN_DISTANCE_CHANGE_FOR_UPDATES = 0 м.

MIN_TIME_BW_UPDATES = 1000 секунд.

Подойдя к вашему вопросу, onLocationChanged() будет вызываться, если текущее обновление местоположения не соответствует последнему известному местоположению.

Обновленное местоположение будет изменено для каждого minTime (в моем случае 1000 миллисекунд), а также если устройство переместило расстояние minDistance (в моем случае 0 метров).

Надеюсь, вы поймете это.

Ответ 3

Поскольку это, похоже, является общей проблемой при получении Android Locations, я поставлю быстрый контрольный список общих исправлений:


  • Проверьте свой манифест!

    Одна из наиболее распространенных проблем заключается в том, что правильные разрешения никогда не предоставлялись. Если вы используете GPS (с или без сети), используйте <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>, иначе используйте <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>. Google FusedLocationApi требует ACCESS_FINE_LOCATION.


  1. (для Android 6+) Проверить разрешения во время выполнения!

    Проверить и запросить разрешения! Если вам никогда не дадут разрешения, вы столкнетесь с аварийными ситуациями или, что еще хуже (если вы поймаете все исключения), вы ничего не увидите! Не имеет значения, предоставит ли пользователь разрешение в начале приложения, всегда проверяйте, есть ли у вас разрешения для всех вызовов. Пользователь может легко перейти к своим настройкам и отозвать их.


    1. Дважды проверьте свой код!

      Вы уверены, что проходите в правом слушателе? Добавили ли вы, что BroadcastReceiver или IntentService в ваш манифест? Используете ли вы PendingIntent.getService() в классе BroadcastReceiver или getBroadcast() в классе IntentService? Вы уверены, что не отменили регистрацию своего слушателя где-то еще в своем коде сразу после запроса?


      1. Проверьте настройки устройства!

        Очевидно, убедитесь, что у вас есть службы определения местоположения.

        введите описание изображения здесь

        Если вы используете сетевые службы, включили ли вы "Сканирование всегда доступно"? У вас установлен режим "Лучшее" ( "Высокая точность" ) или "Аккумулятор" ( "Только для сети" )?

        введите описание изображения здесь

        Если вы используете GPS, включили ли вы режим "Лучшее" ( "Высокая точность" ) или "Только устройство" в режиме местоположения?

        введите описание изображения здесь


        1. Дважды проверьте свой код!

          Да, это здесь дважды. Вы пытались использовать LocationListener вместо PendingIntent или наоборот, чтобы убедиться, что вы действительно реализовали LocationManager правильно? Вы уверены, что запрос местоположения не удаляется в какой-либо части жизненного цикла активности или службы, который вы не ожидали?


          1. Проверьте свое окружение!

            Вы тестируете GPS на первом этаже здания в центре Сан-Франциско? Проверяете ли вы сетевые местоположения в середине нигде? Вы работаете в секретном подземном бункере, лишенном всех радиосигналов, удивляясь, почему ваше устройство не получает место? Всегда проверяйте свое окружение при попытке устранить проблемы с местоположением!


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