这段时间在做项目的时候需要用户后台触发的功能,采用高德地图定位的api进行实现;
1、在使用高德定位之前,需要进行权限的动态申请,在8.0之后定位权限进行了细分
public static final String ACCESS_FINE_LOCATION = "android.permission.ACCESS_FINE_LOCATION";
public static final String ACCESS_COARSE_LOCATION = "android.permission.ACCESS_COARSE_LOCATION";
public static final String ACCESS_BACKGROUND_LOCATION = "android.permission.ACCESS_BACKGROUND_LOCATION";
当应用不需要后台定位的时候可以不申请ACCESS_BACKGROUND_LOCATION
2、权限申请之后,需要开启定位功能。
/**
* 定位相关
*/
AMapLocationClient locationClient = null;
/**
* @description 开启定位
*/
private void statrLocation() {
locationClient = new AMapLocationClient(this);
AMapLocationClientOption option = new AMapLocationClientOption();
option.setLocationPurpose(AMapLocationClientOption.AMapLocationPurpose.Sport); //定位的方式
option.setInterval(3000); //定位间隔时间
option.setSensorEnable(true); //方位变化时候开启
locationClient.setLocationOption(option);
locationClient.setLocationListener(this); //位置变化回调方法
locationClient.startLocation(); //开启定位
}
代码写到这里我们的应用在前台和刚切入后台的时候都可以进行位置变化的更新。
但是当app在后台长时间挂起的时候,定位的后台服务就会被清理,无法准确进行位置信息的更新,所以我们需要在app切入后台的时候手动开启后台定位的功能。
@Override
protected void onPause() {
super.onPause();
if (mapview != null) {
mapview.onPause();
}
if(AndPermission.hasPermissions(this, LOCATION)) { //判断是否开启后台定位的权限
//开始后台定位服务
locationClient.enableBackgroundLocation(2001, buildNotification()); //设置后台定位可以使用,需要通过通知栏的方式进行唤起
}
}
我们给后台定位设置了通知栏,当应用切入后台,我们会在通知栏看到一条通知,提示应用"正在后台运行"
/**
* 后台定位通过通知进行服务唤醒
* @return
*/
@SuppressLint("NewApi")
private Notification buildNotification() {
Notification.Builder builder = null;
Notification notification = null;
if(android.os.Build.VERSION.SDK_INT >= 26) {
//Android O上对Notification进行了修改,如果设置的targetSDKVersion>=26建议使用此种方式创建通知栏
if (null == notificationManager) {
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
}
String channelId = getPackageName();
if(!isCreateChannel) {
NotificationChannel notificationChannel = new NotificationChannel(channelId,
NOTIFICATION_CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
//是否在桌面icon右上角展示小圆点
notificationChannel.enableLights(true);
//小圆点颜色
notificationChannel.setLightColor(Color.BLUE);
//是否在久按桌面图标时显示此渠道的通知
notificationChannel.setShowBadge(true);
notificationManager.createNotificationChannel(notificationChannel);
isCreateChannel = true;
}
builder = new Notification.Builder(getApplicationContext(), channelId);
} else {
builder = new Notification.Builder(getApplicationContext());
}
builder.setSmallIcon(R.drawable.app_logo_round)
.setContentTitle("app")
.setContentText("正在后台运行")
.setWhen(System.currentTimeMillis());
if (android.os.Build.VERSION.SDK_INT >= 16) {
notification = builder.build();
} else {
return builder.getNotification();
}
return notification;
}
当应用从后台切入前台的时候,我们再关闭后台定位服务
@Override
protected void onResume() {
super.onResume();
//取消后台定位服务
if(AndPermission.hasPermissions(this, LOCATION)){
locationClient.disableBackgroundLocation(true);
}
}
在3秒内如果位置有变化就会通过回调方法onLocationChanged()获取位置信息
/**
* @description 定位回调
*/
@Override
public void onLocationChanged(AMapLocation location) {
//errCode等于0代表定位成功,其他的为定位失败,具体的可以参照官网定位错误码说明
if (location.getErrorCode() == 0) {
//纬 度
myLat = location.getLatitude();
//经 度
myLng = location.getLongitude();
float bear = location.getBearing();
//精度/米
location.getAccuracy();
// LoggerManager.e(myLat+","+myLng+":"+location.getAccuracy()+"米");
//定位成功-1.提示gps信号状态 2.在地图上显示定位点
getGpsStatusstring(location.getLocationQualityReport().getGPSStatus());
if(fenceClient.isPause()){
fenceClient.resumeGeoFence();
}
if (mapview != null) {
if (myLng != 0 && myLat != 0) {
mapview.setLocationPoint(myLng, myLat, null, bear);
}
}
} else {
//定位失败-第一次定位失败提示用户定位未开启
myLng = 0;
myLat = 0;
if (firstDingwei) {
LoggerManager.e("locationerror", location.getErrorCode() + "");
ToastUtil.showTopToastFail(mContext, "定位未开启或当前GPS信号弱,位置信息可能发生偏移");
firstDingwei = false;
}
dingweiPiancha = true;
}
}
/**
* 获取GPS状态的字符串
*
* @param statusCode GPS状态码
*/
private void getGpsStatusstring(int statusCode) {
if (isToast && statusCode != AMapLocationQualityReport.GPS_STATUS_OK) {
ToastUtil.showTopToastFail(mContext, "定位未开启或当前GPS信号弱,位置信息可能发生偏移");
isToast = false;
return;
}
if (oldGpsStatus == AMapLocationQualityReport.GPS_STATUS_OK && statusCode != AMapLocationQualityReport.GPS_STATUS_OK) {
ToastUtil.showTopToastFail(mContext, "定位未开启或当前GPS信号弱,位置信息可能发生偏移");
isToast = false;
}
oldGpsStatus = statusCode;
if (statusCode != AMapLocationQualityReport.GPS_STATUS_OK) {
dingweiPiancha = true;
myLat = 0;
myLng = 0;
} else {
dingweiPiancha = false;
}
}
我们可以在onLocationChanged()方法里面实现自己的业务需求,下一面我们将分享地理围栏的使用。