android 定位更新 (Google LocationRequest)
对于定位,首先要先认识下定位地理坐标体系:
还有Android API 定位:
认识完了坐标体系后,我们再进行定位:
明确说明在8.0以后,后台对获取位置的时间做了限制,一个小时内只能获取几次,所有需要在后台使用服务需要注意。
(1)FusedLocationProviderClient LocationRequest
LocationServices.getFusedLocationProviderClient(Context)
.requestLocationUpdates(LocationRequest, LocationCallback, Looper.myLooper());
1]创建 LocationRequest;
2]创建 FusedLocationProviderClient mFusedLocationClient = LocationServices.getFusedLocationProviderClient(context);
3]创建 LocationSettingsRequest, 传入创建好的LocationRequest;
4] 创建 SettingsClient, 检查定位设置是否满足可用;
5]请求 requestLocationUpdates 定位更新;
1 package com.demo.utils.location; 2 3 import android.app.Activity; 4 import android.content.Context; 5 import android.content.IntentSender; 6 import android.location.Location; 7 import android.os.Bundle; 8 import android.os.Looper; 9 import android.support.annotation.NonNull; 10 import android.support.annotation.Nullable; 11 import android.util.Log; 12 import android.widget.Toast; 13 14 import com.google.android.gms.common.ConnectionResult; 15 import com.google.android.gms.common.api.ApiException; 16 import com.google.android.gms.common.api.GoogleApiClient; 17 import com.google.android.gms.common.api.ResolvableApiException; 18 import com.google.android.gms.location.FusedLocationProviderClient; 19 import com.google.android.gms.location.LocationCallback; 20 import com.google.android.gms.location.LocationRequest; 21 import com.google.android.gms.location.LocationResult; 22 import com.google.android.gms.location.LocationServices; 23 import com.google.android.gms.location.LocationSettingsRequest; 24 import com.google.android.gms.location.LocationSettingsResponse; 25 import com.google.android.gms.location.LocationSettingsStatusCodes; 26 import com.google.android.gms.location.SettingsClient; 27 import com.google.android.gms.maps.model.LatLng; 28 import com.google.android.gms.tasks.OnFailureListener; 29 import com.google.android.gms.tasks.OnSuccessListener; 30 31 /** 32 * class: 33 * <p> 34 * 35 * @author charles 36 * created at 17/12/7 37 * @Desciption 38 */ 39 40 public class FusedLocationUtil { 41 42 public static final int REQUEST_CHECK_SETTINGS = 10; 43 44 private GoogleApiClient mGoogleApiClient; 45 private LocationRequest mLocationRequest; 46 private CLocationCallBack mLocationCallBack; 47 private FusedLocationProviderClient mFusedLocationClient; 48 49 private long UPDATE_INTERVAL = 2000; /* 10 secs */ 50 private long FASTEST_INTERVAL = 1000; /* 2 sec */ 51 52 protected FusedLocationUtils() { 53 initGoogleApiClient(); 54 // Create the location request to start receiving updates 55 mLocationRequest = new LocationRequest(); 56 mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); 57 mLocationRequest.setInterval(UPDATE_INTERVAL); 58 mLocationRequest.setFastestInterval(FASTEST_INTERVAL); 59 } 60 61 private void initGoogleApiClient() { 62 mGoogleApiClient = new GoogleApiClient.Builder(AppManager.getInstance()) 63 .addOnConnectionFailedListener(connectionFailedListener) 64 .addConnectionCallbacks(connectionCallbacks) 65 .addApi(LocationServices.API) 66 .build(); 67 } 68 69 //连接google服务失败监听器 70 private GoogleApiClient.OnConnectionFailedListener connectionFailedListener = 71 new GoogleApiClient.OnConnectionFailedListener() { 72 @Override 73 public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { 74 75 int errorCode = connectionResult.getErrorCode(); 76 // 裝置沒有安裝Google Play服務 77 if (errorCode == ConnectionResult.SERVICE_MISSING) { 78 Toast.makeText(DemoApplication.getInstance(), "Google play service missing", Toast.LENGTH_LONG).show(); 79 } 80 81 if (mLocationCallBack != null) { 82 mLocationCallBack.onLatLngResult(new LatLng(0, 0)); 83 mLocationCallBack.onLocationChange(null, true); 84 } 85 } 86 }; 87 88 //连接google服务成功监听器 89 private GoogleApiClient.ConnectionCallbacks connectionCallbacks = 90 new GoogleApiClient.ConnectionCallbacks() { 91 @Override 92 public void onConnected(@Nullable Bundle bundle) { 93 94 } 95 96 @Override 97 public void onConnectionSuspended(int status) { 98 99 } 100 }; 101 102 public void requestLocationUpdate(final Context context, CLocationCallBack callBack) { 103 104 mLocationCallBack = callBack; 105 if (mFusedLocationClient == null) { 106 107 if (context instanceof Activity) { 108 mFusedLocationClient = LocationServices.getFusedLocationProviderClient(((Activity) context)); 109 } else { 110 mFusedLocationClient = LocationServices.getFusedLocationProviderClient(context); 111 } 112 113 // Create LocationSettingsRequest object using location request 114 LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder(); 115 builder.addLocationRequest(mLocationRequest); 116 LocationSettingsRequest locationSettingsRequest = builder.build(); 117 118 // Check whether location settings are satisfied 119 // https://developers.google.com/android/reference/com/google/android/gms/location/SettingsClient 120 SettingsClient settingsClient; 121 122 if (context instanceof Activity) { 123 settingsClient = LocationServices.getSettingsClient(((Activity) context)); 124 } else { 125 settingsClient = LocationServices.getSettingsClient(context); 126 } 127 128 settingsClient.checkLocationSettings(locationSettingsRequest) 129 .addOnSuccessListener(new OnSuccessListener<LocationSettingsResponse>() { 130 @Override 131 public void onSuccess(LocationSettingsResponse locationSettingsResponse) { 132 133 android.util.Log.e("checkLocationSettings", "==onSuccess"); 134 135 startLocationUpdates(); 136 } 137 }) 138 .addOnFailureListener(new OnFailureListener() { 139 @Override 140 public void onFailure(@NonNull Exception e) { 141 int statusCode = ((ApiException) e).getStatusCode(); 142 switch (statusCode) { 143 case LocationSettingsStatusCodes.RESOLUTION_REQUIRED: 144 Log.i("FusedLocationUtils", "Location settings are not satisfied. Attempting to upgrade " + 145 "location settings "); 146 if (context instanceof Activity) { 147 try { 148 // Show the dialog by calling startResolutionForResult(), and check the 149 // result in onActivityResult(). 150 ResolvableApiException rae = (ResolvableApiException) e; 151 rae.startResolutionForResult(((Activity) context), REQUEST_CHECK_SETTINGS); 152 } catch (IntentSender.SendIntentException sie) { 153 Log.i("FusedLocationUtils", "PendingIntent unable to execute request."); 154 } 155 } 156 break; 157 case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE: 158 159 String errorMessage = "Location settings are inadequate, and cannot be " + 160 "fixed here. Fix in Settings."; 161 Log.e("FusedLocationUtils", errorMessage); 162 if (context instanceof Activity) { 163 Toast.makeText(context, errorMessage, Toast.LENGTH_LONG).show(); 164 } 165 } 166 } 167 }); 168 } 169 170 if (mGoogleApiClient.isConnected()) { 171 // new Google API SDK v11 uses getFusedLocationProviderClient(this) 172 mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, 173 Looper.myLooper()); 174 return; 175 } 176 177 if (mGoogleApiClient.isConnecting()) 178 return; 179 mGoogleApiClient.connect(); 180 } 181 182 // Trigger new location updates at interval 183 public void startLocationUpdates() { 184 185 if (mFusedLocationClient != null) { 186 mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, 187 Looper.myLooper()); 188 } 189 190 } 191 192 private LocationCallback mLocationCallback = new LocationCallback() { 193 @Override 194 public void onLocationResult(LocationResult locationResult) { 195 196 android.util.Log.e("FusedLocationUtils", "onLocationResult"); 197 198 if (locationResult == null || locationResult.getLastLocation() == null) { 199 return; 200 } 201 202 Location lastLocation = locationResult.getLastLocation(); 203 204 android.util.Log.e("onLocationResult", "==locationResult:" + lastLocation.toString()); 205 206 if (mLocationCallBack != null) { 207 mLocationCallBack.onLatLngResult(new LatLng(lastLocation.getLatitude(), lastLocation.getLongitude())); 208 mLocationCallBack.onLocationChange(lastLocation, true); 209 } 210 } 211 }; 212 213 public void stopLocation() { 214 if (mFusedLocationClient != null) { 215 mFusedLocationClient.removeLocationUpdates(mLocationCallback); 216 } 217 } 218 219 public void recycleResource() { 220 if (mGoogleApiClient.isConnected() || mGoogleApiClient.isConnecting()) 221 mGoogleApiClient.disconnect(); 222 if (mFusedLocationClient != null) { 223 mFusedLocationClient = null; 224 } 225 mLocationCallBack = null; 226 } 227 228 }
(2)FusedLocationApi LocationRequest
LocationServices.FusedLocationApi.requestLocationUpdates(LocationRequest)
1]初始化 GoogleApiClient;
2]创建LocationRequest;
3]外部调用传入定位回调时,连接google服务;
4]GoogleApiClient.ConnectionCallbacks 回调,表明连接google服务成功,连接成功后,开始定位请求;
5]GoogleApiClient.OnConnectionFailedListener 回调,表明连接google服务失败,可在此回调进行相对应的提示;
1 package com.demo.utils.location; 2 3 import android.location.Location; 4 import android.os.Bundle; 5 import android.support.annotation.NonNull; 6 import android.support.annotation.Nullable; 7 import android.widget.Toast; 8 9 import com.google.android.gms.common.ConnectionResult; 10 import com.google.android.gms.common.api.GoogleApiClient; 11 import com.google.android.gms.location.LocationListener; 12 import com.google.android.gms.location.LocationRequest; 13 import com.google.android.gms.location.LocationServices; 14 import com.google.android.gms.maps.model.LatLng; 15 16 /** 17 * Created by Charles on 17/6/30. 18 */ 19 20 public class GoogleLocationUtil { 21 22 private GoogleApiClient mGoogleApiClient; 23 private LocationRequest mLocationRequest; 24 private CLocationCallBack mLocationCallBack; 25 26 protected GoogleLocationUtils() { 27 initGoogleApiClient(); 28 createLocationRequest(); 29 } 30 31 private void initGoogleApiClient() { 32 mGoogleApiClient = new GoogleApiClient.Builder(DemoApplication.getInstance()) 33 .addOnConnectionFailedListener(connectionFailedListener) 34 .addConnectionCallbacks(connectionCallbacks) 35 .addApi(LocationServices.API) 36 .build(); 37 } 38 39 private void createLocationRequest() { 40 mLocationRequest = LocationRequest.create(); 41 mLocationRequest.setInterval(2000); 42 mLocationRequest.setFastestInterval(1000); 43 mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); 44 } 45 46 //连接google服务失败监听器 47 private GoogleApiClient.OnConnectionFailedListener connectionFailedListener = 48 new GoogleApiClient.OnConnectionFailedListener() { 49 @Override 50 public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { 51 52 int errorCode = connectionResult.getErrorCode(); 53 // 裝置沒有安裝Google Play服務 54 if (errorCode == ConnectionResult.SERVICE_MISSING) { 55 Toast.makeText(DemoApplication.getInstance(), "Google play service missing", Toast.LENGTH_LONG).show(); 56 } 57 58 if (mLocationCallBack != null) { 59 mLocationCallBack.onLatLngResult(new LatLng(0, 0)); 60 mLocationCallBack.onLocationChange(null, true); 61 } 62 } 63 }; 64 65 //连接google服务成功监听器 66 private GoogleApiClient.ConnectionCallbacks connectionCallbacks = 67 new GoogleApiClient.ConnectionCallbacks() { 68 @Override 69 public void onConnected(@Nullable Bundle bundle) { 70 startLocationUpdate(); 71 } 72 73 @Override 74 public void onConnectionSuspended(int status) { 75 if (mLocationCallBack != null) { 76 mLocationCallBack.onLatLngResult(new LatLng(0, 0)); 77 mLocationCallBack.onLocationChange(null, true); 78 } 79 } 80 }; 81 82 private LocationListener locationListener = new LocationListener() { 83 @Override 84 public void onLocationChanged(Location location) { 85 Log.e("onLocationChanged", "Google location is:", location.toString()); 86 if (mLocationCallBack != null) { 87 mLocationCallBack.onLatLngResult(new LatLng(location.getLatitude(), location.getLongitude())); 88 mLocationCallBack.onLocationChange(location, true); 89 } 90 } 91 }; 92 93 private void startLocationUpdate() { 94 if (!mGoogleApiClient.isConnected()) 95 return; 96 97 Location lastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient); 98 99 if (lastLocation != null) { 100 Log.e("startLocationUpdate", "== the last google location is:", lastLocation.toString()); 101 if (mLocationCallBack != null) { 102 mLocationCallBack.onLatLngResult(new LatLng(lastLocation.getLatitude(), lastLocation.getLongitude())); 103 mLocationCallBack.onLocationChange(lastLocation, false); 104 } 105 } 106 107 LocationServices.FusedLocationApi.requestLocationUpdates( 108 mGoogleApiClient, mLocationRequest, locationListener); 109 } 110 111 public void requestLocationUpdate() { 112 113 if (mGoogleApiClient == null || mLocationRequest == null || locationListener == null) { 114 return; 115 } 116 117 if (!mGoogleApiClient.isConnected()) 118 return; 119 120 LocationServices.FusedLocationApi.requestLocationUpdates( 121 mGoogleApiClient, mLocationRequest, locationListener); 122 } 123 124 public void requestLocation(CLocationCallBack locationCallBack) { 125 this.mLocationCallBack = locationCallBack; 126 if (mGoogleApiClient.isConnected()) { 127 LocationServices.FusedLocationApi.requestLocationUpdates 128 (mGoogleApiClient, mLocationRequest, locationListener); 129 return; 130 } 131 if (mGoogleApiClient.isConnecting()) 132 return; 133 mGoogleApiClient.connect(); 134 } 135 136 public void stopUpdate() { 137 if (mGoogleApiClient.isConnected()) 138 LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, locationListener); 139 } 140 141 public void stopLocation() { 142 if (mGoogleApiClient.isConnected() || mGoogleApiClient.isConnecting()) 143 mGoogleApiClient.disconnect(); 144 145 mLocationCallBack = null; 146 } 147 148 public boolean isConnected() { 149 return mGoogleApiClient != null && mGoogleApiClient.isConnected(); 150 } 151 152 }
以上两种方式是Google提供的位置服务:
The getLastLocation()
method returns a Task
that you can use to get a Location
object with the latitude and longitude coordinates of a geographic location. The location object may be null
in the following situations:
- Location is turned off in the device settings. The result could be
null
even if the last location was previously retrieved because disabling location also clears the cache. - The device never recorded its location, which could be the case of a new device or a device that has been restored to factory settings.
- Google Play services on the device has restarted, and there is no active Fused Location Provider client that has requested location after the services restarted. To avoid this situation you can create a new client and request location updates yourself. For more information, see Receiving Location Updates.
因为是获取上一次定位的信息,所以location在以下几种情况会返回null
- 在定位服务被关闭的时候,因为关闭后会清除上次的定位信息
- 设备从未记录其位置,可能是新设备或已恢复出厂设置的设备
- 设备不支持Google Play服务
- 设备上的Google Play服务已重新启动。
(3)高德定位:
1] 在AndroidManifest 中,<application>节点中,添加如下代码:
1 <meta-data android:name="com.amap.api.v2.apikey" android:value="your key" /> 2 3 <service android:name="com.amap.api.location.APSService"></service>
2] 使用;
1 public class AMapLocationUtil implements AMapLocationListener { 2 3 protected AMapLocationUtil() { 4 mlocationClient = new AMapLocationClient(AppManager.getInstance()); 5 //初始化定位参数 6 mLocationOption = new AMapLocationClientOption(); 7 //设置定位监听 8 mlocationClient.setLocationListener(this); 9 //设置定位模式为高精度模式,Battery_Saving为低功耗模式,Device_Sensors是仅设备模式 10 mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy); 11 //设置定位间隔,单位毫秒,默认为2000ms 12 mLocationOption.setInterval(2000); 13 mLocationOption.setNeedAddress(false); 14 mLocationOption.setMockEnable(false); 15 //设置定位参数 16 mlocationClient.setLocationOption(mLocationOption); 17 18 mLastLocation = new Location(""); 19 } 20 21 //声明mlocationClient对象 22 private AMapLocationClient mlocationClient; 23 //声明mLocationOption对象 24 private AMapLocationClientOption mLocationOption = null; 25 private CLocationCallBack mLocationCallBack; 26 private Location mLastLocation; 27 28 public void requestLocationUpdate(CLocationCallBack callBack) { 29 mLocationCallBack = callBack; 30 31 // 此方法为每隔固定时间会发起一次定位请求,为了减少电量消耗或网络流量消耗, 32 // 注意设置合适的定位时间的间隔(最小间隔支持为1000ms),并且在合适时间调用stopLocation()方法来取消定位请求 33 // 在定位结束后,在合适的生命周期调用onDestroy()方法 34 // 在单次定位情况下,定位无论成功与否,都无需调用stopLocation()方法移除请求,定位sdk内部会移除 35 //启动定位 36 mlocationClient.startLocation(); 37 } 38 39 public void startLocation() { 40 mlocationClient.startLocation(); 41 } 42 43 @Override 44 public void onLocationChanged(AMapLocation aMapLocation) { 45 if (aMapLocation != null) { 46 if (aMapLocation.getErrorCode() == 0) { 47 //定位成功回调信息,设置相关消息 48 aMapLocation.getLatitude();//获取纬度 49 aMapLocation.getLongitude();//获取经度 50 51 double[] wgs84 = JZLocationConverter.gcj02ToWgs84(aMapLocation.getLatitude(), aMapLocation.getLongitude()); 52 53 mLastLocation.setLatitude(wgs84[0]); 54 mLastLocation.setLongitude(wgs84[1]); 55 56 android.util.Log.e("AMapLocationUtil", "onLocationChanged:" + mLastLocation.toString()); 57 58 if (mLocationCallBack != null) { 59 mLocationCallBack.onLatLngResult(new LatLng(mLastLocation.getLatitude(), mLastLocation.getLongitude())); 60 mLocationCallBack.onLocationChange(mLastLocation, false); 61 } 62 63 } else { 64 //显示错误信息ErrCode是错误码,errInfo是错误信息,详见错误码表。 65 android.util.Log.e("AmapError", "location Error, ErrCode:" 66 + aMapLocation.getErrorCode() + ", errInfo:" 67 + aMapLocation.getErrorInfo()); 68 } 69 } 70 } 71 72 public void stopLocation() { 73 if (mlocationClient != null) { 74 mlocationClient.stopLocation(); 75 } 76 } 77 78 public void recycleResource() { 79 mLocationCallBack = null; 80 if (mlocationClient != null) { 81 mlocationClient.unRegisterLocationListener(this); 82 mlocationClient.onDestroy(); 83 } 84 } 85 86 }
统一的对外回调:
1 public interface CLocationCallBack { 2 3 void onLocationChange(Location location, boolean isStopUpdate); 4 5 void onLatLngResult(LatLng latLng); 6 7 }