在Android上获取用户当前位置的最简单、最可靠的方法是什么?

Android上的LocationManager API似乎对于只需要偶尔粗略地近似用户位置的应用程序使用有点痛苦。

我正在开发的应用程序本身并不是一个真正的位置应用程序,但它确实需要获取用户的位置才能显示附近企业的列表。它不需要担心用户是否在四处走动或类似的事情。

这是我想做的:

  1. 向用户显示附近位置的列表。
  2. 预加载用户的位置,以便在Activity X中需要它时,它将可用。
  3. 我并不特别在意更新的准确性和频率,只要不是太离谱,抓住一个位置就足够了。也许如果我想花哨,我会每隔几分钟左右更新一次位置,但这并不是一个很大的优先级。
  4. 适用于任何设备,只要它有GPS或网络位置提供商。

这似乎并不难,但在我看来,我必须启动两个不同的位置提供商(GPS和网络)并管理每个的生命周期。不仅如此,我还必须在多个活动中复制相同的代码来满足#2。过去我曾尝试使用getBestProvider()将解决方案缩减为只使用一个位置提供商,但这似乎只能给你最好的“理论”提供商,而不是实际上会给你最好结果的提供商。

有没有更简单的方法来实现这一点?

359578 次浏览

你可以一直使用LocationManager.get最近位置,但它说它可能已经过时了。

获得一般位置的简单方法可以是注册网络(通常非常快)。

LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000, 1000, this);

然后做

locationManager.removeUpdates(this);

在侦听器的onLocationChanged()方法中。

我不确定基于位置的服务是否可以从GPS以外的其他基础设施获取位置,但根据那篇文章,这似乎是可能的:

应用程序可以调用任何几种定位方法。

使用移动电话网络:当前单元格ID可用于识别基地收发站(BTS)设备正在通信和那个BTS的位置。显然,这种方法的准确性取决于细胞的大小,并且-可能不太准确-一个GSM手机可能在2到20之间直径两公里。其他与细胞ID一起使用的技术可以精度在150米以内。

利用卫星:全球受控定位系统(GPS)由美国国防部,使用由24颗卫星组成的星座绕地球运行。GPS确定设备的位置通过计算时间信号的差异来自不同的卫星需要到达接收器。GPS信号是编码的,所以移动设备必须配备带有GPS接收器。GPS是可能是最准确的方法(4到40米之间,如果GPS接收器可以清楚地看到天空),但它有一些缺点:额外的硬件可能很昂贵,消耗电池在使用时,需要冷启动后的热身对可见卫星的初步修复。它还受到“峡谷效应”的影响在城市里,卫星能见度断断续续

使用短距离定位信标:相对小区域,例如单个大楼,局域网可以提供位置以及其他服务。例如,适当配备的设备可以使用蓝牙进行短距离定位。

我是这样做的:

  1. 首先,我检查启用了哪些提供程序。有些可能在设备上被禁用,有些可能在应用程序清单中被禁用。
  2. 如果有任何提供者可用,我将启动位置侦听器和超时计时器。在我的示例中为20秒,可能不足以用于GPS,因此您可以放大它。
  3. 如果我从位置侦听器获得更新,我使用提供的值。我停止侦听器和计时器。
  4. 如果我没有得到任何更新和计时器流逝,我必须使用最后的已知值。
  5. 我从可用的提供程序中获取最后的已知值,并选择其中最新的值。

这是我如何使用我的类:

