Android Query - определение местоположения

Я использую Android Query для определения местоположения пользователя.

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

В чем может быть проблема здесь?

public class LocationHelper {
    private Context mContext;
    private double latitude;
    private double longitude;

    public LocationHelper(Context mContext) {
        this.mContext = mContext;
        location_ajax();
    }

    public double getLatitude() {
        return latitude;
    }

    public double getLongitude() {
        return longitude;
    }

    private void location_ajax() {
        // Get the location
        LocationAjaxCallback cb = new LocationAjaxCallback();
        cb.weakHandler(this, "locationCb");
        cb.async(mContext);
    }

    public void locationCb(String url, Location loc, AjaxStatus status) {
        if (loc != null) {
            //Toast.makeText(mContext, loc.toString(), Toast.LENGTH_LONG).show();
            this.latitude = loc.getLatitude();
            this.longitude = loc.getLongitude();            
        } else {
            Toast.makeText(mContext, mContext.getString(R.string.msg_could_not_retrieve_location), Toast.LENGTH_LONG).show();
        }
    }   
}

Logcat:

03-19 23:03:17.146: W/AQuery(29954): reporting:java.lang.reflect.InvocationTargetException
03-19 23:03:17.146: W/AQuery(29954):    at java.lang.reflect.Method.invokeNative(Native Method)
03-19 23:03:17.146: W/AQuery(29954):    at java.lang.reflect.Method.invoke(Method.java:511)
03-19 23:03:17.146: W/AQuery(29954):    at com.androidquery.util.AQUtility.invokeMethod(AQUtility.java:206)
03-19 23:03:17.146: W/AQuery(29954):    at com.androidquery.util.AQUtility.invokeHandler(AQUtility.java:183)
03-19 23:03:17.146: W/AQuery(29954):    at com.androidquery.callback.AbstractAjaxCallback.callback(AbstractAjaxCallback.java:577)
03-19 23:03:17.146: W/AQuery(29954):    at com.androidquery.callback.LocationAjaxCallback.failure(LocationAjaxCallback.java:192)
03-19 23:03:17.146: W/AQuery(29954):    at com.androidquery.callback.LocationAjaxCallback.access$3(LocationAjaxCallback.java:183)
03-19 23:03:17.146: W/AQuery(29954):    at com.androidquery.callback.LocationAjaxCallback$Listener.run(LocationAjaxCallback.java:308)
03-19 23:03:17.146: W/AQuery(29954):    at java.util.Timer$TimerImpl.run(Timer.java:284)
03-19 23:03:17.146: W/AQuery(29954): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
03-19 23:03:17.146: W/AQuery(29954):    at android.os.Handler.<init>(Handler.java:121)
03-19 23:03:17.146: W/AQuery(29954):    at android.widget.Toast$TN.<init>(Toast.java:361)
03-19 23:03:17.146: W/AQuery(29954):    at android.widget.Toast.<init>(Toast.java:97)
03-19 23:03:17.146: W/AQuery(29954):    at android.widget.Toast.makeText(Toast.java:254)
03-19 23:03:17.146: W/AQuery(29954):    at uk.ac.gla.project.helpers.LocationHelper.locationCb(LocationHelper.java:46)
03-19 23:03:17.146: W/AQuery(29954):    ... 9 more
03-19 23:03:20.001: W/AQuery(29954): reporting:java.lang.reflect.InvocationTargetException
03-19 23:03:20.001: W/AQuery(29954):    at java.lang.reflect.Method.invokeNative(Native Method)
03-19 23:03:20.001: W/AQuery(29954):    at java.lang.reflect.Method.invoke(Method.java:511)
03-19 23:03:20.001: W/AQuery(29954):    at com.androidquery.util.AQUtility.invokeMethod(AQUtility.java:206)
03-19 23:03:20.001: W/AQuery(29954):    at com.androidquery.util.AQUtility.invokeHandler(AQUtility.java:183)
03-19 23:03:20.001: W/AQuery(29954):    at com.androidquery.callback.AbstractAjaxCallback.callback(AbstractAjaxCallback.java:577)
03-19 23:03:20.001: W/AQuery(29954):    at com.androidquery.callback.LocationAjaxCallback.failure(LocationAjaxCallback.java:192)
03-19 23:03:20.001: W/AQuery(29954):    at com.androidquery.callback.LocationAjaxCallback.access$3(LocationAjaxCallback.java:183)
03-19 23:03:20.001: W/AQuery(29954):    at com.androidquery.callback.LocationAjaxCallback$Listener.run(LocationAjaxCallback.java:308)
03-19 23:03:20.001: W/AQuery(29954):    at java.util.Timer$TimerImpl.run(Timer.java:284)
03-19 23:03:20.001: W/AQuery(29954): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
03-19 23:03:20.001: W/AQuery(29954):    at android.os.Handler.<init>(Handler.java:121)
03-19 23:03:20.001: W/AQuery(29954):    at android.widget.Toast$TN.<init>(Toast.java:361)
03-19 23:03:20.001: W/AQuery(29954):    at android.widget.Toast.<init>(Toast.java:97)
03-19 23:03:20.001: W/AQuery(29954):    at android.widget.Toast.makeText(Toast.java:254)
03-19 23:03:20.001: W/AQuery(29954):    at uk.ac.gla.project.helpers.LocationHelper.locationCb(LocationHelper.java:46)
03-19 23:03:20.001: W/AQuery(29954):    ... 9 more
03-19 23:03:20.671: W/AQuery(29954): reporting:java.lang.reflect.InvocationTargetException
03-19 23:03:20.671: W/AQuery(29954):    at java.lang.reflect.Method.invokeNative(Native Method)
03-19 23:03:20.671: W/AQuery(29954):    at java.lang.reflect.Method.invoke(Method.java:511)
03-19 23:03:20.671: W/AQuery(29954):    at com.androidquery.util.AQUtility.invokeMethod(AQUtility.java:206)
03-19 23:03:20.671: W/AQuery(29954):    at com.androidquery.util.AQUtility.invokeHandler(AQUtility.java:183)
03-19 23:03:20.671: W/AQuery(29954):    at com.androidquery.callback.AbstractAjaxCallback.callback(AbstractAjaxCallback.java:577)
03-19 23:03:20.671: W/AQuery(29954):    at com.androidquery.callback.LocationAjaxCallback.failure(LocationAjaxCallback.java:192)
03-19 23:03:20.671: W/AQuery(29954):    at com.androidquery.callback.LocationAjaxCallback.access$3(LocationAjaxCallback.java:183)
03-19 23:03:20.671: W/AQuery(29954):    at com.androidquery.callback.LocationAjaxCallback$Listener.run(LocationAjaxCallback.java:308)
03-19 23:03:20.671: W/AQuery(29954):    at java.util.Timer$TimerImpl.run(Timer.java:284)
03-19 23:03:20.671: W/AQuery(29954): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
03-19 23:03:20.671: W/AQuery(29954):    at android.os.Handler.<init>(Handler.java:121)
03-19 23:03:20.671: W/AQuery(29954):    at android.widget.Toast$TN.<init>(Toast.java:361)
03-19 23:03:20.671: W/AQuery(29954):    at android.widget.Toast.<init>(Toast.java:97)
03-19 23:03:20.671: W/AQuery(29954):    at android.widget.Toast.makeText(Toast.java:254)
03-19 23:03:20.671: W/AQuery(29954):    at uk.ac.gla.project.helpers.LocationHelper.locationCb(LocationHelper.java:46)
03-19 23:03:20.671: W/AQuery(29954):    ... 9 more
03-19 23:03:20.906: W/AQuery(29954): reporting:java.lang.reflect.InvocationTargetException
03-19 23:03:20.906: W/AQuery(29954):    at java.lang.reflect.Method.invokeNative(Native Method)
03-19 23:03:20.906: W/AQuery(29954):    at java.lang.reflect.Method.invoke(Method.java:511)
03-19 23:03:20.906: W/AQuery(29954):    at com.androidquery.util.AQUtility.invokeMethod(AQUtility.java:206)
03-19 23:03:20.906: W/AQuery(29954):    at com.androidquery.util.AQUtility.invokeHandler(AQUtility.java:183)
03-19 23:03:20.906: W/AQuery(29954):    at com.androidquery.callback.AbstractAjaxCallback.callback(AbstractAjaxCallback.java:577)
03-19 23:03:20.906: W/AQuery(29954):    at com.androidquery.callback.LocationAjaxCallback.failure(LocationAjaxCallback.java:192)
03-19 23:03:20.906: W/AQuery(29954):    at com.androidquery.callback.LocationAjaxCallback.access$3(LocationAjaxCallback.java:183)
03-19 23:03:20.906: W/AQuery(29954):    at com.androidquery.callback.LocationAjaxCallback$Listener.run(LocationAjaxCallback.java:308)
03-19 23:03:20.906: W/AQuery(29954):    at java.util.Timer$TimerImpl.run(Timer.java:284)
03-19 23:03:20.906: W/AQuery(29954): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
03-19 23:03:20.906: W/AQuery(29954):    at android.os.Handler.<init>(Handler.java:121)
03-19 23:03:20.906: W/AQuery(29954):    at android.widget.Toast$TN.<init>(Toast.java:361)
03-19 23:03:20.906: W/AQuery(29954):    at android.widget.Toast.<init>(Toast.java:97)
03-19 23:03:20.906: W/AQuery(29954):    at android.widget.Toast.makeText(Toast.java:254)
03-19 23:03:20.906: W/AQuery(29954):    at uk.ac.gla.project.helpers.LocationHelper.locationCb(LocationHelper.java:46)
03-19 23:03:20.906: W/AQuery(29954):    ... 9 more
03-19 23:03:21.061: W/AQuery(29954): reporting:java.lang.reflect.InvocationTargetException
03-19 23:03:21.061: W/AQuery(29954):    at java.lang.reflect.Method.invokeNative(Native Method)
03-19 23:03:21.061: W/AQuery(29954):    at java.lang.reflect.Method.invoke(Method.java:511)
03-19 23:03:21.061: W/AQuery(29954):    at com.androidquery.util.AQUtility.invokeMethod(AQUtility.java:206)
03-19 23:03:21.061: W/AQuery(29954):    at com.androidquery.util.AQUtility.invokeHandler(AQUtility.java:183)
03-19 23:03:21.061: W/AQuery(29954):    at com.androidquery.callback.AbstractAjaxCallback.callback(AbstractAjaxCallback.java:577)
03-19 23:03:21.061: W/AQuery(29954):    at com.androidquery.callback.LocationAjaxCallback.failure(LocationAjaxCallback.java:192)
03-19 23:03:21.061: W/AQuery(29954):    at com.androidquery.callback.LocationAjaxCallback.access$3(LocationAjaxCallback.java:183)
03-19 23:03:21.061: W/AQuery(29954):    at com.androidquery.callback.LocationAjaxCallback$Listener.run(LocationAjaxCallback.java:308)
03-19 23:03:21.061: W/AQuery(29954):    at java.util.Timer$TimerImpl.run(Timer.java:284)
03-19 23:03:21.061: W/AQuery(29954): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
03-19 23:03:21.061: W/AQuery(29954):    at android.os.Handler.<init>(Handler.java:121)
03-19 23:03:21.061: W/AQuery(29954):    at android.widget.Toast$TN.<init>(Toast.java:361)
03-19 23:03:21.061: W/AQuery(29954):    at android.widget.Toast.<init>(Toast.java:97)
03-19 23:03:21.061: W/AQuery(29954):    at android.widget.Toast.makeText(Toast.java:254)
03-19 23:03:21.061: W/AQuery(29954):    at uk.ac.gla.project.helpers.LocationHelper.locationCb(LocationHelper.java:46)
03-19 23:03:21.061: W/AQuery(29954):    ... 9 more
03-19 23:03:21.486: W/AQuery(29954): reporting:java.lang.reflect.InvocationTargetException
03-19 23:03:21.486: W/AQuery(29954):    at java.lang.reflect.Method.invokeNative(Native Method)
03-19 23:03:21.486: W/AQuery(29954):    at java.lang.reflect.Method.invoke(Method.java:511)
03-19 23:03:21.486: W/AQuery(29954):    at com.androidquery.util.AQUtility.invokeMethod(AQUtility.java:206)
03-19 23:03:21.486: W/AQuery(29954):    at com.androidquery.util.AQUtility.invokeHandler(AQUtility.java:183)
03-19 23:03:21.486: W/AQuery(29954):    at com.androidquery.callback.AbstractAjaxCallback.callback(AbstractAjaxCallback.java:577)
03-19 23:03:21.486: W/AQuery(29954):    at com.androidquery.callback.LocationAjaxCallback.failure(LocationAjaxCallback.java:192)
03-19 23:03:21.486: W/AQuery(29954):    at com.androidquery.callback.LocationAjaxCallback.access$3(LocationAjaxCallback.java:183)
03-19 23:03:21.486: W/AQuery(29954):    at com.androidquery.callback.LocationAjaxCallback$Listener.run(LocationAjaxCallback.java:308)
03-19 23:03:21.486: W/AQuery(29954):    at java.util.Timer$TimerImpl.run(Timer.java:284)
03-19 23:03:21.486: W/AQuery(29954): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
03-19 23:03:21.486: W/AQuery(29954):    at android.os.Handler.<init>(Handler.java:121)
03-19 23:03:21.486: W/AQuery(29954):    at android.widget.Toast$TN.<init>(Toast.java:361)
03-19 23:03:21.486: W/AQuery(29954):    at android.widget.Toast.<init>(Toast.java:97)
03-19 23:03:21.486: W/AQuery(29954):    at android.widget.Toast.makeText(Toast.java:254)
03-19 23:03:21.486: W/AQuery(29954):    at uk.ac.gla.project.helpers.LocationHelper.locationCb(LocationHelper.java:46)

