• 定位-----LocationUtils

 

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 list = geocoder.getFromLocation(latitude,longitude,3);
            if (list.size() > 0){
                Address address = list.get(0);
                L.i("省:" + address.getAdminArea());
                L.i("市:" + address.getLocality());
                L.i("县/区:" + address.getSubLocality());
                return address;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

}
 

更多相关文章

  1. libgdx实例分析小记(一)
  2. 百度新版定位无法进入MyLocationListenner的解决办法
  3. Android自定义ViewGroup神器-ViewDragHelper
  4. Android(安卓)AlertDialog 绝对位置计算
  5. android动态控制组件的位置、大小和新的动画
  6. android 精确定位
  7. Android(安卓)Debug keystore系统位置
  8. Android开发指南(43) —— Location and Maps
  9. Android断点续传学习

随机推荐

  1. Android(安卓)TransactionTooLargeExcept
  2. 【总结】layout_below与layout_alignBott
  3. 开发Android第一步,安装SDK 1.6, 模拟器及
  4. android 录音机&示波器
  5. Android(安卓)App 增量更新实例(Smart App
  6. Android(安卓)兼容获取Mac地址与手机信息
  7. 修改AndroidStudio默认的compileSdkVersi
  8. 数据库表的查询操作实践演练(实验三)
  9. 解决“Connection to https://dl-ssl.goo
  10. 通過android selector改变界面状态