package com.amap.location.demo;
import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.TextView;
import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationClientOption.AMapLocationMode;
import com.amap.api.location.AMapLocationClientOption.AMapLocationProtocol;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.location.AMapLocationQualityReport;
/**
* Created by hongming.wang on 2018/1/29.
* 后台定位示例
* <p>
* 从Android 8.0开始,Android系统为了实现低功耗,Android 8.0系统对后台应用获取位置的频率进行了限制,只允许每小时几次位置更新。
* 根据Android 8.0的开发指引,为了适配这一系统特性,
* 高德定位SDK从8.0开始增加了两个新接口enableBackgroundLocation和disableBackgroundLocation用来控制是否开启后台定位。
* 开启后sdk会生成一个前台服务通知,告知用户应用正在后台运行,使得开发者自己的应用退到后台的时候,仍有前台通知在,提高应用切入后台后位置更新的频率。
* 如果您的应用在退到后台时本身就有前台服务通知,则无需按照本示例的介绍做适配。<br>
* 示例中提供了两种方法启动和关闭后台定位功能,请根据业务场景进行相应的修改<br>
* 1、通过按钮触发,点击按钮调用相应的接口开开启或者关闭后台定位,此种方法主要是更直观的展示后台定位的功能
* 2、通过生命周期判断APP是否处于后台,当处于后台时才开启后台定位功能,恢复到前台后关闭后台定位功能
* </p>
*/
public class Location_BackGround_Activity extends CheckPermissionsActivity
implements
OnClickListener{
private TextView tvResult;
private Button btEnableBackgroundLocation
; private Button btDisableBackgroundLocation
;
private AMapLocationClient locationClient = null;
private AMapLocationClientOption locationOption = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_location_background);
setTitle(R.string.title_locationBackground);
initView();
initLocation();
}
@Override
protected void onResume() {
super.onResume();
//切入前台后关闭后台定位功能
if(null != locationClient) {
locationClient.disableBackgroundLocation(true);
}
}
@Override
protected void onStop() {
super.onStop();
boolean isBackground = ((MyApplication)getApplication()).isBackground();
//如果app已经切入到后台,启动后台定位功能
if(isBackground){
if(null != locationClient) {
locationClient.enableBackgroundLocation(2001, buildNotification());
}
}
}
@Override
protected void onPause() {
super.onPause();
}
//初始化控件
private void initView(){
tvResult = (TextView) findViewById(R.id.tv_result);
btLocation
= (Button) findViewById
(R.
id.
bt_location); btEnableBackgroundLocation
= (Button) findViewById
(R.
id.
bt_enableBackground); btDisableBackgroundLocation
= (Button) findViewById
(R.
id.
bt_disableBackground);
btLocation.setOnClickListener(this);
btEnableBackgroundLocation.setOnClickListener(this);
btDisableBackgroundLocation.setOnClickListener(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
destroyLocation();
}
@Override
public void onClick
(View v
) { if (v.getId() == R.id.bt_location) {
if (btLocation.getText().equals(
getResources().getString(R.string.startLocation))) {
btLocation.setText(getResources().getString(
R.string.stopLocation));
tvResult.setText("正在定位...");
startLocation();
} else {
btLocation.setText(getResources().getString(
R.string.startLocation));
stopLocation();
tvResult.setText("定位停止");
}
}
if(v.getId() == R.id.bt_enableBackground){
if(null == locationClient){
try {
locationClient = new AMapLocationClient(this);
//启动后台定位
locationClient.enableBackgroundLocation(2001, buildNotification());
e.printStackTrace();
}
}
}
if(v.getId() == R.id.bt_disableBackground){
if(null == locationClient){
try {
locationClient = new AMapLocationClient(this);
//关闭后台定位
locationClient.disableBackgroundLocation(true);
e.printStackTrace();
}
}
}
}
/**
* 初始化定位
*
* @since 2.8.0
* @author hongming.wang
*
*/
private void initLocation(){
//初始化client
try {
locationClient = new AMapLocationClient(this.getApplicationContext());
locationOption = getDefaultOption();
//设置定位参数
locationClient.setLocationOption(locationOption);
// 设置定位监听
locationClient.setLocationListener(locationListener);
e.printStackTrace();
}
}
/**
* 默认的定位参数
* @since 2.8.0
* @author hongming.wang
*
*/
private AMapLocationClientOption getDefaultOption(){
AMapLocationClientOption mOption = new AMapLocationClientOption();
mOption.setLocationMode(AMapLocationMode.Hight_Accuracy);//可选,设置定位模式,可选的模式有高精度、仅设备、仅网络。默认为高精度模式
mOption.setGpsFirst(false);//可选,设置是否gps优先,只在高精度模式下有效。默认关闭
mOption.setHttpTimeOut(30000);//可选,设置网络请求超时时间。默认为30秒。在仅设备模式下无效
mOption.setInterval(2000);//可选,设置定位间隔。默认为2秒
mOption.setNeedAddress(true);//可选,设置是否返回逆地理地址信息。默认是true
mOption.setOnceLocation(false);//可选,设置是否单次定位。默认是false
mOption.setOnceLocationLatest(false);//可选,设置是否等待wifi刷新,默认为false.如果设置为true,会自动变为单次定位,持续定位时不要使用
AMapLocationClientOption.setLocationProtocol(AMapLocationProtocol.HTTP);//可选, 设置网络请求的协议。可选HTTP或者HTTPS。默认为HTTP
mOption.setSensorEnable(false);//可选,设置是否使用传感器。默认是false
mOption.setWifiScan(true); //可选,设置是否开启wifi扫描。默认为true,如果设置为false会同时停止主动刷新,停止以后完全依赖于系统刷新,定位位置可能存在误差
mOption.setLocationCacheEnable(true); //可选,设置是否使用缓存定位,默认为true
return mOption;
}
/**
* 定位监听
*/
AMapLocationListener locationListener = new AMapLocationListener() {
@Override
public void onLocationChanged(AMapLocation location) {
if (null != location) {
//errCode等于0代表定位成功,其他的为定位失败,具体的可以参照官网定位错误码说明
if(location.getErrorCode() == 0){
sb.append("定位成功" + "\n");
sb.append("定位类型: " + 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(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");
//解析定位结果,
String result
= sb.
toString(); tvResult.setText(result);
} else {
tvResult.setText("定位失败,loc is null");
}
}
};
/**
* 获取GPS状态的字符串
* @param statusCode GPS状态码
* @return
*/
private String getGPSStatusString
(int statusCode
){ 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;
}
/**
* 开始定位
*
* @since 2.8.0
* @author hongming.wang
*
*/
private void startLocation(){
try {
// 设置定位参数
locationClient.setLocationOption(locationOption);
// 启动定位
locationClient.startLocation();
e.printStackTrace();
}
}
/**
* 停止定位
*
* @since 2.8.0
* @author hongming.wang
*
*/
private void stopLocation(){
try {
// 停止定位
locationClient.stopLocation();
e.printStackTrace();
}
}
@Override
public void onBackPressed() {
super.onBackPressed();
}
/**
* 销毁定位
*
* @since 2.8.0
* @author hongming.wang
*
*/
private void destroyLocation(){
if (null != locationClient) {
/**
* 如果AMapLocationClient是在当前Activity实例化的,
* 在Activity的onDestroy中一定要执行AMapLocationClient的onDestroy
*/
locationClient.onDestroy();
locationClient = null;
locationOption = null;
}
}
private void createNotificationChannel(){
}
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.drawable.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;
}
}