Есть ли надежные альтернативы?

7 ответов

Почему так сложно? Используйте Сервисы Google Play. Они бесплатны и используют сложные стратегии размещения

Почему не классический

locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

// Define a listener that responds to location updates

locationListener = new LocationListener() {

        public void onLocationChanged(Location location) {

                // Called when a new location is found by the network location provider.

                longitude = String.valueOf(location.getLongitude());

                latitude = String.valueOf(location.getLatitude());

                Log.d(TAG, "changed Loc : " + longitude + ":" + latitude);

        }

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

        }

        public void onProviderEnabled(String provider) {

        }

        public void onProviderDisabled(String provider) {

        }

};

// getting GPS status

isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);

// check if GPS enabled

if (isGPSEnabled) {

        Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);

        if (location != null) {

                longitude = String.valueOf(location.getLongitude());

                latitude = String.valueOf(location.getLatitude());

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

        } else {

                location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

                if (location != null) {

                        longitude = String.valueOf(location.getLongitude());

                        latitude = String.valueOf(location.getLatitude());

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

                } else {

                        longitude = "0.00";

                        latitude = "0.00";

                }

        }

}

взяты отсюда http://androidadvance.com/android_snippets.php

Согласно вашему logCat у вас есть RuntimeException, когда ваш LocationAjaxCallback$Listener запускается и вызывает этот метод.

