我正在使用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)
有没有可靠的替代方案?
答案 0 :(得分:3)
为什么这么复杂?使用Google Play Services。它们是免费的,使用复杂的Location Strategies
答案 1 :(得分:1)
根据您的logCat,当您的LocationAjaxCallback $ Listener触发并调用此方法时,您会遇到RuntimeException。
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()
之后,您的更新方法将正确触发并更新lat和long
答案 2 :(得分:1)
为什么不是经典的:
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";
}
}
}
答案 3 :(得分:1)
在cb.uiCallback(true);
cb.async(mContext);
<强>为什么强>
我可以告诉你从没有LocationHelper
的后台线程创建Looper
的实例,这样就不能用它来获取异步回调。
基本上,如果你想在不调用cb.async(mContext);
的情况下调用cb.uiCallback(true);
,你必须从UI线程*
*或任何其他具有Looper
答案 4 :(得分:1)
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
}
}
答案 5 :(得分:1)
@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)
{
}
}
答案 6 :(得分:0)
下一个错误表示您已启动将接收消息异步的处理程序。要做到这一点,你需要在主线程上,或者你可以启动一个looper:
无法在未调用的线程内创建处理程序 Looper.prepare()
我认为重点在于您正在创建一个AJAX处理程序,它似乎需要GeoLoc API中的一些异步消息。
您可以尝试在Activity中实例化此处理程序或尝试启动Looper:
Looper.prepare();
LocationAjaxCallback cb = new LocationAjaxCallback();
Looper.loop();
如果您开始使用弯针,请务必在完成后关闭它。认为一个looper就像一个在当前线程中运行的监听器(因此它不会在调用线程中运行)并且它有一个内部队列,用于存储新消息。 无论何时新消息到达,队列都会更新,并且循环线程处理此事件(当它以当前事件结束时,将接收下一个或阻塞,直到新消息到达)。
因此你应该启动looper(创建一个新线程来处理消息)并在完成时关闭(释放该线程+消息队列)。