package com.behe.treasure.util;
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;
import android.support.annotation.Nullable;
import java.io.IOException;
import java.util.List;
/**
* Created by Jevons Lee on 2017/3/31.
* 定位
*/
public class LocationUtil {
private static OnResponseListener responseListener;
private static LocationUtil locationUtil;
private LocationManager locationManager;
private android.location.Location currentBestLocation;
private NetworkListener networkListener;
private GPSLocationListener gpsListener;
private LocationUtil() {
}
/**
* 定位模式
*/
public enum Mode{
NETWORK, //网络定位
GPS, //GPS定位
AUTO //自动定位,使用网络或GPS定位
}
public static final int NO_PERMISSION = 1; //没权限
public static final int GPS_CLOSE = 2; //GPS是关闭的
public static final int UNAVAILABLE = 3; //不可用
/**
* 请求定位
*/
public static void requestLocation(Context context, Mode mode, OnResponseListener onResponseListener) {
LocationUtil.responseListener = onResponseListener;
if (PermissionUtil.checkPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) ||
PermissionUtil.checkPermission(context,Manifest.permission.ACCESS_COARSE_LOCATION)){
L.i("获取定位权限,开始定位");
//开始定位
locationUtil = new LocationUtil();
locationUtil.startLocation(context,mode);
} else {
L.i("没有定位权限,定位失败");
String provider = mode == Mode.GPS ? LocationManager.GPS_PROVIDER : LocationManager.NETWORK_PROVIDER;
onResponseListener.onErrorResponse(provider, NO_PERMISSION);
}
}
long l;
/**
* 开始定位
*/
private void startLocation(Context context, Mode mode) {
locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
if (PermissionUtil.checkPermission(context,Manifest.permission.ACCESS_FINE_LOCATION) ||
PermissionUtil.checkPermission(context,Manifest.permission.ACCESS_COARSE_LOCATION)){
switch (mode){
case NETWORK:
if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)){
L.i("网络定位");
networkListener = new NetworkListener();
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 500, 0.1f, networkListener);
} else {
responseListener.onErrorResponse(LocationManager.NETWORK_PROVIDER, UNAVAILABLE);
}
break;
case GPS:
if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)){
L.i("GPS定位");
gpsListener = new GPSLocationListener();
l = System.currentTimeMillis();
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000 * 2, 0.1f, gpsListener);
} else {
responseListener.onErrorResponse(LocationManager.GPS_PROVIDER, GPS_CLOSE);
}
break;
case AUTO:
if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)){
L.i("自动定位选择网络定位");
networkListener = new NetworkListener();
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 500, 0.1f, networkListener);
} else if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
L.i("自动定位选择gps");
gpsListener = new GPSLocationListener();
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000 * 2, 0.1f, gpsListener);
} else {
responseListener.onErrorResponse(LocationManager.NETWORK_PROVIDER, UNAVAILABLE);
}
break;
default:
break;
}
} else {
L.e("无权限");
}
}
/**
* 停止定位
*/
public static void stopLocation(){
if (locationUtil == null){
L.e("locationUtil is null");
return;
}
if (locationUtil.networkListener != null){
locationUtil.locationManager.removeUpdates(locationUtil.networkListener);
}
if (locationUtil.gpsListener != null){
locationUtil.locationManager.removeUpdates(locationUtil.gpsListener);
}
L.i("停止定位");
}
private class GPSLocationListener implements LocationListener {
@Override
public void onLocationChanged(Location location) {
L.i("onLocationChanged");
if (location != null) {
L.i("GPS定位成功");
L.i("GPS定位耗时:" + ((System.currentTimeMillis() - l) / 1000) + "秒");
boolean isBetter = isBetterLocation(location, currentBestLocation);
if (isBetter) {
currentBestLocation = location;
}
double latitude = currentBestLocation.getLatitude(); //纬度
double longitude = currentBestLocation.getLongitude(); //经度
responseListener.onSuccessResponse(latitude, longitude);
} else {
L.i("location is null");
}
}
@SuppressLint("MissingPermission")
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
L.i("onStatusChanged:" + status);
if (status == LocationProvider.OUT_OF_SERVICE || status == LocationProvider.TEMPORARILY_UNAVAILABLE) {
L.i("GPS定位失败");
//如果之前没有开启过网络定位,自动切换到网络定位
if (networkListener == null){
//开启网络定位
networkListener = new NetworkListener();
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, networkListener);
}
}
}
@Override
public void onProviderEnabled(String provider) {
L.i("onProviderEnabled");
}
@Override
public void onProviderDisabled(String provider) {
L.i("onProviderDisabled");
}
}
private class NetworkListener implements LocationListener {
@Override
public void onLocationChanged(android.location.Location location) {
if (location != null){
L.i("网络定位成功");
boolean isBetter = isBetterLocation(location,currentBestLocation);
if (isBetter){
currentBestLocation = location;
}
double latitude = currentBestLocation.getLatitude(); //纬度
double longitude = currentBestLocation.getLongitude(); //经度
responseListener.onSuccessResponse(latitude, longitude);
}
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
if (status == LocationProvider.OUT_OF_SERVICE || status == LocationProvider.TEMPORARILY_UNAVAILABLE ) {
L.i("网络定位失败");
responseListener.onErrorResponse(LocationManager.NETWORK_PROVIDER, UNAVAILABLE);
}
}
@Override
public void onProviderEnabled(String provider) {
L.e("可用");
}
@Override
public void onProviderDisabled(String provider) {
L.e("不可用");
}
}
private static final int TWO_MINUTES = 1000 * 60 * 2;
/**
* 比较最新获取到的位置是否比当前最好的位置更好
*
* @param location 最新获得的位置
* @param currentBestLocation 当前获取到的最好的位置
* @return 最新获取的位置比当前最好的位置更好则返回true
*/
private boolean isBetterLocation(Location location, Location currentBestLocation) {
if (currentBestLocation == null) {
// A new locationUtil is always better than no locationUtil
return true;
}
//实时性
// Check whether the new locationUtil 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 locationUtil, use the new locationUtil
// because the user has likely moved
if (isSignificantlyNewer) {
return true;
// If the new locationUtil is more than two minutes older, it must be worse
} else if (isSignificantlyOlder) {
return false;
}
//精确性
// Check whether the new locationUtil fix is more or less accurate
//locationUtil.getAccuracy()值越小越精确
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 locationUtil are from the same provider
boolean isFromSameProvider = isSameProvider(location.getProvider(),
currentBestLocation.getProvider());
// Determine locationUtil 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);
}
public interface OnResponseListener {
/**
* 定位成功
* @param latitude 纬度
* @param longitude 经度
*/
void onSuccessResponse(double latitude, double longitude);
/**
* 定位失败
* @param provider provider
* @param status 失败码
*/
void onErrorResponse(String provider, int status);
}
/**
* 获取地址
* @param context Context
* @param latitude 纬度
* @param longitude 经度
* @return Address
*/
public static @Nullable Address getAddress(Context context, double latitude, double longitude){
Geocoder geocoder = new Geocoder(context);
try {
List
}