LocationResult locationResult = new LocationResult(){@Overridepublic void gotLocation(Location location){//Got the location!}};MyLocation myLocation = new MyLocation();myLocation.getLocation(this, locationResult);

下面是MyPlace类:

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 enabledif(!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 {@Overridepublic 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 oneif(gps_loc!=null && net_loc!=null){if(gps_loc.getTime()>net_loc.getTime())locationResult.gotLocation(gps_loc);elselocationResult.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,那么您可以使用网络提供的价值。

还有一种方法是使用LocationClienthttp://developer.android.com/training/location/retrieve-current.html。但它需要在用户设备上安装Google Play Services apk。

实际上,我们可以使用两个提供商(GPS和网络)。它们只是共享一个公共侦听器:

locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 10 * 1000, (float) 10.0, listener);locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 90 * 1000, (float) 10.0, listener);

这是必要的,因为总是需要及时调用OnLocationChanged()方法。

要获取并显示用户的当前位置,您也可以使用MyLocationOverlay。假设您的活动中有一个mapView字段。显示用户位置所需做的一切如下:

myLocationOverlay = new MyLocationOverlay(this, mapView);myLocationOverlay.enableMyLocation();mapView.getOverlays().add(myLocationOverlay);

这将从GPS或网络获取当前位置。如果两者都失败,enableMyLocation()将返回false

至于该地区周围事物的位置,ItemizedOverlay应该可以做到。

我希望我没有误解你的问题。祝你好运。

在寻找最佳实现如何获得最佳精确的用户位置之后,我设法结合了所有最好的方法并提出了以下类:

/*** Retrieve accurate location from GPS or network services.*** Class usage example:** public void onCreate(Bundle savedInstanceState) {*      ...*      my_location = new MyLocation();*      my_location.init(main.this, locationResult);* }*** public LocationResult locationResult = new LocationResult(){*      @Override*      public void gotLocation(final Location location){*          // do something*          location.getLongitude();*          location.getLatitude();*      }*  };*/class MyLocation{
/*** If GPS is enabled.* Use minimal connected satellites count.*/private static final int min_gps_sat_count = 5;
/*** Iteration step time.*/private static final int iteration_timeout_step = 500;
LocationResult locationResult;private Location bestLocation = null;private Handler handler = new Handler();private LocationManager myLocationManager;public Context context;
private boolean gps_enabled = false;
private int counts    = 0;private int sat_count = 0;
private Runnable showTime = new Runnable() {    
public void run() {boolean stop = false;counts++;System.println("counts=" + counts);            
//if timeout (1 min) exceeded, stop tyingif(counts > 120){stop = true;}            
//update last best locationbestLocation = getLocation(context);            
//if location is not ready or don`t exists, try againif(bestLocation == null && gps_enabled){System.println("BestLocation not ready, continue to wait");handler.postDelayed(this, iteration_timeout_step);}else{//if best location is known, calculate if we need to continue to look for better location//if gps is enabled and min satellites count has not been connected or min check count is smaller then 4 (2 sec)if(stop == false && !needToStop()){System.println("Connected " + sat_count + " sattelites. continue waiting..");handler.postDelayed(this, iteration_timeout_step);}else{System.println("#########################################");System.println("BestLocation found return result to main. sat_count=" + sat_count);System.println("#########################################");
// removing all updates and listenersmyLocationManager.removeUpdates(gpsLocationListener);myLocationManager.removeUpdates(networkLocationListener);myLocationManager.removeGpsStatusListener(gpsStatusListener);sat_count = 0;                    
// send best location to locationResultlocationResult.gotLocation(bestLocation);}}}};        
/*** Determine if continue to try to find best location*/private Boolean needToStop(){
if(!gps_enabled){return true;}else if(counts <= 4){return false;}if(sat_count < min_gps_sat_count){//if 20-25 sec and 3 satellites found then stopif(counts >= 40 && sat_count >= 3){return true;}return false;}}return true;}
/*** Best location abstract result class*/public static abstract class LocationResult{public abstract void gotLocation(Location location);}
/*** Initialize starting values and starting best location listeners** @param Context ctx* @param LocationResult result*/public void init(Context ctx, LocationResult result){context = ctx;locationResult = result;    
myLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);    
gps_enabled = (Boolean) myLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);    
bestLocation = null;counts = 0;    
// turning on location updatesmyLocationManager.requestLocationUpdates("network", 0, 0, networkLocationListener);myLocationManager.requestLocationUpdates("gps", 0, 0, gpsLocationListener);myLocationManager.addGpsStatusListener(gpsStatusListener);    
// starting best location finder loophandler.postDelayed(showTime, iteration_timeout_step);}
/*** GpsStatus listener. OnChainged counts connected satellites count.*/public final GpsStatus.Listener gpsStatusListener = new GpsStatus.Listener() {public void onGpsStatusChanged(int event) {        
if(event == GpsStatus.GPS_EVENT_SATELLITE_STATUS){try {// Check number of satellites in list to determine fix stateGpsStatus status = myLocationManager.getGpsStatus(null);Iterable<GpsSatellite>satellites = status.getSatellites();                     
sat_count = 0;                     
Iterator<GpsSatellite>satI = satellites.iterator();while(satI.hasNext()) {GpsSatellite satellite = satI.next();System.println("Satellite: snr=" + satellite.getSnr() + ", elevation=" + satellite.getElevation());sat_count++;}} catch (Exception e) {e.printStackTrace();sat_count = min_gps_sat_count + 1;}                 
System.println("#### sat_count = " + sat_count);}}};
/*** Gps location listener.*/public final LocationListener gpsLocationListener = new LocationListener(){@Overridepublic void onLocationChanged(Location location){        
}public void onProviderDisabled(String provider){}public void onProviderEnabled(String provider){}public void onStatusChanged(String provider, int status, Bundle extras){}};
/*** Network location listener.*/public final LocationListener networkLocationListener = new LocationListener(){@Overridepublic void onLocationChanged(Location location){        
}public void onProviderDisabled(String provider){}public void onProviderEnabled(String provider){}public void onStatusChanged(String provider, int status, Bundle extras){}};

/*** Returns best location using LocationManager.getBestProvider()** @param context* @return Location|null*/public static Location getLocation(Context context){System.println("getLocation()");    
// fetch last known location and update ittry {LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);             
Criteria criteria = new Criteria();criteria.setAccuracy(Criteria.ACCURACY_FINE);criteria.setAltitudeRequired(false);criteria.setBearingRequired(false);criteria.setCostAllowed(true);String strLocationProvider = lm.getBestProvider(criteria, true);            
System.println("strLocationProvider=" + strLocationProvider);Location location = lm.getLastKnownLocation(strLocationProvider);if(location != null){return location;}return null;} catch (Exception e) {e.printStackTrace();return null;}}}

如果启用GPS,此类尝试连接到min_gps_sat_count卫星。否则返回LocationManager.getBestProvider()位置。检查代码!

使用Fedor的解决方案,我经历了多次执行回调gotLocation。这似乎是由于重写的LocationListener.onLocationChanged方法中的竞争条件,当gotPlace方法是“足够长”时。我不确定,但我猜removeUpdates阻止了Looper队列中新消息的排队,但它不会删除那些已经排队但尚未消耗的消息。因此是竞争条件。

为了减少这种错误行为的可能性,可以在触发onLocationChanged事件之前调用demveUpdate,但我们仍然有竞争条件。

我发现最好的解决方案是用requestSingleUpdate替换requestLocationUpdates

这是我的版本,基于Fedor的解决方案,使用Handler向循环线程发送消息:

public class LocationResolver {private Timer timer;private LocationManager locationManager;private LocationResult locationResult;private boolean gpsEnabled = false;private boolean networkEnabled = false;private Handler locationTimeoutHandler;
private final Callback locationTimeoutCallback = new Callback() {public boolean handleMessage(Message msg) {locationTimeoutFunc();return true;}
private void locationTimeoutFunc() {locationManager.removeUpdates(locationListenerGps);locationManager.removeUpdates(locationListenerNetwork);
Location networkLocation = null, gpsLocation = null;if (gpsEnabled)gpsLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);if (networkEnabled)networkLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
// if there are both values use the latest oneif (gpsLocation != null && networkLocation != null) {if (gpsLocation.getTime() > networkLocation.getTime())locationResult.gotLocation(gpsLocation);elselocationResult.gotLocation(networkLocation);return;}
if (gpsLocation != null) {locationResult.gotLocation(gpsLocation);return;}if (networkLocation != null) {locationResult.gotLocation(networkLocation);return;}locationResult.gotLocation(null);}};private final LocationListener locationListenerGps = new LocationListener() {public void onLocationChanged(Location location) {timer.cancel();locationResult.gotLocation(location);locationManager.removeUpdates(this);locationManager.removeUpdates(locationListenerNetwork);}
public void onProviderDisabled(String provider) {}
public void onProviderEnabled(String provider) {}
public void onStatusChanged(String provider, int status, Bundle extras) {}};private final LocationListener locationListenerNetwork = new LocationListener() {public void onLocationChanged(Location location) {timer.cancel();locationResult.gotLocation(location);locationManager.removeUpdates(this);locationManager.removeUpdates(locationListenerGps);}
public void onProviderDisabled(String provider) {}
public void onProviderEnabled(String provider) {}
public void onStatusChanged(String provider, int status, Bundle extras) {}};
public void prepare() {locationTimeoutHandler = new Handler(locationTimeoutCallback);}
public synchronized boolean getLocation(Context context, LocationResult result, int maxMillisToWait) {locationResult = result;if (locationManager == null)locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
// exceptions will be thrown if provider is not permitted.try {gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);} catch (Exception ex) {}try {networkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);} catch (Exception ex) {}
// don't start listeners if no provider is enabledif (!gpsEnabled && !networkEnabled)return false;
if (gpsEnabled)locationManager.requestSingleUpdate(LocationManager.GPS_PROVIDER, locationListenerGps, Looper.myLooper());//locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListenerGps);if (networkEnabled)locationManager.requestSingleUpdate(LocationManager.NETWORK_PROVIDER, locationListenerNetwork, Looper.myLooper());//locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListenerNetwork);
timer = new Timer();timer.schedule(new GetLastLocationTask(), maxMillisToWait);return true;}
private class GetLastLocationTask extends TimerTask {@Overridepublic void run() {locationTimeoutHandler.sendEmptyMessage(0);}}
public static abstract class LocationResult {public abstract void gotLocation(Location location);}}

我从一个定制的循环线程中使用这个类,如下所示:

public class LocationGetter {private final Context context;private Location location = null;private final Object gotLocationLock = new Object();private final LocationResult locationResult = new LocationResult() {@Overridepublic void gotLocation(Location location) {synchronized (gotLocationLock) {LocationGetter.this.location = location;gotLocationLock.notifyAll();Looper.myLooper().quit();}}};
public LocationGetter(Context context) {if (context == null)throw new IllegalArgumentException("context == null");
this.context = context;}
public synchronized Coordinates getLocation(int maxWaitingTime, int updateTimeout) {try {final int updateTimeoutPar = updateTimeout;synchronized (gotLocationLock) {new Thread() {public void run() {Looper.prepare();LocationResolver locationResolver = new LocationResolver();locationResolver.prepare();locationResolver.getLocation(context, locationResult, updateTimeoutPar);Looper.loop();}}.start();
gotLocationLock.wait(maxWaitingTime);}} catch (InterruptedException e1) {e1.printStackTrace();}
if (location != null)coordinates = new Coordinates(location.getLatitude(), location.getLongitude());elsecoordinates = Coordinates.UNDEFINED;return coordinates;}}

其中坐标是一个简单的类,具有两个属性:纬度和经度。

使用下面的代码,它将提供最好的提供商:

String locCtx = Context.LOCATION_SERVICE;
LocationManager locationMgr = (LocationManager) ctx.getSystemService(locCtx);
Criteria criteria  = new Criteria();criteria.setAccuracy(Criteria.ACCURACY_FINE);criteria.setAltitudeRequired(false);criteria.setBearingRequired(false);criteria.setCostAllowed(true);criteria.setPowerRequirement(Criteria.POWER_LOW);
String provider = locationMgr.getBestProvider(criteria, true);
System.out.println("Best Available provider::::"+provider);

我创建了一个小应用程序,一步一步的描述,以获取当前位置GPS坐标。

输入图片描述

以下URL中的完整示例源代码:


获取当前位置坐标,城市名称-在Android中


看看它是如何工作的:

  • 我们需要做的就是在清单文件中添加此权限

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
  • and create LocationManager instance like this

    LocationManager locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
  • Check GPS is enabled or not

  • then implement LocationListener and Get Coordinates

    LocationListener locationListener = new MyLocationListener();locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 10, locationListener);
  • here is the sample code to do


/*----------Listener class to get coordinates ------------- */private class MyLocationListener implements LocationListener {
@Overridepublic void onLocationChanged(Location loc) {editLocation.setText("");pb.setVisibility(View.INVISIBLE);Toast.makeText(getBaseContext(),"Location changed: Lat: " + loc.getLatitude() + " Lng: "+ loc.getLongitude(), Toast.LENGTH_SHORT).show();String longitude = "Longitude: " + loc.getLongitude();Log.v(TAG, longitude);String latitude = "Latitude: " + loc.getLatitude();Log.v(TAG, latitude);/*-------to get City-Name from coordinates -------- */String cityName = null;Geocoder gcd = new Geocoder(getBaseContext(), Locale.getDefault());List<Address> addresses;try {addresses = gcd.getFromLocation(loc.getLatitude(),loc.getLongitude(), 1);if (addresses.size() > 0)System.out.println(addresses.get(0).getLocality());cityName = addresses.get(0).getLocality();} catch (IOException e) {e.printStackTrace();}String s = longitude + "\n" + latitude + "\n\nMy Current City is: "+ cityName;editLocation.setText(s);}
@Overridepublic void onProviderDisabled(String provider) {}
@Overridepublic void onProviderEnabled(String provider) {}
@Overridepublic void onStatusChanged(String provider, int status, Bundle extras) {}}

这是提供用户当前位置的代码

创建地图活动:

public class Maps extends MapActivity {
public static final String TAG = "MapActivity";private MapView mapView;private LocationManager locationManager;Geocoder geocoder;Location location;LocationListener locationListener;CountDownTimer locationtimer;MapController mapController;MapOverlay mapOverlay = new MapOverlay();
@Overrideprotected void onCreate(Bundle icicle) {super.onCreate(icicle);setContentView(R.layout.main);initComponents();mapView.setBuiltInZoomControls(true);mapView.setSatellite(true);mapView.setTraffic(true);mapView.setStreetView(true);mapController = mapView.getController();mapController.setZoom(16);locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);if (locationManager == null) {Toast.makeText(Maps.this, "Location Manager Not Available",Toast.LENGTH_SHORT).show();return;}location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);if (location == null)location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);if (location != null) {double lat = location.getLatitude();double lng = location.getLongitude();Toast.makeText(Maps.this, "Location Are" + lat + ":" + lng,Toast.LENGTH_SHORT).show();GeoPoint point = new GeoPoint((int) (lat * 1E6), (int) (lng * 1E6));mapController.animateTo(point, new Message());mapOverlay.setPointToDraw(point);List<Overlay> listOfOverlays = mapView.getOverlays();listOfOverlays.clear();listOfOverlays.add(mapOverlay);}locationListener = new LocationListener() {
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {}
public void onProviderEnabled(String arg0) {}
public void onProviderDisabled(String arg0) {}
public void onLocationChanged(Location l) {location = l;locationManager.removeUpdates(this);if (l.getLatitude() == 0 || l.getLongitude() == 0) {} else {double lat = l.getLatitude();double lng = l.getLongitude();Toast.makeText(Maps.this, "Location Are" + lat + ":" + lng,Toast.LENGTH_SHORT).show();}}};if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER))locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 10f, locationListener);locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000, 10f, locationListener);locationtimer = new CountDownTimer(30000, 5000) {
@Overridepublic void onTick(long millisUntilFinished) {if (location != null) locationtimer.cancel();}
@Overridepublic void onFinish() {if (location == null) {}}};locationtimer.start();}
public MapView getMapView() {return this.mapView;}
private void initComponents() {mapView = (MapView) findViewById(R.id.map_container);ImageView ivhome = (ImageView) this.findViewById(R.id.imageView_home);ivhome.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {// TODO Auto-generated method stubIntent intent = new Intent(Maps.this, GridViewContainer.class);startActivity(intent);finish();}});}
@Overrideprotected boolean isRouteDisplayed() {return false;}
class MapOverlay extends Overlay {
private GeoPoint pointToDraw;
public void setPointToDraw(GeoPoint point) {pointToDraw = point;}
public GeoPoint getPointToDraw() {return pointToDraw;}
@Overridepublic boolean draw(Canvas canvas, MapView mapView, boolean shadow,long when) {super.draw(canvas, mapView, shadow);Point screenPts = new Point();mapView.getProjection().toPixels(pointToDraw, screenPts);Bitmap bmp = BitmapFactory.decodeResource(getResources(),R.drawable.select_map);canvas.drawBitmap(bmp, screenPts.x, screenPts.y - 24, null);return true;}}}

main.xml:

    <?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@android:color/black"android:orientation="vertical" >
<com.google.android.maps.MapViewandroid:id="@+id/map_container"android:layout_width="fill_parent"android:layout_height="fill_parent"android:apiKey="yor api key"android:clickable="true"android:focusable="true" />
</LinearLayout>

并在清单中定义以下权限:

<uses-permission android:name="android.permission.INTERNET"/><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/><uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
public static Location getBestLocation(Context ctxt) {Location gpslocation = getLocationByProvider(LocationManager.GPS_PROVIDER, ctxt);Location networkLocation = getLocationByProvider(LocationManager.NETWORK_PROVIDER, ctxt);Location fetchedlocation = null;// if we have only one location available, the choice is easyif (gpslocation != null) {Log.i("New Location Receiver", "GPS Location available.");fetchedlocation = gpslocation;} else {Log.i("New Location Receiver","No GPS Location available. Fetching Network location lat="+ networkLocation.getLatitude() + " lon ="+ networkLocation.getLongitude());fetchedlocation = networkLocation;}return fetchedlocation;}
/*** get the last known location from a specific provider (network/gps)*/private static Location getLocationByProvider(String provider, Context ctxt) {Location location = null;// if (!isProviderSupported(provider)) {// return null;// }LocationManager locationManager = (LocationManager) ctxt.getSystemService(Context.LOCATION_SERVICE);try {if (locationManager.isProviderEnabled(provider)) {location = locationManager.getLastKnownLocation(provider);}} catch (IllegalArgumentException e) {Log.i("New Location Receiver", "Cannot access Provider " + provider);}return location;}

地理位置的简单和最佳方式。

LocationManager lm = null;boolean network_enabled;

if (lm == null)lm = (LocationManager) Kikit.this.getSystemService(Context.LOCATION_SERVICE);
network_enabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
dialog = ProgressDialog.show(Kikit.this, "", "Fetching location...", true);

final Handler handler = new Handler();timer = new Timer();TimerTask doAsynchronousTask = new TimerTask() {
@Overridepublic void run() {handler.post(new Runnable() {
@Overridepublic void run(){
Log.e("counter value","value "+counter);
if(counter<=8){try{counter++;

if (network_enabled) {
lm = (LocationManager) Kikit.this.getSystemService(Context.LOCATION_SERVICE);
Log.e("in network_enabled..","in network_enabled");
// Define a listener that responds to location updatesLocationListener locationListener = new LocationListener(){

public void onLocationChanged(Location location){if(attempt == false)
{attempt = true;Log.e("in location listener..","in location listener..");longi = location.getLongitude();lati = location.getLatitude();Data.longi = "" + longi;Data.lati = "" + lati;

Log.e("longitude : ",""+longi);Log.e("latitude : ",""+lati);


if(faceboo_name.equals("")){if(dialog!=null){dialog.cancel();}timer.cancel();timer.purge();Data.homepage_resume = true;lm = null;Intent intent = new Intent();intent.setClass(Kikit.this,MainActivity.class);
startActivity(intent);finish();}else{
isInternetPresent = cd.isConnectingToInternet();
if (isInternetPresent){if(dialog!=null)dialog.cancel();
Showdata();}else{error_view.setText(Data.internet_error_msg);error_view.setVisibility(0);error_gone();}
}}
}
public void onStatusChanged(String provider, int status,Bundle extras) {}
public void onProviderEnabled(String provider) {//Toast.makeText(getApplicationContext(), "Location enabled", Toast.LENGTH_LONG).show();
}
public void onProviderDisabled(String provider) {

}};


// Register the listener with the Location Manager to receive// location updateslm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 100000, 10,locationListener);
} else{//Toast.makeText(getApplicationContext(), "No Internet Connection.", 2000).show();buildAlertMessageNoGps();
}


} catch (Exception e) {// TODO// Auto-generated// catch// block}}else{
timer.purge();timer.cancel();
if(attempt == false){attempt = true;
String locationProvider = LocationManager.NETWORK_PROVIDER;// Or use LocationManager.GPS_PROVIDER
try {Location lastKnownLocation = lm.getLastKnownLocation(locationProvider);
longi = lastKnownLocation.getLongitude();lati = lastKnownLocation.getLatitude();Data.longi = "" + longi;Data.lati = "" + lati;} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();Log.i("exception in loc fetch", e.toString());}
Log.e("longitude of last known location : ",""+longi);Log.e("latitude of last known location : ",""+lati);
if(Data.fb_access_token == ""){
if(dialog!=null){dialog.cancel();}timer.cancel();timer.purge();Data.homepage_resume = true;Intent intent = new Intent();intent.setClass(Kikit.this,MainActivity.class);
startActivity(intent);finish();}else{
isInternetPresent = cd.isConnectingToInternet();
if (isInternetPresent){if(dialog!=null){dialog.cancel();}Showdata();}else{error_view.setText(Data.internet_error_msg);error_view.setVisibility(0);error_gone();}
}
}}}});}};timer.schedule(doAsynchronousTask, 0, 2000);

private void buildAlertMessageNoGps() {final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Your WiFi & mobile network location is disabled , do you want to enable it?").setCancelable(false).setPositiveButton("Yes", new DialogInterface.OnClickListener() {

public void onClick(@SuppressWarnings("unused") final DialogInterface dialog, @SuppressWarnings("unused") final int id){startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS));setting_page = true;}}).setNegativeButton("No", new DialogInterface.OnClickListener() {public void onClick(final DialogInterface dialog, @SuppressWarnings("unused") final int id) {dialog.cancel();finish();}});final AlertDialog alert = builder.create();alert.show();}

推荐的方法是使用LocationClient

首先,定义位置更新间隔值。根据您的需要进行调整。

private static final int MILLISECONDS_PER_SECOND = 1000;private static final long UPDATE_INTERVAL = MILLISECONDS_PER_SECOND * UPDATE_INTERVAL_IN_SECONDS;private static final int FASTEST_INTERVAL_IN_SECONDS = 1;private static final long FASTEST_INTERVAL = MILLISECONDS_PER_SECOND * FASTEST_INTERVAL_IN_SECONDS;

让你的Activity实现GooglePlayServicesClient.ConnectionCallbacksGooglePlayServicesClient.OnConnectionFailedListenerLocationListener

public class LocationActivity extends Activity implementsGooglePlayServicesClient.ConnectionCallbacks, GooglePlayServicesClient.OnConnectionFailedListener, LocationListener {}

然后,在ActivityonCreate()方法中设置LocationClient

public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
mLocationClient = new LocationClient(this, this, this);
mLocationRequest = LocationRequest.create();mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);mLocationRequest.setInterval(UPDATE_INTERVAL);mLocationRequest.setFastestInterval(FASTEST_INTERVAL);}

将所需的方法添加到您的ActivityonConnected()LocationClient连接时调用的方法。onLocationChanged()是您将检索最新位置的位置。