locationCb(String url, Location loc, AjaxStatus status)

Так как это не может обновить ваши переменные

private double latitude;
private double longitude;

Вам вернут все, что было ранее в них сохранено. (Ваше старое местоположение)

Вы должны исправить то, что вызывает эту ошибку

at com.androidquery.callback.LocationAjaxCallback$Listener.run(LocationAjaxCallback.java:308)
at java.util.Timer$TimerImpl.run(Timer.java:284)
Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

После этого ваш метод обновления будет работать корректно и обновлять широту и долготу

Добавлять cb.uiCallback(true); до cb.async(mContext);

Зачем

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

В основном, если вы хотите позвонить cb.async(mContext); без звонка cb.uiCallback(true); вы должны сделать это из пользовательского интерфейса *

* или любой другой поток, который имеет Looper

Try this one.

package com.example.tracker;

import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;

import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;

import android.content.Context;
import android.content.Intent;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.provider.Settings;
import android.support.v4.app.FragmentActivity;
import android.widget.Toast;

public class MainActivity extends FragmentActivity implements LocationListener {
    private GoogleMap map;
    private static final LatLng ROMA = new LatLng(42.093230818037,
            11.7971813678741);
    private LocationManager locationManager;
    private String provider;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        map = ((SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map)).getMap();

        LocationManager service = (LocationManager) getSystemService(LOCATION_SERVICE);
        boolean enabledGPS = service
                .isProviderEnabled(LocationManager.GPS_PROVIDER);
        boolean enabledWiFi = service
                .isProviderEnabled(LocationManager.NETWORK_PROVIDER);

        // Check if enabled and if not send user to the GSP settings
        // Better solution would be to display a dialog and suggesting to
        // go to the settings
        if (!enabledGPS) {
            Toast.makeText(this, "GPS signal not found", Toast.LENGTH_LONG)
                    .show();
            Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
            startActivity(intent);
        }

        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        // Define the criteria how to select the locatioin provider -> use
        // default
        Criteria criteria = new Criteria();
        provider = locationManager.getBestProvider(criteria, false);
        Location location = locationManager.getLastKnownLocation(provider);

        // Initialize the location fields
        if (location != null) {
            Toast.makeText(this, "Selected Provider " + provider,
                    Toast.LENGTH_SHORT).show();
            onLocationChanged(location);
        } else {

            // do something
        }

    }

    /* Request updates at startup */
    @Override
    protected void onResume() {
        super.onResume();
        locationManager.requestLocationUpdates(provider, 400, 1, this);
    }

    /* Remove the locationlistener updates when Activity is paused */
    @Override
    protected void onPause() {
        super.onPause();
        locationManager.removeUpdates(this);
    }

    @Override
    public void onLocationChanged(Location location) {
        double lat = location.getLatitude();
        double lng = location.getLongitude();
        Toast.makeText(this, "Location " + lat + "," + lng, Toast.LENGTH_LONG)
                .show();
        LatLng coordinate = new LatLng(lat, lng);
        Toast.makeText(this,
                "Location " + coordinate.latitude + "," + coordinate.longitude,
                Toast.LENGTH_LONG).show();
        Marker startPerc = map.addMarker(new MarkerOptions()
                .position(coordinate)
                .title("Start")
                .snippet("Inizio del percorso")
                .icon(BitmapDescriptorFactory
                        .fromResource(R.drawable.ic_launcher)));
    }

    @Override
    public void onProviderDisabled(String provider) {
        Toast.makeText(this, "Enabled new provider " + provider,
                Toast.LENGTH_SHORT).show();

    }

    @Override
    public void onProviderEnabled(String provider) {
        Toast.makeText(this, "Disabled provider " + provider,
                Toast.LENGTH_SHORT).show();

    }

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

    }

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

        Intent intent=new Intent("android.location.GPS_ENABLED_CHANGE");
        intent.putExtra("enabled", true);
        sendBroadcast(intent);  
        LocationManager mlocManager = (LocationManager)this.getSystemService(Context.LOCATION_SERVICE);
        LocationListener mlocListener = new MyLocationListener();
         mlocManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 0, 0, mlocListener);
    }

  /* Class My Location Listener */
        public class MyLocationListener implements LocationListener
        {

          @Override
          public void onLocationChanged(Location loc)
          {
    try{
           lat=loc.getLatitude();
            longs=loc.getLongitude();
            getAddress(lat, longs);
            String Text = "My current location is: " +
            "Latitud = " + loc.getLatitude() +
            "Longitud = " + loc.getLongitude();
    }catch (NullPointerException e) {

    }
           // Toast.makeText( getActivity().getApplicationContext(), Text, Toast.LENGTH_SHORT).show();
          }

          @Override
          public void onProviderDisabled(String provider)
          {
            Toast.makeText(getApplicationContext(), "Gps Disabled", Toast.LENGTH_SHORT ).show();
          }

          @Override
          public void onProviderEnabled(String provider)
          {
            Toast.makeText(getApplicationContext(), "Gps Enabled", Toast.LENGTH_SHORT).show();
          }

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

          }
        }

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

Не удается создать обработчик внутри потока, который не вызвал Looper.prepare()

Я думаю, дело в том, что вы создаете обработчик AJAX, который, похоже, ожидает некоторые асинхронные сообщения от API GeoLoc.

Вы можете попытаться создать этот обработчик в Activity или запустить Looper:

Looper.prepare();
LocationAjaxCallback cb = new LocationAjaxCallback();
Looper.loop();

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

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

Другие вопросы по тегам