public class MapActivity extends BaseActivity implements AMap.OnMapClickListener, LocationSource, AMapLocationListener, View.OnClickListener {
String TAG = "MapActivity";
private BitmapDescriptor ICON_BLUE = BitmapDescriptorFactory
.defaultMarker(BitmapDescriptorFactory.HUE_BLUE);
Button tvTitle;
TextView tvDesc;
MapView mMapView;
AMap mAMap;
/**
* 用于显示当前的位置
* <p>
* 示例中是为了显示当前的位置,在实际使用中,单独的地理围栏可以不使用定位接口
* </p>
*/
private AMapLocationClient mlocationClient;
private OnLocationChangedListener mListener;
private AMapLocationClientOption mLocationOption;
// 中心点marker
private Marker centerMarker;
MarkerOptions markerOption = null;
private List<Marker> markerList = new ArrayList<Marker>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
initUI(savedInstanceState);
markerOption = new MarkerOptions().draggable(true);
init();
}
private void initUI(Bundle savedInstanceState) {
mMapView = findViewById(R.id.mapView);
mMapView.onCreate(savedInstanceState);
tvTitle = findViewById(R.id.tvTitle);
tvDesc = findViewById(R.id.tvDesc);
tvTitle.setOnClickListener(this);
}
/**
* 方法必须重写
*/
@Override
protected void onResume() {
super.onResume();
mMapView.onResume();
//切入前台后关闭后台定位功能
if (null != mlocationClient) {
mlocationClient.disableBackgroundLocation(true);
}
}
/**
* 方法必须重写
*/
@Override
protected void onPause() {
super.onPause();
//如果想要后台定位 这里一定不能打开。
// mMapView.onPause();
// deactivate();
}
@Override
protected void onStop() {
super.onStop();
boolean isBackground = ((MyApplication) getApplication()).isBackground();
//如果app已经切入到后台,启动后台定位功能
if (isBackground) {
if (null != mlocationClient) {
mlocationClient.enableBackgroundLocation(2001, buildNotification());
}
}
}
/**
* 方法必须重写
*/
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mMapView.onSaveInstanceState(outState);
}
private static final String NOTIFICATION_CHANNEL_NAME = "BackgroundLocation";
private NotificationManager notificationManager = null;
boolean isCreateChannel = false;
@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);
notificationChannel.enableLights(true);//是否在桌面icon右上角展示小圆点
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.mipmap.ic_launcher)
.setContentTitle(Utils.getAppName(this))
.setContentText("正在后台运行")
.setWhen(System.currentTimeMillis());
if (android.os.Build.VERSION.SDK_INT >= 16) {
notification = builder.build();
} else {
return builder.getNotification();
}
return notification;
}
/**
* 方法必须重写
*/
@Override
protected void onDestroy() {
super.onDestroy();
mMapView.onDestroy();
if (null != mlocationClient) {
/**
* 如果AMapLocationClient是在当前Activity实例化的,
* 在Activity的onDestroy中一定要执行AMapLocationClient的onDestroy
*/
mlocationClient.onDestroy();
mlocationClient = null;
mLocationOption = null;
}
}
private void init() {
if (mAMap == null) {
mAMap = mMapView.getMap();
mAMap.getUiSettings().setRotateGesturesEnabled(false);
mAMap.moveCamera(CameraUpdateFactory.zoomBy(6));
setUpMap();
}
}
/**
* 设置一些amap的属性
*/
private void setUpMap() {
mAMap.setOnMapClickListener(this);
mAMap.setLocationSource(this);// 设置定位监听
mAMap.getUiSettings().setMyLocationButtonEnabled(true);// 设置默认定位按钮是否显示
mAMap.setMyLocationEnabled(true);// 设置为true表示显示定位层并可触发定位,false表示隐藏定位层并不可触发定位,默认是false
mAMap.setMyLocationType(AMap.LOCATION_TYPE_LOCATE);// 跟随模式
// 自定义系统定位蓝点
MyLocationStyle myLocationStyle = new MyLocationStyle();
// 自定义定位蓝点图标
myLocationStyle.myLocationIcon(
BitmapDescriptorFactory.fromResource(R.drawable.gps_point));
// 自定义精度范围的圆形边框颜色
myLocationStyle.strokeColor(Color.argb(0, 0, 0, 0));
// 自定义精度范围的圆形边框宽度
myLocationStyle.strokeWidth(0);
// 设置圆形的填充颜色
myLocationStyle.radiusFillColor(Color.argb(0, 0, 0, 0));
// 将自定义的 myLocationStyle 对象添加到地图上
mAMap.setMyLocationStyle(myLocationStyle);
// 设置定位的类型为定位模式 ,可以由定位、跟随或地图根据面向方向旋转几种
mAMap.setMyLocationRotateAngle(AMap.LOCATION_TYPE_LOCATE);
}
/**
* 点击地图的位置
*
* @param latLng
*/
@Override
public void onMapClick(LatLng latLng) {
Log.d(TAG, latLng.latitude + " " + latLng.longitude);
markerOption.icon(ICON_BLUE);
addCenterMarker(latLng);
}
private void addCenterMarker(LatLng latlng) {
removeMarkers();
if (null == centerMarker) {
centerMarker = mAMap.addMarker(markerOption);
}
centerMarker.setPosition(latlng);
markerList.add(centerMarker);
}
private void removeMarkers() {
if(null != centerMarker){
centerMarker.remove();
centerMarker = null;
}
if (null != markerList && markerList.size() > 0) {
for (Marker marker : markerList) {
marker.remove();
}
markerList.clear();
}
}
/**
* 激活定位
*/
@Override
public void activate(OnLocationChangedListener listener) {
mListener = listener;
if (mlocationClient == null) {
mlocationClient = new AMapLocationClient(this);
mLocationOption = new AMapLocationClientOption();
// 设置定位监听
mlocationClient.setLocationListener(this);
// 设置为高精度定位模式
//高精度:这种定位模式下,会同时使用网络定位(基站、WIFI定位)和GPS定位,优先返回最高精度的定位结果。
//低功耗模式定位策略:该定位模式下,不会使用GPS,只会使用网络定位(Wi-Fi和基站定位)。
//仅用设备模式定位策略:这种定位模式下,不需要连接网络,只使用GPS进行定位,这种模式下不支持室内环境的定位。
mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
// 只是为了获取当前位置,所以设置为单次定位
mLocationOption.setOnceLocation(false);
/**
* 设置签到场景,相当于设置为:
* option.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
* option.setOnceLocation(false);
* option.setOnceLocationLatest(false);
* option.setMockEnable(false);
* option.setWifiScan(true);
*
* 其他属性均为模式属性。
* 如果要改变其中的属性,请在在设置定位场景之后进行
*/
mLocationOption.setLocationPurpose(AMapLocationClientOption.AMapLocationPurpose.Sport);
// 设置定位参数
mlocationClient.setLocationOption(mLocationOption);
mlocationClient.startLocation();
}
}
/**
* 停止定位
*/
@Override
public void deactivate() {
mListener = null;
if (mlocationClient != null) {
mlocationClient.stopLocation();
mlocationClient.onDestroy();
}
mlocationClient = null;
}
/**
* 定位成功后回调函数
*/
@Override
public void onLocationChanged(AMapLocation amapLocation) {
if (mListener != null && amapLocation != null) {
if (amapLocation != null && amapLocation.getErrorCode() == 0) {
mListener.onLocationChanged(amapLocation);// 显示系统小蓝点
String info = Utils.getLocationStr(amapLocation);
tvDesc.setText("定位成功:" + info);
} else {
String errText = "定位失败," + amapLocation.getErrorCode() + ": "
+ amapLocation.getErrorInfo();
tvDesc.setText("定位失败" + errText);
}
}
}
boolean isOpenDesc = true;
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.tvTitle:
if (isOpenDesc) {
tvDesc.setVisibility(View.VISIBLE);
} else {
tvDesc.setVisibility(View.GONE);
}
isOpenDesc = !isOpenDesc;
break;
}
}
}
public class MyApplication extends Application {
private int count = 0;
@Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
@Override
public void onActivityStarted(Activity activity) {
count++;
}
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
if (count > 0) {
count--;
}
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
}
});
}
/**
* 判断app是否在后台
*
* @return
*/
public boolean isBackground() {
if (count <= 0) {
return true;
} else {
return false;
}
}
}
public class Utils {
/**
* 根据定位结果返回定位信息的字符串
* @param location
* @return
*/
public synchronized static String getLocationStr(AMapLocation location) {
if (null == location) {
return null;
}
StringBuffer sb = new StringBuffer();
//errCode等于0代表定位成功,其他的为定位失败,具体的可以参照官网定位错误码说明
if (location.getErrorCode() == 0) {
sb.append("定位成功" + "\n");
sb.append("定位类型: " + getLocationTypeName(location.getLocationType()) + "\n");
sb.append("经 度 : " + location.getLongitude() + "\n");
sb.append("纬 度 : " + location.getLatitude() + "\n");
sb.append("精 度 : " + location.getAccuracy() + "米" + "\n");
sb.append("提供者 : " + location.getProvider() + "\n");
sb.append("速 度 : " + location.getSpeed() + "米/秒" + "\n");
sb.append("角 度 : " + location.getBearing() + "\n");
// 获取当前提供定位服务的卫星个数
sb.append("星 数 : " + location.getSatellites() + "\n");
sb.append("国 家 : " + location.getCountry() + "\n");
sb.append("省 : " + location.getProvince() + "\n");
sb.append("市 : " + location.getCity() + "\n");
sb.append("城市编码 : " + location.getCityCode() + "\n");
sb.append("区 : " + location.getDistrict() + "\n");
sb.append("区域 码 : " + location.getAdCode() + "\n");
sb.append("地 址 : " + location.getAddress() + "\n");
sb.append("地 址 : " + location.getDescription() + "\n");
sb.append("兴趣点 : " + location.getPoiName() + "\n");
//定位完成的时间
sb.append("定位时间: " + Utils.formatUTC(location.getTime(), "yyyy-MM-dd HH:mm:ss") + "\n");
} else {
//定位失败
sb.append("定位失败" + "\n");
sb.append("错误码:" + location.getErrorCode() + "\n");
sb.append("错误信息:" + location.getErrorInfo() + "\n");
sb.append("错误描述:" + location.getLocationDetail() + "\n");
}
sb.append("***定位质量报告***").append("\n");
sb.append("* WIFI开关:").append(location.getLocationQualityReport().isWifiAble() ? "开启" : "关闭").append("\n");
sb.append("* GPS状态:").append(Utils.getGPSStatusString(location.getLocationQualityReport().getGPSStatus())).append("\n");
sb.append("* GPS星数:").append(location.getLocationQualityReport().getGPSSatellites()).append("\n");
sb.append("****************").append("\n");
//定位之后的回调时间
sb.append("回调时间: " + Utils.formatUTC(System.currentTimeMillis(), "yyyy-MM-dd HH:mm:ss") + "\n");
//定位之后的回调时间
return sb.toString();
}
private static SimpleDateFormat sdf = null;
public static String formatUTC(long l, String strPattern) {
if (TextUtils.isEmpty(strPattern)) {
strPattern = "yyyy-MM-dd HH:mm:ss";
}
if (sdf == null) {
try {
sdf = new SimpleDateFormat(strPattern, Locale.CHINA);
} catch (Throwable e) {
}
} else {
sdf.applyPattern(strPattern);
}
return sdf == null ? "NULL" : sdf.format(l);
}
/**
* 获取app的名称
* @param context
* @return
*/
public static String getAppName(Context context) {
String appName = "";
try {
PackageManager packageManager = context.getPackageManager();
PackageInfo packageInfo = packageManager.getPackageInfo(
context.getPackageName(), 0);
int labelRes = packageInfo.applicationInfo.labelRes;
appName = context.getResources().getString(labelRes);
} catch (Throwable e) {
e.printStackTrace();
}
return appName;
}
/**
* 获取GPS状态的字符串
* @param statusCode GPS状态码
* @return
*/
public static String getGPSStatusString(int statusCode) {
String str = "";
switch (statusCode) {
case AMapLocationQualityReport.GPS_STATUS_OK:
str = "GPS状态正常";
break;
case AMapLocationQualityReport.GPS_STATUS_NOGPSPROVIDER:
str = "手机中没有GPS Provider,无法进行GPS定位";
break;
case AMapLocationQualityReport.GPS_STATUS_OFF:
str = "GPS关闭,建议开启GPS,提高定位质量";
break;
case AMapLocationQualityReport.GPS_STATUS_MODE_SAVING:
str = "选择的定位模式中不包含GPS定位,建议选择包含GPS定位的模式,提高定位质量";
break;
case AMapLocationQualityReport.GPS_STATUS_NOGPSPERMISSION:
str = "没有GPS定位权限,建议开启gps定位权限";
break;
}
return str;
}
public static String getLocationTypeName(int locationType) {
String typeName = "";
switch (locationType) {
case 0:
typeName = "定位失败";
break;
case 1:
typeName = "GPS定位结果";
break;
case 2:
typeName = "前次定位结果";
break;
case 3:
typeName = "3";
break;
case 4:
typeName = "缓存定位结果";
break;
case 5:
typeName = "Wifi定位结果";
break;
case 6:
typeName = "基站定位结果";
break;
case 7:
typeName = "7";
break;
case 8:
typeName = "离线定位结果";
break;
case 9:
typeName = "最后位置缓存";
break;
default:
typeName = String.valueOf(locationType);
break;
}
return typeName;
}
}