@Overridepublic void onConnectionFailed(ConnectionResult connectionResult) {Log.w(TAG, "Location client connection failed");}
@Overridepublic void onConnected(Bundle dataBundle) {Log.d(TAG, "Location client connected");mLocationClient.requestLocationUpdates(mLocationRequest, this);}
@Overridepublic void onDisconnected() {Log.d(TAG, "Location client disconnected");}
@Overridepublic void onLocationChanged(Location location) {if (location != null) {Log.d(TAG, "Updated Location: " + Double.toString(location.getLatitude()) + "," + Double.toString(location.getLongitude()));} else {Log.d(TAG, "Updated location NULL");}}

请务必连接/断开LocationClient,以便仅在绝对必要时使用额外的电池,并且GPS不会无限期运行。必须连接LocationClient才能从中获取数据。

public void onResume() {super.onResume();mLocationClient.connect();}
public void onStop() {if (mLocationClient.isConnected()) {mLocationClient.removeLocationUpdates(this);}mLocationClient.disconnect();super.onStop();}

获取用户的位置。首先尝试使用LocationClient;如果失败,请回退到LocationManager

public Location getLocation() {if (mLocationClient != null && mLocationClient.isConnected()) {return mLocationClient.getLastLocation();} else {LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);if (locationManager != null) {Location lastKnownLocationGPS = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);if (lastKnownLocationGPS != null) {return lastKnownLocationGPS;} else {return locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);}} else {return null;}}}

尽管答案已经在这里给出了。我只是想把这个分享给世界,以防遇到这样的情况。

我的要求是我需要在最大30到35秒内获得用户的当前位置,所以这是我在Nirav Ranpala的回答之后提出的解决方案。

1.我做了MyLocationManager.java类,处理所有GPS和网络的东西

import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.TimeUnit;
import com.app.callbacks.OnLocationDetectectionListener;
import android.app.AlertDialog;import android.content.Context;import android.content.DialogInterface;import android.content.Intent;import android.location.Location;import android.location.LocationListener;import android.location.LocationManager;import android.os.Bundle;import android.provider.Settings;import android.util.Log;import android.widget.Toast;
public class MyLocationManager {/** The minimum distance to GPS change Updates in meters **/private final long MIN_DISTANCE_CHANGE_FOR_UPDATES_FOR_GPS = 2; // 2// meters/** The minimum time between GPS updates in milliseconds **/private final long MIN_TIME_BW_UPDATES_OF_GPS = 1000 * 5 * 1; // 5// seconds
/** The minimum distance to NETWORK change Updates in meters **/private final long MIN_DISTANCE_CHANGE_FOR_UPDATES_FOR_NETWORK = 5; // 5// meters/** The minimum time between NETWORK updates in milliseconds **/private final long MIN_TIME_BW_UPDATES_OF_NETWORK = 1000 * 10 * 1; // 10// seconds
/*** Lets just say i don't trust the first location that the is found. This is* to avoid that**/
private int NetworkLocationCount = 0, GPSLocationCount = 0;private boolean isGPSEnabled;private boolean isNetworkEnabled;/*** Don't do anything if location is being updated by Network or by GPS*/private boolean isLocationManagerBusy;private LocationManager locationManager;private Location currentLocation;private Context mContext;private OnLocationDetectectionListener mListener;
public MyLocationManager(Context mContext,OnLocationDetectectionListener mListener) {this.mContext = mContext;this.mListener = mListener;}
/*** Start the location manager to find my location*/public void startLocating() {try {locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
// Getting GPS statusisGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
// Getting network statusisNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isGPSEnabled && !isNetworkEnabled) {// No network provider is enabledshowSettingsAlertDialog();} else {// If GPS enabled, get latitude/longitude using GPS Servicesif (isGPSEnabled) {locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,MIN_TIME_BW_UPDATES_OF_GPS,MIN_DISTANCE_CHANGE_FOR_UPDATES_FOR_GPS,gpsLocationListener);
}if (isNetworkEnabled) {locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,MIN_TIME_BW_UPDATES_OF_NETWORK,MIN_DISTANCE_CHANGE_FOR_UPDATES_FOR_NETWORK,networkLocationListener);
}}/*** My 30 seconds plan to get myself a location*/ScheduledExecutorService se = Executors.newSingleThreadScheduledExecutor();se.schedule(new Runnable() {
@Overridepublic void run() {if (currentLocation == null) {if (isGPSEnabled) {currentLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);} else if (isNetworkEnabled) {currentLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
}if (currentLocation != null && mListener != null) {locationManager.removeUpdates(gpsLocationListener);locationManager.removeUpdates(networkLocationListener);mListener.onLocationDetected(currentLocation);}}}}, 30, TimeUnit.SECONDS);
} catch (Exception e) {Log.e("Error Fetching Location", e.getMessage());Toast.makeText(mContext,"Error Fetching Location" + e.getMessage(),Toast.LENGTH_SHORT).show();}}
/*** Handle GPS location listener callbacks*/private LocationListener gpsLocationListener = new LocationListener() {
@Overridepublic void onStatusChanged(String provider, int status, Bundle extras) {// TODO Auto-generated method stub
}
@Overridepublic void onProviderEnabled(String provider) {// TODO Auto-generated method stub
}
@Overridepublic void onProviderDisabled(String provider) {// TODO Auto-generated method stub
}
@Overridepublic void onLocationChanged(Location location) {
if (GPSLocationCount != 0 && !isLocationManagerBusy) {Log.d("GPS Enabled", "GPS Enabled");isLocationManagerBusy = true;currentLocation = location;locationManager.removeUpdates(gpsLocationListener);locationManager.removeUpdates(networkLocationListener);isLocationManagerBusy = false;if (currentLocation != null && mListener != null) {mListener.onLocationDetected(currentLocation);}}GPSLocationCount++;}};/*** Handle Network location listener callbacks*/private LocationListener networkLocationListener = new LocationListener() {
@Overridepublic void onStatusChanged(String provider, int status, Bundle extras) {// TODO Auto-generated method stub
}
@Overridepublic void onProviderEnabled(String provider) {// TODO Auto-generated method stub
}
@Overridepublic void onProviderDisabled(String provider) {// TODO Auto-generated method stub
}
@Overridepublic void onLocationChanged(Location location) {if (NetworkLocationCount != 0 && !isLocationManagerBusy) {Log.d("Network", "Network");isLocationManagerBusy = true;currentLocation = location;locationManager.removeUpdates(gpsLocationListener);locationManager.removeUpdates(networkLocationListener);isLocationManagerBusy = false;if (currentLocation != null && mListener != null) {mListener.onLocationDetected(currentLocation);}}NetworkLocationCount++;}};
/*** Function to show settings alert dialog. On pressing the Settings button* it will launch Settings Options.* */public void showSettingsAlertDialog() {AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);
// Setting Dialog TitlealertDialog.setTitle("GPS is settings");
// Setting Dialog MessagealertDialog.setMessage("GPS is not enabled. Do you want to go to settings menu?");
// On pressing the Settings button.alertDialog.setPositiveButton("Settings",new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);mContext.startActivity(intent);}});
// On pressing the cancel buttonalertDialog.setNegativeButton("Cancel",new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {dialog.cancel();}});
// Showing Alert MessagealertDialog.show();}}

