What is the simplest and most robust way to get the user's current location on Android?
android上的
我正在开发的应用本身并不是一个定位应用,但它需要获得用户的位置才能显示附近企业的列表。它不需要担心用户是否在移动或类似的事情。
我想做的是:
看起来不应该那么难,但在我看来,我必须启动两个不同的位置提供商(GPS和网络)并管理每个提供商的生命周期。不仅如此,我还必须在多个活动中复制相同的代码以满足2。过去我曾尝试使用
有没有一个更简单的方法来完成这个?
我要做的是:
以下是我如何使用我的课程:
1 2 3 4 5 6 7 8 | LocationResult locationResult = new LocationResult(){ @Override public void gotLocation(Location location){ //Got the location! } }; MyLocation myLocation = new MyLocation(); myLocation.getLocation(this, locationResult); |
这是我的位置分类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | 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); } } |
也有人想修改我的逻辑。例如,如果从网络提供商处获得更新,不要停止侦听器,而是继续等待。GPS提供更精确的数据,因此值得等待。如果计时器超时,并且您已从网络获得更新,但不是从GPS获得更新,那么您可以使用网络提供的值。
另一种方法是使用locationclient http://developer.android.com/training/location/retrieve-current.html。但它需要在用户设备上安装Google Play Services APK。
在寻找了如何获得最佳精确用户位置的最佳实现之后,我设法将所有最佳方法结合起来,并提出了以下类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 | /** * 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 tying if(counts > 120){ stop = true; } //update last best location bestLocation = getLocation(context); //if location is not ready or don`t exists, try again if(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 finded return result to main. sat_count=" + sat_count); System.println("#########################################"); // removing all updates and listeners myLocationManager.removeUpdates(gpsLocationListener); myLocationManager.removeUpdates(networkLocationListener); myLocationManager.removeGpsStatusListener(gpsStatusListener); sat_count = 0; // send best location to locationResult locationResult.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 stop if(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 updates myLocationManager.requestLocationUpdates("network", 0, 0, networkLocationListener); myLocationManager.requestLocationUpdates("gps", 0, 0, gpsLocationListener); myLocationManager.addGpsStatusListener(gpsStatusListener); // starting best location finder loop handler.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 state GpsStatus 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(){ @Override public 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(){ @Override public 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 it try { 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,该类将尝试连接到
使用Fedor的解决方案,我经历了多次执行回调
为了减少这种错误行为的可能性,可以在触发OnLocationChanged事件之前调用removeUpdates,但我们仍然有争用条件。
我发现最好的解决办法是用
这是我的版本,基于Fedor的解决方案,使用处理程序向Looper线程发送消息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | 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 one if (gpsLocation != null && networkLocation != null) { if (gpsLocation.getTime() > networkLocation.getTime()) locationResult.gotLocation(gpsLocation); else locationResult.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 enabled if (!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 { @Override public void run() { locationTimeoutHandler.sendEmptyMessage(0); } } public static abstract class LocationResult { public abstract void gotLocation(Location location); } } |
我从自定义的looper线程使用这个类,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | public class LocationGetter { private final Context context; private Location location = null; private final Object gotLocationLock = new Object(); private final LocationResult locationResult = new LocationResult() { @Override public 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()); else coordinates = Coordinates.UNDEFINED; return coordinates; } } |
其中,坐标是一个简单的类,具有两个属性:纬度和经度。
我已经创建了一个小应用程序,并逐步描述,以获取当前位置的GPS坐标。
完成以下URL中的示例源代码:
Get Current Location coordinates , City name - in Android
看看它是如何工作的:
我们只需要在清单文件中添加此权限
1
2<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION">
</uses-permission>并创建这样的locationManager实例
1
2LocationManager locationManager = (LocationManager)
getSystemService(Context.LOCATION_SERVICE);检查GPS是否启用
然后实现locationListener并获取坐标
1
2
3LocationListener locationListener = new MyLocationListener();
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, 5000, 10, locationListener);这是要做的示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | /*----------Listener class to get coordinates ------------- */ private class MyLocationListener implements LocationListener { @Override public 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 +" " + latitude +" My Current City is:" + cityName; editLocation.setText(s); } @Override public void onProviderDisabled(String provider) {} @Override public void onProviderEnabled(String provider) {} @Override public void onStatusChanged(String provider, int status, Bundle extras) {} } |
您可以一直使用locationManager.getLastKnownLocation(),但就像它说的那样,它可能已经过时了。
一个简单的方法来获得一个一般的位置可以注册网络(通常相当快)。
1 2 3 | LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); locationManager.requestLocationUpdates( LocationManager.NETWORK_PROVIDER, 1000, 1000, this); |
然后做
1 | locationManager.removeUpdates(this); |
在侦听器的
我已经在demonuts.com上写了详细的教程,介绍了当前的位置。您可以在这里找到更多的描述,还可以下载整个演示源代码,以便更好地理解。
已经有很多答案了,但我想展示使用谷歌API获取位置的最新方法,这样新的程序员可以使用新方法:
首先,把这个放进梯度文件
1 | compile 'com.google.android.gms:play-services:8.4.0' |
然后实现必要的接口
1 | public class MainActivity extends BaseActivitiy implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, com.google.android.gms.location.LocationListener |
声明实例
1 2 3 4 | private GoogleApiClient mGoogleApiClient; private Location mLocation; private LocationManager locationManager; private LocationRequest mLocationRequest; |
把这个放在
1 2 3 4 5 6 | mGoogleApiClient = new GoogleApiClient.Builder(this) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .addApi(LocationServices.API) .build(); locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); |
最后,重写必要的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | @Override public 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 request mLocationRequest = LocationRequest.create() .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY) .setInterval(UPDATE_INTERVAL) .setFastestInterval(FASTEST_INTERVAL); // Request location updates 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; } LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this); Log.d("reque","--->>>>"); } @Override public void onConnectionSuspended(int i) { Log.i(TAG,"Connection Suspended"); mGoogleApiClient.connect(); } @Override public void onConnectionFailed(ConnectionResult connectionResult) { Log.i(TAG,"Connection failed. Error:" + connectionResult.getErrorCode()); } @Override public void onStart() { super.onStart(); mGoogleApiClient.connect(); } @Override public void onStop() { super.onStop(); if (mGoogleApiClient.isConnected()) { mGoogleApiClient.disconnect(); } } @Override public void onLocationChanged(Location location) { } |
在运行应用程序之前,不要忘记在设备中启动GPS。
我不确定基于位置的服务是否可以从GPS以外的其他基础设施获取位置,但根据那篇文章,这似乎是可能的:
Applications can call on any of
several types of positioning methods.Using the mobile phone network: The
current cell ID can be used to
identify the Base Transceiver Station
(BTS) that the device is communicating
with and the location of that BTS.
Clearly, the accuracy of this method
depends on the size of the cell, and
can be quite inaccurate. A GSM cell
may be anywhere from 2 to 20
kilometers in diameter. Other
techniques used along with cell ID can
achieve accuracy within 150 meters.Using satellites: The Global
Positioning System (GPS), controlled
by the US Department of Defense, uses
a constellation of 24 satellites
orbiting the earth. GPS determines the
device's position by calculating
differences in the times signals from
different satellites take to reach the
receiver. GPS signals are encoded, so
the mobile device must be equipped
with a GPS receiver. GPS is
potentially the most accurate method
(between 4 and 40 meters if the GPS
receiver has a clear view of the sky),
but it has some drawbacks: The extra
hardware can be costly, consumes
battery while in use, and requires
some warm-up after a cold start to get
an initial fix on visible satellites.
It also suffers from"canyon effects"
in cities, where satellite visibility
is intermittent.Using short-range
positioning beacons: In relatively
small areas, such as a single
building, a local area network can
provide locations along with other
services. For example, appropriately
equipped devices can use Bluetooth for
short-range positioning.
使用以下代码,它将提供可用的最佳提供商:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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); |
建议使用
首先,定义位置更新间隔值。根据你的需要调整这个。
1 2 3 4 | 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; |
让你的
1 2 | public class LocationActivity extends Activity implements GooglePlayServicesClient.ConnectionCallbacks, GooglePlayServicesClient.OnConnectionFailedListener, LocationListener {} |
然后,在你的
1 2 3 4 5 6 7 8 9 10 | 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); } |
向您的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | @Override public void onConnectionFailed(ConnectionResult connectionResult) { Log.w(TAG,"Location client connection failed"); } @Override public void onConnected(Bundle dataBundle) { Log.d(TAG,"Location client connected"); mLocationClient.requestLocationUpdates(mLocationRequest, this); } @Override public void onDisconnected() { Log.d(TAG,"Location client disconnected"); } @Override public 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"); } } |
一定要连接/断开
1 2 3 4 5 6 7 8 9 10 11 12 | public void onResume() { super.onResume(); mLocationClient.connect(); } public void onStop() { if (mLocationClient.isConnected()) { mLocationClient.removeLocationUpdates(this); } mLocationClient.disconnect(); super.onStop(); } |
获取用户的位置。首先尝试使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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; } } } |
实际上,我们可以使用这两个提供商(GPS和网络)。他们只是分享一个公共听众:
1 2 | locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 10 * 1000, (float) 10.0, listener); locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 90 * 1000, (float) 10.0, listener); |
这是必需的,因为总是需要及时调用
这是提供用户当前位置的代码
创建映射活动:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | 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(); @Override protected 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) { @Override public void onTick(long millisUntilFinished) { if (location != null) locationtimer.cancel(); } @Override public 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 stub Intent intent = new Intent(Maps.this, GridViewContainer.class); startActivity(intent); finish(); } }); } @Override protected boolean isRouteDisplayed() { return false; } class MapOverlay extends Overlay { private GeoPoint pointToDraw; public void setPointToDraw(GeoPoint point) { pointToDraw = point; } public GeoPoint getPointToDraw() { return pointToDraw; } @Override public 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; } } } |
MIN .XML:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <?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.MapView android: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> |
并在清单中定义以下权限:
1 2 3 | <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"/> |
要获取和显示用户的当前位置,您还可以使用
1 2 3 | myLocationOverlay = new MyLocationOverlay(this, mapView); myLocationOverlay.enableMyLocation(); mapView.getOverlays().add(myLocationOverlay); |
这将从GPS或网络中获取当前位置。如果两者都失败,
至于该地区周围事物的位置,一个
希望我没有误解你的问题。祝你好运。
即使这里已经给出了答案。我只是想把这个分享给全世界,以防遇到这样的情况。
我的要求是,我需要在最长30到35秒内获得用户的当前位置,所以这里是我根据Nirav Ranpara的答案得出的解决方案。
1。我做了mylocationmanager.java类,它处理所有的GPS和网络事务。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 | 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 status isGPSEnabled = locationManager .isProviderEnabled(LocationManager.GPS_PROVIDER); // Getting network status isNetworkEnabled = locationManager .isProviderEnabled(LocationManager.NETWORK_PROVIDER); if (!isGPSEnabled && !isNetworkEnabled) { // No network provider is enabled showSettingsAlertDialog(); } else { // If GPS enabled, get latitude/longitude using GPS Services if (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() { @Override public 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() { @Override public void onStatusChanged(String provider, int status, Bundle extras) { // TODO Auto-generated method stub } @Override public void onProviderEnabled(String provider) { // TODO Auto-generated method stub } @Override public void onProviderDisabled(String provider) { // TODO Auto-generated method stub } @Override public 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() { @Override public void onStatusChanged(String provider, int status, Bundle extras) { // TODO Auto-generated method stub } @Override public void onProviderEnabled(String provider) { // TODO Auto-generated method stub } @Override public void onProviderDisabled(String provider) { // TODO Auto-generated method stub } @Override public 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 Title alertDialog.setTitle("GPS is settings"); // Setting Dialog Message alertDialog .setMessage("GPS is not enabled. Do you want to go to settings menu?"); // On pressing the Settings button. alertDialog.setPositiveButton("Settings", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Intent intent = new Intent( Settings.ACTION_LOCATION_SOURCE_SETTINGS); mContext.startActivity(intent); } }); // On pressing the cancel button alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.cancel(); } }); // Showing Alert Message alertDialog.show(); } } |
2。我做了一个接口(callback)onlocationDetectionListener.java,以便将结果传达回调用片段或活动
1 2 3 4 5 | import android.location.Location; public interface OnLocationDetectectionListener { public void onLocationDetected(Location mLocation); } |
三。然后我做了一个mainAppActivity.java活动来实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | public class MainAppActivty extends Activity implements OnLocationDetectectionListener { private Location currentLocation; private MyLocationManager mLocationManager; @Override protected void onCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_home); super.onCreate(savedInstanceState); mLocationManager = new MyLocationManager(this, this); mLocationManager.startLocating(); } @Override public void onLocationDetected(Location mLocation) { //Your new Location is received here currentLocation = mLocation; } |
4。向清单文件添加以下权限
1 2 | <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> |
希望这对其他人有帮助:)
编辑:使用Google Play Services库中最新的位置服务API进行更新(2014年7月)
我建议您使用新的定位服务API,该API可从Google Play服务库中获得,它提供了一个更强大、更高级的框架,可以自动执行位置提供者选择和电源管理等任务。根据官方文件:"…位置API使您可以轻松地构建位置感知应用程序,而无需关注底层位置技术的细节。它们还允许您通过使用设备硬件的所有功能将功耗降至最低。"
有关更多信息,请访问:让您的应用程序知道位置
要查看使用最新位置服务API的完整示例,请访问:android locationclient类已弃用,但在文档中使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | 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 easy if (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; } |
有点晚了,但在这种情况下,我会使用谷歌地图API,并使用谷歌地图的lat和long api标记附近的位置。另外,如果你能在地图上显示他/她的位置,用户体验会更好。无需为更新用户位置或使用Android API进行浏览而烦恼。让谷歌地图为您处理内部问题。
@Emmby可能已经在他的应用程序中解决了这个问题,但是为了将来的参考,我向其他开发者推荐的是谷歌地图API中的特定位置的东西。
编辑:用于在谷歌地图中显示用户位置的链接
在安卓系统中需要很多东西来更新位置,需要大量的玻利erplate代码。
你需要照顾好
- Google Play服务可用性检查,
- 如果google play服务旧或不可用,请更新该服务
- 对话创建googleapiclient及其回调连接、断开连接等。
- 停止和释放用于位置更新的资源
- 处理位置权限方案
- 检查位置服务是否打开或关闭
- 获取最新的已知位置也不是那么容易
- 如果在某段时间后未获取位置,则返回到最后一个已知位置
我已经创建了android easylocation(小型android库),它将处理所有这些东西,您可以专注于业务逻辑。
你所需要的只是延长易感活动和这个
1 | requestSingleLocationFix(easyLocationRequest); |
或
1 | requestLocationUpdates(easyLocationRequest); |
请访问https://github.com/akhgupta/android-easylocation查看所需的示例应用程序和步骤。
这是我请求用户权限的方式。
在androidmanifest.xml中的应用程序标记之外,添加这些权限请求。
1 2 3 | <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" /> |
然后在应用程序渐变文件中添加谷歌的位置依赖项。
1 | implementation 'com.google.android.gms:play-services-location:15.0.0' |
现在声明一些全局变量。
1 2 3 4 | private lateinit var mFusedLocationProvider:FusedLocationProviderClient private lateinit var mLocationCallback: LocationCallback private lateinit var mLocationRequest: LocationRequest private var mLocationPermissionGranted:Boolean = false |
在你活动的onCreate方法中(我无法正确地格式化代码,为此道歉)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | mFusedLocationProvider = LocationServices.getFusedLocationProviderClient(this) //Location Callback mLocationCallback = 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 Request mLocationRequest = LocationRequest.create() mLocationRequest.priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY //Set the Interval for Latest Interval Update mLocationRequest.interval = 5000 //Set How Many Location Updated you Want mLocationRequest.numUpdates = 1 getLocationPermission() getDeviceLocation() |
现在创建这两个函数。
1 2 3 4 5 6 7 8 9 10 11 12 | 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) } } |
第二方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | private fun getDeviceLocation() { try{ if(mLocationPermissionGranted){ mFusedLocationProvider.lastLocation.addOnCompleteListener(this,{task: Task<Location> -> if(task.isSuccessful){ var currentLocation: Location? = task.result if(currentLocation!=null){ Log.i("Location","Latitude is ${currentLocation.latitude} and Longitude" + "${currentLocation.longitude}") } else mFusedLocationProvider.requestLocationUpdates(mLocationRequest,mLocationCallback,null) } }) } }catch (e:SecurityException){ Log.e("Error","Security Exception ${e.message}") } } |
为康斯坦特KT
1 2 3 4 5 6 7 8 9 10 11 12 | class Constant{ companion object { //Location Request Settings const val SET_INTERVAL:Long = 2000 const val NUM_UPDATES:Int = 1 //Location Permission const val FINE_LOCATION:String = android.Manifest.permission.ACCESS_FINE_LOCATION const val COARSE_LOCATION:String = android.Manifest.permission.ACCESS_COARSE_LOCATION } } |
从过去一年多的时间里,我一直在利用GPS提供商和网络提供商的组合来获取当前的位置,它运行良好,但从最近几个月开始,经过长时间的延迟,我得到了位置,所以我切换到最新的API FusedLocationProviderClient,它运行良好。
这是我使用fusedLocationProviderClient编写的用于获取当前位置的类。在下面的代码中,我用了一个定时器来等一下,得到了当前的位置,我安排了定时器15秒的延时,你可以根据自己来改变它。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | 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() { @Override public 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; } @Override public 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); } } |
从活动中调用这个,这是代码
1 2 3 4 5 6 7 8 9 | FusedLocationService.FindOutLocation findOutLocation = new FusedLocationService.FindOutLocation() { @Override public void gotLocation(Location currentLocation) { if (currentLocation != null) { /*TODO DO SOMETHING WITH CURRENT LOCATION*/ } } }; FusedLocationService.getInstance(this).findLocation(findOutLocation); |
在androidmanifest.xml中添加以下条目
1 2 3 4 5 | <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" /> |
简单和最佳的地理定位方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 | 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() { @Override public void run() { handler.post(new Runnable() { @Override public 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 updates LocationListener 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 updates lm.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 block e.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(); } |
@fedor greate答案的Kotlin版本:
类的用法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | val locationResult = object : MyLocation.LocationResult() { override fun gotLocation(location: Location?) { val lat = location!!.latitude val lon = location.longitude Toast.makeText(context,"$lat --SLocRes-- $lon", Toast.LENGTH_SHORT).show() } } val myLocation = MyLocation() myLocation.getLocation(inflater.context, locationResult) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | class MyLocation { internal lateinit var timer1: Timer internal var lm: LocationManager? = null internal lateinit var locationResult: LocationResult internal var gps_enabled = false internal 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 = result if (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 enabled if (!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? = null var 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 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) } } abstract class LocationResult { abstract fun gotLocation(location: Location?) } } |
通过使用FusedLocationProviderAPI,这是最新的API,也是在Android中获得位置的最佳可能性之一。将此添加到build.gradle文件中
1 2 3 | dependencies { compile 'com.google.android.gms:play-services:6.5.87' } |
您可以通过此URL获取完整的源代码http://javapapers.com/android/android-location-fused-provider/
我要做的是:
下面是服务代码。您可以根据需要的位置更新频率来运行它。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 | 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; } @Override public 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"); } } @Override public void onStatusChanged(String provider, int status, Bundle extras) { Log.d(TAG,"onStatusChanged provider" + provider); } @Override public void onProviderEnabled(String provider) { Log.d(TAG,"onProviderEnabled provider" + provider); } @Override public void onProviderDisabled(String provider) { Log.d(TAG,"onProviderDisabled provider" + provider); } } private Handler mStopServiceHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case 1: { stopSelf(); } break; } } }; @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { super.onStartCommand(intent, flags, startId); Log.d(TAG,"onStartCommand"); return START_STICKY; } @Override public void onCreate() { super.onCreate(); Log.d(TAG,"onCreate"); requestLocation(); mStopServiceHandler.sendEmptyMessageDelayed(1, TWO_MINUTES); } private void requestLocation() { // Acquire a reference to the system Location Manager if (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 location return true; } // Check whether the new location fix is newer or older long 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 moved if (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 accurate int 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 provider boolean isFromSameProvider = isSameProvider(location.getProvider(), currentBestLocation.getProvider()); // Determine location quality using a combination of timeliness and accuracy if (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); } @Override public 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); } } } } } |
最近重构得到了代码的位置,学习了一些好的思想,最终实现了一个相对完善的库和演示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | //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() { @Override public 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(); } } @Override public void onStatusChanged(String provider, int status, Bundle extras) { } @Override public void onProviderEnabled(String provider) { } @Override public 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 update public 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 filter private 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 position private 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
*每个请求完成的位置,最好删除更新,否则手机状态栏将始终显示定位图标。
在看到所有答案和问题之后(最简单和强大)。我只被点击了图书馆Android的反应位置。
当我做了一个位置跟踪应用程序。然后我意识到用电池优化位置跟踪是非常典型的。
所以我想告诉那些不想在未来优化的情况下维护他们的位置代码的开发人员。使用此库。
1 2 3 4 5 6 7 8 9 10 | ReactiveLocationProvider locationProvider = new ReactiveLocationProvider(context); locationProvider.getLastKnownLocation() .subscribe(new Consumer<Location>() { @Override public void call(Location location) { doSthImportantWithObtainedLocation(location); } }); |
要放入应用程序级build.gradle的依赖项
1 2 3 4 5 6 7 | 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 need compile '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是并将被积极维护的。
- 你不用担心电池优化。因为开发人员已经尽力了。
- 安装简单,放置依赖和播放。
- 轻松连接到播放服务API
- 获取最后一个已知位置
- 订阅位置更新使用
- 位置设置API
- 管理地理围栏
- 地址列表的地理代码位置
- 活动识别
- 使用当前位置API获取位置
- 自动完成建议
在我回答之前,我只想直面我与Neura有关联的事实。现在回答你的问题。因此,您可以使用我们的SDK,而不是浪费时间在编码上以获取用户的位置。集成不到30分钟。Neura为您提供了用户的位置/活动,您可以相应地配置应用程序,以便在收到数据后执行某些任务。以下是使用Neura超过其他活动识别API的几个原因: