Android上的 LocationManager API看起来对于仅需要偶尔粗略近似用户位置的应用程序来说有点麻烦。
我正在开发的应用程序本身并不是一个位置应用程序,但它确实需要获取用户的位置才能显示附近的商家列表。它不需要担心用户是否正在移动或类似的东西。
以下是我想要做的:
好像它不应该那么难,但在我看来,我必须旋转建立两个不同的位置提供商(GPS和NETWORK)并管理每个生命周期。不仅如此,我还必须在多个活动中复制相同的代码才能满足#2。过去,我尝试过使用 getBestProvider()来将解决方案简化为只使用一个位置提供者,但这似乎只给你最好的理论提供者而不是实际上会给你带来最好结果的提供商。
有没有更简单的方法来完成这项工作?
以下是我如何使用我的类:
LocationResult locationResult = new LocationResult(){ @Override public void gotLocation(Location location){ // Got那个地点! } }; MyLocation myLocation = new MyLocation(); myLocation.getLocation(this,locationResult);以下是MyLocation类:
import java.util.Timer; import java.util.TimerTask; 导入android.content.Context; 导入android.location.Location; 导入android.location.LocationListener; 导入android.location.LocationManager; 导入android.os.Bundle; public class MyLocation { Timer timer1; LocationManager lm; LocationResult locationResult; 布尔值gps_enabled = false; 布尔值network_enabled = false; public boolean getLocation(Context context,LocationResult result) { //我使用LocationResult回调类将位置值从MyLocation传递给用户代码。 locationResult = result; if(lm == null) lm =(LocationManager)context.getSystemService(Context.LOCATION_SERVICE); //如果提供者不被允许,将抛出异常。 try {gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);} catch(Exception ex){} try {network_enabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);} catch(Exception ex){} //如果没有启用提供程序,则不启动监听程序 if(!gps_enabled&< network_enabled) 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(),20000); 返回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){} $ b $ public void onProviderEnabled(String provider){} $ b $ 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){} $ b $ public void onProviderEnabled(String provider){} $ b $ public void onStatusChanged(String provider,int status,Bundle extras){} }; $ b $ class GetLastLocation extends TimerTask { @Override public void run(){ lm.removeUpdates(locationListenerGps); lm.removeUpdates(locationListenerNetwork); 位置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); (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); } }有人可能也想修改我的逻辑。例如,如果你从网络提供商那里得到更新,不要停止监听,而是继续等待。 GPS提供更准确的数据,因此值得等待。如果计时器已过,并且您已从网络获取更新,但无法从GPS获得更新,则可以使用Network提供的值。 developer.android/training/location/retrieve-current.html =noreferrer> developer.android/training/location/retrieve-current.html 。但它需要将Google Play服务apk安装在用户设备上。
The LocationManager API on Android seems like it's a bit of a pain to use for an application that only needs an occasional and rough approximation of the user's location.
The app I'm working on isn't really a location app per se, but it does need to get the user's location in order to display a list of nearby businesses. It doesn't need to worry about if the user is moving around or anything like that.
Here's what I'd like to do:
It seems like it shouldn't be that hard, but it appears to me that I have to spin up two different location providers (GPS and NETWORK) and manage each's lifecycle. Not only that, but I have to duplicate the same code in multiple activities to satisfy #2. I've tried using getBestProvider() in the past to cut the solution down to just using one location provider, but that seems to only give you the best "theoretical" provider rather than the provider that's actually going to give you the best results.
Is there a simpler way to accomplish this?
解决方案Here's what I do:
Here's how I use my class:
LocationResult locationResult = new LocationResult(){ @Override public void gotLocation(Location location){ //Got the location! } }; MyLocation myLocation = new MyLocation(); myLocation.getLocation(this, locationResult);And here's MyLocation class:
import java.util.Timer; import java.util.TimerTask; import android.content.Context; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Bundle; public class MyLocation { Timer timer1; LocationManager lm; LocationResult locationResult; boolean gps_enabled=false; boolean network_enabled=false; public boolean getLocation(Context context, LocationResult result) { //I use LocationResult callback class to pass location value from MyLocation to user code. locationResult=result; if(lm==null) lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); //exceptions will be thrown if provider is not permitted. try{gps_enabled=lm.isProviderEnabled(LocationManager.GPS_PROVIDER);}catch(Exception ex){} try{network_enabled=lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);}catch(Exception ex){} //don't start listeners if no provider is enabled if(!gps_enabled && !network_enabled) 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(), 20000); 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() { lm.removeUpdates(locationListenerGps); lm.removeUpdates(locationListenerNetwork); 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); } }Somebody may also want to modify my logic. For example if you get update from Network provider don't stop listeners but continue waiting. GPS gives more accurate data so it's worth waiting for it. If timer elapses and you've got update from Network but not from GPS then you can use value provided from Network.
One more approach is to use LocationClient developer.android/training/location/retrieve-current.html. But it requires Google Play Services apk to be installed on user device.
更多推荐
在Android上获取用户当前位置的最简单和最稳健的方法是什么?
发布评论