2.我做了一个接口(回调)OnLocationDetectectionListener.java以便将结果传达回调用片段或活动

import android.location.Location;
public interface OnLocationDetectectionListener {public void onLocationDetected(Location mLocation);}

3.然后我做了一个MainAppActivty.java活动,实现了OnLocationDetectectionListener接口,这是我如何在其中接收我的位置

public class MainAppActivty extends Activity implementsOnLocationDetectectionListener {
private Location currentLocation;private MyLocationManager mLocationManager;
@Overrideprotected void onCreate(Bundle savedInstanceState) {setContentView(R.layout.activity_home);super.onCreate(savedInstanceState);mLocationManager = new MyLocationManager(this, this);mLocationManager.startLocating();}
@Overridepublic void onLocationDetected(Location mLocation) {//Your new Location is received herecurrentLocation = mLocation;}

4.将以下权限添加到您的清单文件

<uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

希望对别人有帮助:)

编辑:使用Google Play服务库中的最新位置服务API更新(2014年7月)

我建议你使用新的位置服务API,它可以从Google Play服务库中获得,它提供了一个更强大的高级框架,可以自动执行位置提供商选择和电源管理等任务。根据官方留档:“…位置API使您可以轻松构建位置感知应用程序,而无需关注底层位置技术的细节。它们还让您通过使用设备硬件的所有功能来最大限度地降低功耗。”

更多信息请访问:让您的应用程序位置感知

要查看使用最新位置服务API的完整示例,请访问:Android LocationClient类已弃用,但用于留档

有点晚了,但我在这种情况下会使用谷歌地图API,并使用谷歌地图的lat和long API标记附近的位置。如果你能在地图上显示他/她的位置,用户体验会更好。无需担心用户位置的更新或用安卓API搜身。让谷歌地图为你处理内部事务。

@emmby可能已经在他的应用程序中解决了这个问题,但为了将来的参考,我向其他开发人员推荐谷歌地图API以获取特定位置的东西。

编辑:显示谷歌地图中的用户位置的链接

我在demonuts.com上写了详细的教程,涵盖当前位置。您可以在此处找到更多描述,也可以下载整个演示源代码以更好地理解。

那里已经有很多答案,但我想展示使用Google API获取位置的最新方法,因此新程序员可以使用新方法:

首先把这个放到gradle文件里

compile 'com.google.android.gms:play-services:8.4.0'

然后实现必要的接口

public class MainActivity  extends BaseActivitiy implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, com.google.android.gms.location.LocationListener

声明实例

  private GoogleApiClient mGoogleApiClient;private Location mLocation;private LocationManager locationManager;private LocationRequest mLocationRequest;

把这个放在onCreate()

 mGoogleApiClient = new GoogleApiClient.Builder(this).addConnectionCallbacks(this).addOnConnectionFailedListener(this).addApi(LocationServices.API).build();locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

最后,覆盖必要的方法

