当我的地图活动被调用时,我在onCreate中调用addUserMapPoint。此函数包含两个实例,我尝试使用myOverlay.getMyLocation获取位置信息。在此活动的初始加载时,第一次尝试的结果返回一个空的GeoPoint,并在主UI线程完成位于myOverlay.runOnFirstFix的监听器线程中的第二次尝试(新的Runnable()...在一秒后调用并且确实包含一个包含lat和lon的GeoPoint。这个监听器函数内的调用看起来似乎把点放在地图上,而mapController.animateTo(gp)行确实将地图移动到我的位置。我的应用程序有一个刷新按钮,当clicked再次触发此活动。我需要lat和lon才能从另一个服务获取位置数据。刷新后,第二次通过map活动代码我期待第一次调用myOverlay.getMyLocation()现在将是能够获得GeoPoint,但它仍然是空的。
如果我无法通过第一次调用myOverlay.getMyLocation来获取GeoPoint,那么如何从myOverlay.runOnFirstFix(new Runnable()...线程中找到的第二个调用中传递lat和lon值。会注意到我一直在尝试将lat和lon添加到MyApp这是辅助bean类,但是这个类中的lat和lon即使在刷新之后也是null。如果我在addUserMapPoint函数中手动设置lat和lon第一个访问活动的时间保留这些值。我猜这是因为它是在主UI线程上设置的。
public class MapActivity extends com.google.android.maps.MapActivity {
private MapView mapView = null;
private MapController mapController = null;
private MyLocationOverlay myOverlay = null;
public static MyApp app;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
app = (MyApp) getApplicationContext();
mapView = (MapView) findViewById(R.id.mapview);
mapView.setBuiltInZoomControls(true);
mapController = mapView.getController();
List<Overlay> mapOverlays = mapView.getOverlays();
mapOverlays.clear();
addUserMapPoint(mapView);
if (!app.isLocServOff()) {
//map other points – service call to get items from our service near lat and lon
addOtherMapPoints(mapOverlays);
} else {
Toast.makeText(app.getApplicationContext(),"Current location could not be found.",Toast.LENGTH_LONG).show();
}
}
private void addUserMapPoint(MapView mapView){
myOverlay = new MyLocationOverlay(app.getApplicationContext(), mapView);
myOverlay.disableCompass();
myOverlay.enableMyLocation();
if(app.getMyLat()==null||app.getMyLon()==null){
GeoPoint gp = myOverlay.getMyLocation();
if(gp!=null){
app.setMyLat(Helper.latLon1E6Calc(gp.getLatitudeE6()));
app.setMyLon(Helper.latLon1E6Calc(gp.getLongitudeE6()));
app.setLocServOff(false);
}else{
app.setLocServOff(true);
}
}
myOverlay.runOnFirstFix(new Runnable() {
public void run() {
GeoPoint gp = myOverlay.getMyLocation();
if(gp!=null){
app.setMyLat(Helper.latLon1E6Calc(gp.getLatitudeE6()));
app.setMyLon(Helper.latLon1E6Calc(gp.getLongitudeE6()));
app.setLocServOff(false);
mapController.animateTo(gp);
}else{
app.setLocServOff(true);
}
}
});
mapView.getOverlays().add(myOverlay);
}
}
我们要求您提供以下问题的帮助。 如何在主UI线程中获取包含lat和lon的GeoPoint,或者如何从GeoPoint传递这些值,我可以从myOverlay.runOnFirstFix(新的Runnable()...线程获取?
如果您打算建议我使用Handler或runOnUiThread,请提供代码示例,将lat和lon传递回主UI线程/地图视图可以使用的内容。我尝试过以下代码,但没有产生预期的结果。我能够收到toast的消息,但是无法以我能够使用的方式传递lat和lon。
final Handler handler = new Handler();
myOverlay.runOnFirstFix(new Runnable() {
@Override public void run() {
handler.post(new Runnable() {
@Override public void run() {
GeoPoint gp = myOverlay.getMyLocation();
if(gp!=null){
app.setMyLat(Helper.latLon1E6Calc(gp.getLatitudeE6()));
app.setMyLon(Helper.latLon1E6Calc(gp.getLongitudeE6()));
app.setLocServOff(false);
mapController.animateTo(gp);
}else{
app.setLocServOff(true);
}
//Toast.makeText(getApplicationContext(),"wowoowowowoowoowowow",Toast.LENGTH_LONG).show();
}
});
}
});
我还使用了以下代码来获取lat和lon并且它可以正常工作,但是因为当前位置有时会比返回whas的lat和lon不同,例如我无法获得gps信号但是还是返回了一个旧值。我添加了检查以查看lat / lon数据是否超过2分钟,但我仍然无法将最新的lat和lon与myOverlay.getMyLocation返回的数据进行匹配。
LocationManager locMgr = (LocationManager)appcontext.getSystemService(Context.LOCATION_SERVICE);
MyLocationListener locLstnr = new MyLocationListener();
//fetch current location for current location
locMgr.requestSingleUpdate(LocationManager.GPS_PROVIDER, locLstnr, appcontext.getMainLooper());
答案 0 :(得分:3)
Bellow你可以找到一些关于如何在UI线程中获取当前位置的例子,但首先是一些背景信息。
GPS
可能需要一些时间(15秒到1分钟)才能获得新位置请求后的第一个修复。这是您第一次尝试从myOverlay
获取失败的原因,并且只有在第一次修复后才能获得该值。
在中断期间,如果您赶时间,可以使用getLastKnownLocation()
获取最后一个知名的GPS位置。如果不可用,则返回null
代码:
上一个已知位置
LocationManager locMgr=(LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
Location loc = locMgr.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if(loc != null){
//we have a valid location. Check location date
}
申请单一位置更新
LocationManager locMgr=(LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
locMgr.requestSingleUpdate(LocationManager.GPS_PROVIDER, locationListener, appcontext.getMainLooper);
申请连续位置更新
LocationManager locMgr = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
//use 0 for minDistance and minDistance between updates if you need the maximum update frequency.
locMgr.requestLocationUpdates(LocationManager.GPS_PROVIDER, minDistance, minTime, locationListener);
单点和连续位置更新的位置监听器
这是最后一段代码,也是您获得上述新位置的地方。
当通过GPS检索到与上面定义的请求相匹配的新位置时,会立即调用此侦听器,除非您的设备正在忙于执行其他无法中断的操作(即回调是在暂停的线程上或者命中一把锁。)
在onLocationChanged()
内,您可以根据需要设置任何类级别。如果您从UI线程注册了侦听器,那么它将在UI上运行。
LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location fix) {
fix.setTime(fix.getTime() + timeZoneOffset); //Add Timezone offset if needed
//here you have a fresh new location in fix...
//You can set the value of any class level field from here
}
public void onProviderDisabled(String provider) {
}
public void onProviderEnabled(String provider) {
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
};
问候。
答案 1 :(得分:2)
在寻找设备位置时必须考虑的一些最重要的要点是:
在下面的代码示例中,LinkedBlockingQueue中的poll方法在指定的时间间隔结束或者位置排队之前不会返回。
使用以下内容获取当前位置:
Location getCurrentLocation() {
long startmillis = 0;
LinkedBlockingQueue<Location> mQueue = new LinkedBlockingQueue<Location>();
try{
long millisSinceLastCollection = System.currentTimeMillis() - startmillis;
startmillis = System.currentTimeMillis();
mQueue.clear();
// Register for Satellite GPS listener as well as Network GPS listener.
registerGPSListeners();
// Wait for a maximum of one minutes for a fix
Location firstfix = mQueue.poll(1, TimeUnit.MINUTES);
if(firstfix != null && firstfix.getProvider().equals(LocationManager.GPS_PROVIDER)) {
return firstfix;
}
long elapsedmillis = System.currentTimeMillis() - startmillis;
long remainingmillis = ONE_MINUTE_IN_MS - elapsedmillis;
if (remainingmillis <= 0){
return firstfix;
}
Location secondfix = mQueue.poll(remainingmillis, TimeUnit.MILLISECONDS);
if(secondfix != null && secondfix.getProvider().equals(LocationManager.GPS_PROVIDER)) {
return secondfix;
}
/*
* In case we receive fix only from Network provider, return it.
*/
if(firstfix != null && firstfix.getProvider().equals(LocationManager.NETWORK_PROVIDER)) {
return firstfix;
}
} catch(Exception e){
Logger.e("GPS: Exception while listening for the current location", e);
} finally {
Logger.i("GPS: Unsubscribing from any existing GPS listeners");
unregisterGPSListeners();
}
}
// GPS issue fix edit.
private void registerGPSListeners() {
LocationManager locationManager = (LocationManager)AirWatchApp.getAppContext().getSystemService(Context.LOCATION_SERVICE);
if(locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER))
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 30000, 100, oneShotNetworkGPSLocationListener, MyAppApp.getAppContext().getMainLooper());
if(locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)){
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 30000, 100, oneShotSatelliteGPSLocationListener, AirWatchApp.getAppContext().getMainLooper());
}
}
private void unregisterGPSListeners(){
final LocationManager locationManager = (LocationManager)MyApp.getAppContext().getSystemService(Context.LOCATION_SERVICE);
locationManager.removeUpdates(oneShotSatelliteGPSLocationListener);
locationManager.removeUpdates(oneShotNetworkGPSLocationListener);
}
//One shot location listener
protected LocationListener oneShotSatelliteGPSLocationListener = new LocationListener() {
public void onLocationChanged(Location location) {
try {
mQueue.put(location);
} catch (InterruptedException e) {
Logger.e("Exception in putting new Location to the queue", e);
}
Logger.d("GPS: Location received from Satellite GPS Provider");
unregisterGPSListeners();
}
public void onProviderDisabled(String provider) {}
public void onStatusChanged(String provider, int status, Bundle extras) {}
public void onProviderEnabled(String provider) {}
};
//One shot location listener
protected LocationListener oneShotNetworkGPSLocationListener = new LocationListener() {
public void onLocationChanged(Location location) {
try {
mQueue.put(location);
} catch (InterruptedException e) {
Logger.e("Exception in putting new Location to the queue", e);
}
Logger.d("GPS: Location received from Network GPS Provider");
// Stop Listener for one-shot location fix from Network GPS provider.
final LocationManager locationManager = (LocationManager)AirWatchApp.getAppContext().getSystemService(Context.LOCATION_SERVICE);
locationManager.removeUpdates(oneShotNetworkGPSLocationListener);
Logger.d("GPS: Unsubscribed the network location listener.");
}
public void onProviderDisabled(String provider) {}
public void onStatusChanged(String provider, int status, Bundle extras) {}
public void onProviderEnabled(String provider) {}
};
答案 2 :(得分:2)
handler.post(new Runnable() {
@Override public void run() {
GeoPoint gp = myOverlay.getMyLocation();
if(gp!=null){
app.setMyLat(Helper.latLon1E6Calc(gp.getLatitudeE6()));
app.setMyLon(Helper.latLon1E6Calc(gp.getLongitudeE6()));
app.setLocServOff(false);
// HERE WE HAVE VALID gp VALUE AND WE NEED TO SHARE IT
mapController.animateTo(gp);
}else{
app.setLocServOff(true);
}
}
});
我认为您的app.set / get | MyLat / Lon无法正常工作,因为您从不同的线程调用它们。要修复它同步set和获取MyLat / Long的方法。 (创建用于同步和同步的对象)
或者,如果您喜欢使用处理程序,那么这应该可行:
final Handler handler = new Handler(); // BE SURE TO RUN THIS LINE ON UI THREAD
...
myOverlay.runOnFirstFix(new Runnable() {
@Override public void run() {
// THIS PART WORKS AS BEFORE
final GeoPoint gp = myOverlay.getMyLocation();
mapController.animateTo(gp);
...
// AND THIS RUNNABLE TO UPDATE MyLat/MyLong FROM UI THREAD
handler.post(new Runnable() {
@Override public void run() {
app.setMyLat(Helper.latLon1E6Calc(gp.getLatitudeE6()));
app.setMyLon(Helper.latLon1E6Calc(gp.getLongitudeE6()));
});
}
});
答案 3 :(得分:2)
Android修改用户界面并处理来自单个用户界面线程(主线程)的输入事件。
如果程序员不使用任何并发结构,则Android应用程序的所有代码都在此线程中运行。
GPS
是确定用户位置的最佳方式,但过多地ping全球定位卫星会很快耗尽移动设备的电池,需要很长时间才能获得用户位置,而且这种方法并不总能在室内工作。 You are not getting your location in first attempt that's why you are getting null over there.
Android的Network Location Provider
根据手机信号塔和Wi-Fi信号确定用户的位置。它不仅使用比GPS更少的电池电量,而且它也更快,无论用户是在室外还是室内,它都能正常工作。
我正在显示progress dialog
下面的工作代码,倾听用户的位置&amp;获取位置后,在 Google-map
location overlay
我认为您已在Menifest file
中授予以下权限
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.INTERNET"/>
我的主要班级
public class MyLocationOnMap extends MapActivity {
private MapView mapView;
private MyLocationOverlay itemizedoverlay;
private LocationManager locationManager;
private String provider;
private MyLocationListener locationListener;
MyBroadCastreceiver myBroadCastreceiver;
/**
* My current Location <i>longitude</i>.
*/
static int longitude;
/**
* My current Location <i>latitude</i>.
*/
static int latitude;
/**
*My progress indicator.
*/
ProgressDialog loadingDialog;
public static final String INTENT_FILTER_TAG="my location broadcast receiver";
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_location_on_map);
loadingDialog = new ProgressDialog(this);
loadingDialog.setTitle("Hot Spots!");
loadingDialog.setMessage("Please wait ...");
loadingDialog.setIndeterminate(true);
loadingDialog.setCancelable(false);
loadingDialog.show();
// Configure the Map
mapView = (MapView) findViewById(R.id.mapview);
mapView.setBuiltInZoomControls(true);
mapView.setStreetView(true);
/**
* Get your location manager and Location Listener...
*/
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationListener=new MyLocationListener();
myBroadCastreceiver = new MyBroadCastreceiver();
if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
Log.i("GPS_Enabled", "GPS enable! listening for gps location.");
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 0, locationListener);
registerReceiver(myBroadCastreceiver, new IntentFilter(INTENT_FILTER_TAG));
} else if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
Log.i("Network_Enabled", "Network enable! listening for Network location.");
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 10000, 0, locationListener);
registerReceiver(myBroadCastreceiver, new IntentFilter(INTENT_FILTER_TAG));
} else {
loadingDialog.dismiss();
Toast.makeText(this, "No Provider enable!", Toast.LENGTH_LONG).show();
}
}//End of onCreate......
/**
* My BroadCast Receiver, that is called when i get the location of user.
* @author Rupesh Yadav.
*
*/
class MyBroadCastreceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
//Remove location update when you get user`s location very first time.
locationManager.removeUpdates(locationListener);
//Remove the broadcast listener that update my location on map.
unregisterReceiver(myBroadCastreceiver);
GeoPoint point = new GeoPoint(latitude, longitude);
mapView.getController().animateTo(point);
List<Overlay> mapOverlays = mapView.getOverlays();
Drawable drawable = MyLocationOnMap.this.getResources().getDrawable(R.drawable.hs_mapoverlay);
itemizedoverlay = new MyLocationOverlay(drawable, MyLocationOnMap.this);
OverlayItem overlayitem = new OverlayItem(point, "Hello!", "My Current Location :)");
itemizedoverlay.addOverlay(overlayitem);
mapOverlays.add(itemizedoverlay);
loadingDialog.dismiss();
}
}
/**
* My Location listener...
*/
class MyLocationListener implements LocationListener{
@Override
public void onLocationChanged(Location location) {
latitude=(int) ((location.getLatitude())*1E6);
longitude=(int) ((location.getLongitude())*1E6);
//Send broadcast to update my location.
Intent sendLocationIntent=new Intent(INTENT_FILTER_TAG);
sendBroadcast(sendLocationIntent);
}
@Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
@Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
}
@Override
protected boolean isRouteDisplayed() {
// TODO Auto-generated method stub
return false;
}
}
MyLocationOverlay类
public class MyLocationOverlay extends ItemizedOverlay<OverlayItem> {
Context mContext;
private ArrayList<OverlayItem> hsOverlays = new ArrayList<OverlayItem>();
public MyLocationOverlay(Drawable defaultMarker) {
super(boundCenterBottom(defaultMarker));
// TODO Auto-generated constructor stub
}
public MyLocationOverlay(Drawable defaultMarker, Context context) {
super(boundCenterBottom(defaultMarker));
mContext = context;
}
@Override
protected OverlayItem createItem(int i) {
// TODO Auto-generated method stub
return hsOverlays.get(i);
}
@Override
public int size() {
// TODO Auto-generated method stub
return hsOverlays.size();
}
/**
* add new OverlayItem objects to map OverlayItem ArrayList.
*
* @param overlay
*/
public void addOverlay(OverlayItem overlay) {
hsOverlays.add(overlay);
populate();
}
/**
* Called when user clicks on map overlay.
*/
@Override
protected boolean onTap(int index) {
// TODO Auto-generated method stub
// return super.onTap(index);
OverlayItem item = hsOverlays.get(index);
AlertDialog.Builder dialog = new AlertDialog.Builder(mContext);
dialog.setTitle(item.getTitle());
dialog.setMessage(item.getSnippet());
dialog.show();
return true;
}
您可以修改Location Listener
&amp; Broadcasr Receiver
根据您的需要。
我希望这能解决你的问题
最好的问候!
答案 4 :(得分:2)
我用这个班来检测我的lat&amp; LON: 希望这对你也有用。
示例使用方法: 的 GPSUtility.getInstance(上下文).getLatitude(); GPSUtility.getInstance(CamPhotoModeAct.this).getLongitude()强>
public class GPSUtility {
public static final String TAG = "GPSUtility";
private Context ctx;
Timer timer1;
LocationManager lm;
LocationResult locationResult;
boolean gps_enabled=false;
boolean network_enabled=false;
private double latitude;
private double longitude;
private static SharedPreferences SHARED_PREF;
private static SharedPreferences.Editor EDITOR_SHARED_PREF;
private static GPSUtility this_instance;
public GPSUtility(Context ctx){
this.ctx = ctx;
SHARED_PREF = ctx.getSharedPreferences(ConstantsG.SHARED_PREF_FILE, Context.MODE_PRIVATE);
EDITOR_SHARED_PREF = SHARED_PREF.edit();
this.getLocation(innerLocationResult);
}
public static GPSUtility getInstance(Context ctx){
if(this_instance == null)
this_instance = new GPSUtility(ctx);
return this_instance;
}
public static void updateLocation(Context ctx){
GPSUtility.getInstance(ctx);//this writes the latitude and longitude in sharable preference file
}
public double getLatitude(){
String latitudeStr = SHARED_PREF.getString(ConstantsG.KEY_LATITUDE,null);
if(latitudeStr == null){
latitude = 0.0;
}
else{
latitude = Double.parseDouble(latitudeStr);
}
return latitude;
}
public double getLongitude(){
String longitudeStr = SHARED_PREF.getString(ConstantsG.KEY_LONGITUDE,null);
if(longitudeStr == null){
longitude = 0.0;
}
else{
longitude = Double.parseDouble(longitudeStr);
}
return longitude;
}
private void updateWithNewLocation(Location location) {
if (location != null) {
latitude = location.getLatitude();
EDITOR_SHARED_PREF.putString(ConstantsG.KEY_LATITUDE, String.valueOf(latitude) );
longitude = location.getLongitude();
EDITOR_SHARED_PREF.putString(ConstantsG.KEY_LONGITUDE, String.valueOf(longitude));
EDITOR_SHARED_PREF.commit();
}
}
public boolean getLocation(LocationResult result)
{
//I use LocationResult callback class to pass location value from GPSUtility to user code.
locationResult=result;
if(lm==null)
lm = (LocationManager) this.ctx.getSystemService(Context.LOCATION_SERVICE);
//exceptions will be thrown if provider is not permitted.
try {
gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch (Exception ex) {
Log.e(TAG, "Exception error: " + ex.getLocalizedMessage(), ex);
}
try {
network_enabled = lm
.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} catch (Exception ex) {
Log.e(TAG, "Exception error: " + ex.getLocalizedMessage(), ex);
}
//Toast.makeText(context, gps_enabled+" "+network_enabled, Toast.LENGTH_LONG).show();
//don't start listeners if no provider is enabled
if(!gps_enabled && !network_enabled){
Toast.makeText(this.ctx, "You should enable gps or be connected to network.", Toast.LENGTH_LONG).show();
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(), 10000);
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() {
//Context context = getClass().getgetApplicationContext();
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);
}
LocationResult innerLocationResult = new LocationResult() {
@Override
public void gotLocation(Location location) {
updateWithNewLocation(location);
}
};
}