 @Overridepublic void onConnected(Bundle bundle) {if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {// TODO: Consider calling//    ActivityCompat#requestPermissions// here to request the missing permissions, and then overriding//   public void onRequestPermissionsResult(int requestCode, String[] permissions,//                                          int[] grantResults)// to handle the case where the user grants the permission. See the documentation// for ActivityCompat#requestPermissions for more details.return;}mLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);if(mLocation == null){startLocationUpdates();}if (mLocation != null) {double latitude = mLocation.getLatitude();double longitude = mLocation.getLongitude();} else {// Toast.makeText(this, "Location not Detected", Toast.LENGTH_SHORT).show();}}
protected void startLocationUpdates() {// Create the location requestmLocationRequest = LocationRequest.create().setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY).setInterval(UPDATE_INTERVAL).setFastestInterval(FASTEST_INTERVAL);// Request location updatesif (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {// TODO: Consider calling//    ActivityCompat#requestPermissions// here to request the missing permissions, and then overriding//   public void onRequestPermissionsResult(int requestCode, String[] permissions,//                                          int[] grantResults)// to handle the case where the user grants the permission. See the documentation// for ActivityCompat#requestPermissions for more details.return;}LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,mLocationRequest, this);Log.d("reque", "--->>>>");}
@Overridepublic void onConnectionSuspended(int i) {Log.i(TAG, "Connection Suspended");mGoogleApiClient.connect();}
@Overridepublic void onConnectionFailed(ConnectionResult connectionResult) {Log.i(TAG, "Connection failed. Error: " + connectionResult.getErrorCode());}
@Overridepublic void onStart() {super.onStart();mGoogleApiClient.connect();}
@Overridepublic void onStop() {super.onStop();if (mGoogleApiClient.isConnected()) {mGoogleApiClient.disconnect();}}@Overridepublic void onLocationChanged(Location location) {
}

不要忘记在运行应用程序之前在您的设备中启动GPS。

通过使用FusedLocationProviderApi,这是最新的API,也是在Android中获取位置的可用可能性中最好的。添加到build.gradle文件

dependencies {compile 'com.google.android.gms:play-services:6.5.87'}

您可以通过此URL获取完整的源代码http://javapapers.com/android/android-location-fused-provider/

我是这样做的:

  1. 首先,我检查是否启用了网络或GPS提供程序。有些可能在设备上被禁用,有些可能在应用程序清单中被禁用。如果启用了任何提供程序,我获取此提供程序的缓存最后位置并启动此提供程序的位置更新侦听器。
  2. 有一种方法可以确定一个位置是否比链接中提到的上次接收到的位置更好:-https://developer.android.com/guide/topics/location/strategies.html#BestEstimate
  3. 如果我从位置侦听器获得更新,我检查此位置是否比以前收到的位置更好。如果它比将此位置替换为以前的最佳位置(mFinalLocation)更好。
  4. 还有一个两分钟的处理程序(定时器),它最终停止服务,并在服务的onDestroy()方法中停止监听每个提供者的位置更新。

以下是服务代码。您可以根据需要的位置更新频率运行它。

import android.app.Service;import android.content.Context;import android.content.Intent;import android.location.Location;import android.location.LocationListener;import android.location.LocationManager;import android.os.Bundle;import android.os.Handler;import android.os.IBinder;import android.os.Message;import android.support.annotation.Nullable;import android.util.Log;

public class RecordLocationService extends Service {
private final String TAG = RecordLocationService.class.getSimpleName();
private final int TWO_MINUTES = 1000 * 60 * 2;
private LocationManager mLocationManager;
private MyLocationListener mLocationListeners[] = new MyLocationListener[]{new MyLocationListener(LocationManager.NETWORK_PROVIDER),new MyLocationListener(LocationManager.GPS_PROVIDER)};
private Location mFinalLocation;
private class MyLocationListener implements LocationListener {private String mProvider;
public MyLocationListener(String provider) {Log.d(TAG, "LocationListener : " + provider);mProvider = provider;}
public String getProvider() {return mProvider;}
@Overridepublic void onLocationChanged(Location location) {Log.d(TAG, "onLocationChanged : " + location);
if (isBetterLocation(location, mFinalLocation)) {Log.d(TAG, "Setting current Final Location to recent most Location for Provider : " + location.getProvider());Log.d(TAG, "Setting current Final Location to : " + location);mFinalLocation = location;} else {Log.d(TAG, "Keeping current Final Location to previous Final Location");}
}
@Overridepublic void onStatusChanged(String provider, int status, Bundle extras) {Log.d(TAG, "onStatusChanged provider " + provider);}
@Overridepublic void onProviderEnabled(String provider) {Log.d(TAG, "onProviderEnabled provider " + provider);}
@Overridepublic void onProviderDisabled(String provider) {Log.d(TAG, "onProviderDisabled provider " + provider);}}
private Handler mStopServiceHandler = new Handler() {
@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case 1: {stopSelf();}break;}}};
@Nullable@Overridepublic IBinder onBind(Intent intent) {return null;}
@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {super.onStartCommand(intent, flags, startId);Log.d(TAG, "onStartCommand");return START_STICKY;}
@Overridepublic void onCreate() {super.onCreate();Log.d(TAG, "onCreate");requestLocation();mStopServiceHandler.sendEmptyMessageDelayed(1, TWO_MINUTES);}
private void requestLocation() {// Acquire a reference to the system Location Managerif (mLocationManager == null) {mLocationManager = (LocationManager) this.getApplicationContext().getSystemService(Context.LOCATION_SERVICE);}
try {if (mLocationManager.getAllProviders().contains(LocationManager.NETWORK_PROVIDER) && mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {Log.d(TAG, "Fetching Cached Location for Provider : " + LocationManager.NETWORK_PROVIDER);Location cachedNetworkLocation = mLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (cachedNetworkLocation != null) {Log.d(TAG, "Setting Final Location to Cached Location for Provider : " + LocationManager.NETWORK_PROVIDER);Log.d(TAG, "Setting Final Location to : " + cachedNetworkLocation);mFinalLocation = cachedNetworkLocation;} else {Log.d(TAG, "Cached Location for Provider : " + LocationManager.NETWORK_PROVIDER + " is NULL");}
Log.d(TAG, "Requesting Location Update for Provider : " + LocationManager.NETWORK_PROVIDER);mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, mLocationListeners[0]);}
} catch (SecurityException se) {Log.e(TAG, se.getMessage(), se);} catch (IllegalArgumentException iae) {Log.e(TAG, iae.getMessage(), iae);}
try {if (mLocationManager.getAllProviders().contains(LocationManager.GPS_PROVIDER) && mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {Log.d(TAG, "Fetching Cached Location for Provider : " + LocationManager.GPS_PROVIDER);Location cachedGPSLocation = mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (cachedGPSLocation != null) {if (isBetterLocation(cachedGPSLocation, mFinalLocation)) {Log.d(TAG, "Setting Final Location to Cached Location for Provider : " + LocationManager.GPS_PROVIDER);Log.d(TAG, "Setting Final Location to : " + cachedGPSLocation);mFinalLocation = cachedGPSLocation;}} else {Log.d(TAG, "Cached Location for Provider : " + LocationManager.GPS_PROVIDER + " is NULL");}
Log.d(TAG, "Requesting Location Update for Provider : " + LocationManager.GPS_PROVIDER);mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mLocationListeners[1]);}
} catch (SecurityException se) {Log.e(TAG, se.getMessage(), se);} catch (IllegalArgumentException iae) {Log.e(TAG, iae.getMessage(), iae);}

}
/*** Determines whether one Location reading is better than the current Location fix** @param location            The new Location that you want to evaluate* @param currentBestLocation The current Location fix, to which you want to compare the new one*/protected boolean isBetterLocation(Location location, Location currentBestLocation) {if (currentBestLocation == null) {// A new location is always better than no locationreturn true;}
// Check whether the new location fix is newer or olderlong timeDelta = location.getTime() - currentBestLocation.getTime();boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;boolean isNewer = timeDelta > 0;
// If it's been more than two minutes since the current location, use the new location// because the user has likely movedif (isSignificantlyNewer) {return true;// If the new location is more than two minutes older, it must be worse} else if (isSignificantlyOlder) {return false;}
// Check whether the new location fix is more or less accurateint accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());boolean isLessAccurate = accuracyDelta > 0;boolean isMoreAccurate = accuracyDelta < 0;boolean isSignificantlyLessAccurate = accuracyDelta > 200;
// Check if the old and new location are from the same providerboolean isFromSameProvider = isSameProvider(location.getProvider(),currentBestLocation.getProvider());
// Determine location quality using a combination of timeliness and accuracyif (isMoreAccurate) {return true;} else if (isNewer && !isLessAccurate) {return true;} else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {return true;}return false;}
/*** Checks whether two providers are the same*/private boolean isSameProvider(String provider1, String provider2) {if (provider1 == null) {return provider2 == null;}return provider1.equals(provider2);}
@Overridepublic void onDestroy() {super.onDestroy();Log.d(TAG, "onDestroy");if (mLocationManager != null) {for (int i = 0; i < mLocationListeners.length; i++) {try {Log.d(TAG, "Removing Location Update for Provider : " + mLocationListeners[i].getProvider());mLocationManager.removeUpdates(mLocationListeners[i]);} catch (Exception ex) {Log.e(TAG, "fail to remove location listeners, ignore", ex);}}}}}

在Android中获取位置更新需要很多东西,需要大量的波利尔板代码。

你需要照顾

  • Google Play服务可用性检查,
  • 更新Google Play服务,如果它旧或不可用
  • 对话框创建GoogleApiClient及其回调连接、断开等。
  • 停止和释放用于位置更新的资源
  • 处理位置权限场景
  • 检查位置服务是否打开或关闭
  • 找到最新的位置也不是那么容易
  • 如果在一定持续时间后没有获得位置,则回退到最后已知位置

我已经创建了Android-Easy位置(小型Android库),它将处理所有这些事情,您可以专注于业务逻辑。

所有你需要的是扩展EasyLocationActivityActivityActivityActivityActivtionEasyLocationActivityActivityActivityActivityActivityActiveActivityActiveActiveActiveActiveActiveActiveActiveActiveActiveActiveActiveActiveActive和这个

requestSingleLocationFix(easyLocationRequest);

requestLocationUpdates(easyLocationRequest);

https://github.com/akhgupta/Android-EasyLocation处查看示例应用程序和所需步骤

最近重构获取了代码的位置,学习了一些不错的思路,终于实现了比较完善的库和Demo。

//request all valid provider(network/gps)private boolean requestAllProviderUpdates() {checkRuntimeEnvironment();checkPermission();
if (isRequesting) {EasyLog.d("Request location update is busy");return false;}

long minTime = getCheckTimeInterval();float minDistance = getCheckMinDistance();
if (mMapLocationListeners == null) {mMapLocationListeners = new HashMap<>();}
mValidProviders = getValidProviders();if (mValidProviders == null || mValidProviders.isEmpty()) {throw new IllegalArgumentException("Not available provider.");}
for (String provider : mValidProviders) {LocationListener locationListener = new LocationListener() {@Overridepublic void onLocationChanged(Location location) {if (location == null) {EasyLog.e("LocationListener callback location is null.");return;}printf(location);mLastProviderTimestamp = location.getTime();
if (location.getProvider().equals(LocationManager.GPS_PROVIDER)) {finishResult(location);} else {doLocationResult(location);}
removeProvider(location.getProvider());if (isEmptyValidProviders()) {requestTimeoutMsgInit();removeUpdates();}}
@Overridepublic void onStatusChanged(String provider, int status, Bundle extras) {}
@Overridepublic void onProviderEnabled(String provider) {}
@Overridepublic void onProviderDisabled(String provider) {}};getLocationManager().requestLocationUpdates(provider, minTime, minDistance, locationListener);mMapLocationListeners.put(provider, locationListener);EasyLog.d("Location request %s provider update.", provider);}isRequesting = true;return true;}
//remove request updatepublic void removeUpdates() {checkRuntimeEnvironment();
LocationManager locationManager = getLocationManager();if (mMapLocationListeners != null) {Set<String> keys = mMapLocationListeners.keySet();for (String key : keys) {LocationListener locationListener = mMapLocationListeners.get(key);if (locationListener != null) {locationManager.removeUpdates(locationListener);EasyLog.d("Remove location update, provider is " + key);}}mMapLocationListeners.clear();isRequesting = false;}}
//Compared with the last successful position, to determine whether you need to filterprivate boolean isNeedFilter(Location location) {checkLocation(location);
if (mLastLocation != null) {float distance = location.distanceTo(mLastLocation);if (distance < getCheckMinDistance()) {return true;}if (location.getAccuracy() >= mLastLocation.getAccuracy()&& distance < location.getAccuracy()) {return true;}if (location.getTime() <= mLastProviderTimestamp) {return true;}}return false;}
private void doLocationResult(Location location) {checkLocation(location);
if (isNeedFilter(location)) {EasyLog.d("location need to filtered out, timestamp is " + location.getTime());finishResult(mLastLocation);} else {finishResult(location);}}
//Return to the finished positionprivate void finishResult(Location location) {checkLocation(location);
double latitude = location.getLatitude();double longitude = location.getLongitude();float accuracy = location.getAccuracy();long time = location.getTime();String provider = location.getProvider();
if (mLocationResultListeners != null && !mLocationResultListeners.isEmpty()) {String format = "Location result:<%f, %f> Accuracy:%f Time:%d Provider:%s";EasyLog.i(String.format(format, latitude, longitude, accuracy, time, provider));
mLastLocation = location;synchronized (this) {Iterator<LocationResultListener> iterator =  mLocationResultListeners.iterator();while (iterator.hasNext()) {LocationResultListener listener = iterator.next();if (listener != null) {listener.onResult(location);}iterator.remove();}}}}

完整代码:https://github.com/bingerz/FastLocation/blob/master/fastlocationlib/src/main/java/cn/bingerz/fastlocation/FastLocation.java

*每次请求完成定位时,最好删除更新,否则手机状态栏会一直显示定位图标。

这就是我请求用户权限的方式。

在应用程序标记之外AndroidManifest.xml添加这些权限请求。

<uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/><uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

然后在App Gradle文件中添加Google的位置依赖项。

implementation 'com.google.android.gms:play-services-location:15.0.0'

现在声明一些全局变量。

private lateinit var mFusedLocationProvider:FusedLocationProviderClientprivate lateinit var mLocationCallback: LocationCallbackprivate lateinit var mLocationRequest: LocationRequestprivate var mLocationPermissionGranted:Boolean = false

在活动的OnCreate方法中(我无法正确格式化代码,为此道歉)

mFusedLocationProvider = LocationServices.getFusedLocationProviderClient(this)
//Location CallbackmLocationCallback = object: LocationCallback(){override fun onLocationResult(p0: LocationResult?) {if(p0==null){//todo(request user to enable location from settings then remove return)return}else{getDeviceLocation()}}}
//Location RequestmLocationRequest = LocationRequest.create()mLocationRequest.priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY//Set the Interval for Latest Interval UpdatemLocationRequest.interval = 5000//Set How Many Location Updated you WantmLocationRequest.numUpdates = 1
getLocationPermission()getDeviceLocation()

现在创建这两个函数。

 private fun getLocationPermission() {
val permission:Array<String> = arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION,android.Manifest.permission.ACCESS_COARSE_LOCATION)if(ContextCompat.checkSelfPermission(applicationContext,Constant.FINE_LOCATION)== PermissionChecker.PERMISSION_GRANTED){if(ContextCompat.checkSelfPermission(applicationContext,Constant.COARSE_LOCATION)== PermissionChecker.PERMISSION_GRANTED){mLocationPermissionGranted = true}}else{ActivityCompat.requestPermissions(this,permission,Constant.LOCATION_REQUEST_CODE)}
}

第二种方法

private fun getDeviceLocation() {try{if(mLocationPermissionGranted){
mFusedLocationProvider.lastLocation.addOnCompleteListener(this,{task: Task<Location> ->if(task.isSuccessful){var currentLocation: Location? = task.resultif(currentLocation!=null){
Log.i("Location","Latitude is ${currentLocation.latitude} and Longitude" +"${currentLocation.longitude}")}
elsemFusedLocationProvider.requestLocationUpdates(mLocationRequest,mLocationCallback,null)}})}}catch (e:SecurityException){Log.e("Error", "Security Exception ${e.message}")}}

为了Constant.kt

class Constant{companion object {
//Location Request Settingsconst val SET_INTERVAL:Long = 2000const val NUM_UPDATES:Int = 1
//Location Permissionconst val FINE_LOCATION:String = android.Manifest.permission.ACCESS_FINE_LOCATIONconst val COARSE_LOCATION:String = android.Manifest.permission.ACCESS_COARSE_LOCATION}}

在看到所有的答案和问题(简单而强大)之后。我只点击了图书馆Android-被动定位

当我做了一个位置跟踪应用程序。然后我意识到它非常典型的处理位置跟踪与电池优化。

所以我想告诉那些不想在未来的优化中维护他们的位置代码的新手和开发人员。使用这个库。

ReactiveLocationProvider locationProvider = new
ReactiveLocationProvider(context);locationProvider.getLastKnownLocation().subscribe(new Consumer<Location>() {@Overridepublic void call(Location location) {doSthImportantWithObtainedLocation(location);}});

将依赖项放入应用程序级别build.gradle

dependencies {...compile 'pl.charmas.android:android-reactive-location2:2.1@aar'compile 'com.google.android.gms:play-services-location:11.0.4' //you can use newer GMS version if you needcompile 'com.google.android.gms:play-services-places:11.0.4'compile 'io.reactivex:rxjava:2.0.5' //you can override RxJava version if you need}

使用这个lib的优点:

  • 这个库是并将成为积极维护的。
  • 您不必担心电池优化。因为开发人员已经尽了最大努力。
  • 安装方便,放依赖和播放。
  • 轻松连接到Play服务API
  • 获取最后已知位置
  • 订阅位置更新使用
  • 位置设置API
  • 管理地理围栏
  • 地址列表的地理编码位置
  • 活动识别
  • 使用当前位置API获取位置
  • 自动完成建议

从过去一年多的时间里,我一直在使用GPS_PROVIDER和NETWORK_PROVIDER的组合来获取当前位置,并且运行良好,但从过去几个月开始,经过长时间的延迟,我获得了位置,所以我切换到最新的API FusedLocationProviderClient,它运行得非常好。

这是我为使用FusedLocationProviderClient获取当前位置而编写的类。在下面的代码中,我用了一个定时器等待一段时间来获取当前位置,我安排定时器延迟15秒,你可以根据你的需要更改它。

private static FusedLocationService ourInstance;private final LocationRequest locationRequest;private FusedLocationProviderClient mFusedLocationClient;private Location mLastLocation;private Context context;private FindOutLocation findOutLocation;private boolean callbackTriggered = false;private Timer timer;
public static FusedLocationService getInstance(Context pContext) {
if (null == ourInstance) ourInstance = new FusedLocationService(pContext);
return ourInstance;}
private FusedLocationService(Context pContext) {context = pContext;mFusedLocationClient = LocationServices.getFusedLocationProviderClient(context);locationRequest = getLocationRequest();requestLocation(context);}
public Location getLastKnownLocation() {return mLastLocation;}
private void requestLocation(Context context) {
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {return;}mFusedLocationClient.requestLocationUpdates(locationRequest, mLocationCallback, null);mFusedLocationClient.getLastLocation().addOnSuccessListener(location -> {if (location != null) {mLastLocation = location;triggerCallback(mLastLocation);}});}
private LocationRequest getLocationRequest() {LocationRequest locationRequest = new LocationRequest();long INTERVAL = 10 * 1000;long FASTEST_INTERVAL = 5 * 1000;locationRequest.setInterval(INTERVAL);locationRequest.setFastestInterval(FASTEST_INTERVAL);locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);return locationRequest;}
private LocationCallback mLocationCallback = new LocationCallback() {@Overridepublic void onLocationResult(LocationResult locationResult) {for (Location location : locationResult.getLocations()) {if (location != null) mLastLocation = location;}if (null != mLastLocation) triggerCallback(mLastLocation);}};
public static abstract class FindOutLocation {public abstract void gotLocation(Location location);}
@SuppressLint("MissingPermission")public void findLocation(FindOutLocation findOutLocation) {long TIMER_TIME_OUT = 15 * 1000;this.findOutLocation = findOutLocation;callbackTriggered = false;
try {requestLocation(context);timer = new Timer();timer.schedule(new GetLastLocation(context), TIMER_TIME_OUT);} catch (Exception e) {e.printStackTrace();}}
private class GetLastLocation extends TimerTask {Context context;
GetLastLocation(Context context) {this.context = context;}
@Overridepublic void run() {triggerCallback(mLastLocation);}}
private void triggerCallback(Location location) {if (null != location) mLastLocation = location;if (!callbackTriggered && null != findOutLocation) {callbackTriggered = true;removeLocationUpdates();findOutLocation.gotLocation(location);findOutLocation = null;}}
private void removeLocationUpdates() {if (null != timer) timer.cancel();if (null != mFusedLocationClient)mFusedLocationClient.removeLocationUpdates(mLocationCallback);}}

从活动中调用这个,这是代码

    FusedLocationService.FindOutLocation findOutLocation = new FusedLocationService.FindOutLocation() {@Overridepublic void gotLocation(Location currentLocation) {if (currentLocation != null) {/*TODO DO SOMETHING WITH CURRENT LOCATION*/}}};FusedLocationService.getInstance(this).findLocation(findOutLocation);

在AndroidManifest.xml中添加以下条目

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- Needed only if your app targets Android 5.0 (API level 21) or higher. --><uses-feature android:name="android.hardware.location.gps" />

静态编程语言版本@FedorGreate回答:

类的用法:

val locationResult = object : MyLocation.LocationResult() {
override fun gotLocation(location: Location?) {
val lat = location!!.latitudeval lon = location.longitude
Toast.makeText(context, "$lat --SLocRes-- $lon", Toast.LENGTH_SHORT).show()}
}
val myLocation = MyLocation()myLocation.getLocation(inflater.context, locationResult)

MyLocation类:

class MyLocation {internal lateinit var timer1: Timerinternal var lm: LocationManager? = nullinternal lateinit var locationResult: LocationResultinternal var gps_enabled = falseinternal var network_enabled = false
internal var locationListenerGps: LocationListener = object : LocationListener {

override fun onLocationChanged(location: Location) {timer1.cancel()locationResult.gotLocation(location)lm!!.removeUpdates(this)lm!!.removeUpdates(locationListenerNetwork)}
override fun onProviderDisabled(provider: String) {}override fun onProviderEnabled(provider: String) {}override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {}}
internal var locationListenerNetwork: LocationListener = object : LocationListener {override fun onLocationChanged(location: Location) {timer1.cancel()locationResult.gotLocation(location)lm!!.removeUpdates(this)lm!!.removeUpdates(locationListenerGps)}
override fun onProviderDisabled(provider: String) {}override fun onProviderEnabled(provider: String) {}override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {}}
fun getLocation(context: Context, result: LocationResult): Boolean {//I use LocationResult callback class to pass location value from MyLocation to user code.locationResult = resultif (lm == null)lm = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager?
//exceptions will be thrown if provider is not permitted.try {gps_enabled = lm!!.isProviderEnabled(LocationManager.GPS_PROVIDER)} catch (ex: Exception) {}
try {network_enabled = lm!!.isProviderEnabled(LocationManager.NETWORK_PROVIDER)} catch (ex: Exception) {}
//don't start listeners if no provider is enabledif (!gps_enabled && !network_enabled)return false
if (ActivityCompat.checkSelfPermission(context,Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED ||ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) run {
ActivityCompat.requestPermissions(context as Activity,arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION), 111)}

if (gps_enabled)lm!!.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0f, locationListenerGps)if (network_enabled)lm!!.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0f, locationListenerNetwork)timer1 = Timer()timer1.schedule(GetLastLocation(context), 20000)return true}
internal inner class GetLastLocation(var context: Context) : TimerTask() {override fun run() {lm!!.removeUpdates(locationListenerGps)lm!!.removeUpdates(locationListenerNetwork)
var net_loc: Location? = nullvar gps_loc: Location? = null
if (ActivityCompat.checkSelfPermission(context,Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED ||ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) run {
ActivityCompat.requestPermissions(context as Activity,arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION),111)}

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 oneif (gps_loc != null && net_loc != null) {if (gps_loc.getTime() > net_loc.getTime())locationResult.gotLocation(gps_loc)elselocationResult.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)}}
abstract class LocationResult {abstract fun gotLocation(location: Location?)}}

在活动类中创建一个自定义方法:

private void getTheUserPermission() {ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_LOCATION);locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);LocationGetter locationGetter = new LocationGetter(FreshMenuSearchActivity.this, REQUEST_LOCATION, locationManager);

if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
locationGetter.OnGPS();} else {
locationGetter.getLocation();}}

创建一个用户定义的类名LocationGetter:-

public class LocationGetter {
private int REQUEST_LOCATION;private FreshMenuSearchActivity mContext;private LocationManager locationManager;private Geocoder geocoder;
public LocationGetter(FreshMenuSearchActivity mContext, int requestLocation, LocationManager locationManager) {this.mContext = mContext;this.locationManager = locationManager;this.REQUEST_LOCATION = requestLocation;}

public void getLocation() {
if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(mContext,
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(mContext, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_LOCATION);} else {Location LocationGps = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);Location LocationNetwork = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);Location LocationPassive = locationManager.getLastKnownLocation(LocationManager.PASSIVE_PROVIDER);
if (LocationGps != null) {double lat = LocationGps.getLatitude();double longi = LocationGps.getLongitude();getTheAddress(lat, longi);} else if (LocationNetwork != null) {double lat = LocationNetwork.getLatitude();double longi = LocationNetwork.getLongitude();getTheAddress(lat, longi);} else if (LocationPassive != null) {double lat = LocationPassive.getLatitude();double longi = LocationPassive.getLongitude();getTheAddress(lat, longi);} else {Toast.makeText(mContext, "Can't Get Your Location", Toast.LENGTH_SHORT).show();}
}
}
private void getTheAddress(double latitude, double longitude) {List<Address> addresses;geocoder = new Geocoder(mContext, Locale.getDefault());
try {addresses = geocoder.getFromLocation(latitude, longitude, 1);String address = addresses.get(0).getAddressLine(0);String city = addresses.get(0).getLocality();String state = addresses.get(0).getAdminArea();String country = addresses.get(0).getCountryName();String postalCode = addresses.get(0).getPostalCode();String knownName = addresses.get(0).getFeatureName();Log.d("neel", address);} catch (IOException e) {e.printStackTrace();}

}
public void OnGPS() {
final AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
builder.setMessage("Enable GPS").setCancelable(false).setPositiveButton("YES", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {mContext.startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));}}).setNegativeButton("NO", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {
dialog.cancel();}});final AlertDialog alertDialog = builder.create();alertDialog.show();}
}

对@Fedor解决方案的改进。我们可以使用位置管理器的更新时间方法,而不是以“0”时间间隔和“0”距离请求位置。更新的代码(kotlin版本)

import android.annotation.SuppressLintimport android.content.Contextimport android.location.Criteriaimport android.location.Locationimport android.location.LocationListenerimport android.location.LocationManagerimport android.os.Bundleimport java.util.*
@SuppressLint("MissingPermission")class AppLocationProvider {
private lateinit var timer: Timerprivate var locationManager: LocationManager? = nullprivate lateinit var locationCallBack: LocationCallBackprivate var gpsEnabled = falseprivate var networkEnabled = false
private var locationListener: LocationListener = object : LocationListener {
override fun onLocationChanged(location: Location) {timer.cancel()locationCallBack.locationResult(location)}
override fun onProviderDisabled(provider: String) {}override fun onProviderEnabled(provider: String) {}override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {}}
fun getLocation(context : Context, callBack: LocationCallBack): Boolean {locationCallBack = callBackif (locationManager == null)locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager?
//exceptions will be thrown if provider is not permitted.try {gpsEnabled = locationManager!!.isProviderEnabled(LocationManager.GPS_PROVIDER)} catch (ex: Exception) {ex.printStackTrace()}
try {networkEnabled = locationManager!!.isProviderEnabled(LocationManager.NETWORK_PROVIDER)} catch (ex: Exception) {ex.printStackTrace()}
//don't start listeners if no provider is enabledif (!gpsEnabled && !networkEnabled)return false
val criteria = Criteria()if (gpsEnabled) {criteria.accuracy = Criteria.ACCURACY_FINE} else {criteria.accuracy = Criteria.ACCURACY_COARSE}locationManager!!.requestSingleUpdate(criteria, locationListener, null)
timer = Timer()timer.schedule(GetLastKnownLocation(), 5000)return true}
inner class GetLastKnownLocation : TimerTask() {
override fun run() {locationManager!!.removeUpdates(locationListener)
var netLoc: Location? = nullvar gpsLoc: Location? = null
if (gpsEnabled)gpsLoc = locationManager!!.getLastKnownLocation(LocationManager.GPS_PROVIDER)if (networkEnabled)netLoc = locationManager!!.getLastKnownLocation(LocationManager.NETWORK_PROVIDER)
//check which value use the latest oneif (gpsLoc != null && netLoc != null) {if (gpsLoc.time > netLoc.time)locationCallBack.locationResult(gpsLoc)elselocationCallBack.locationResult(netLoc)return}
if (gpsLoc != null) {locationCallBack.locationResult(gpsLoc)return}if (netLoc != null) {locationCallBack.locationResult(netLoc)return}locationCallBack.locationResult(null)}}
interface LocationCallBack {fun locationResult(location: Location?)}}

要获取位置,只需调用getPlace方法-

AppLocationProvider().getLocation(context, object : AppLocationProvider.LocationCallBack {override fun locationResult(location: Location?) {// use location, this might get called in a different thread if a location is a last known location. In that case, you can post location on main thread}})

注:在调用getPlace方法之前,必须授予所需的位置权限。

其中一些ans现在已经过时了,所以我回答说,

FusedLocationProviderClient fusedLocationProviderClient; //set global variableLocation currentLocation;//set global varprivate boolean mLocationPermissionGranted; //set global varfusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(getContext()); //write this oncreatefetchLastLocation();  // call the funct for current location//here is the functionprivate void fetchLastLocation() {
if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION)!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(getActivity(),new String[]{Manifest.permission.ACCESS_FINE_LOCATION},REQUEST_CODE);return;}else {mLocationPermissionGranted=true;}Task<Location> task= fusedLocationProviderClient.getLastLocation();task.addOnSuccessListener(new OnSuccessListener<Location>() {@Overridepublic void onSuccess(Location location) {if(location != null){currentLocation =location;Toast.makeText(getContext(), currentLocation.getLatitude()+"" +" "+currentLocation.getLongitude(),Toast.LENGTH_SHORT).show();//if you want to show in google mapsSupportMapFragment supportMapFragment =(SupportMapFragment)getChildFragmentManager().findFragmentById(R.id.map);supportMapFragment.getMapAsync(MapsFragment.this);}}});

}