//定位权限、网络权限:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.INTERNET" />
//GPS开关和app定位权限手动打开,这里未提供。以下定位代码:
//以下是定位工具类:
/**
* 系统定位工具类
* todo:注意 LocationManager.NETWORK_PROVIDER、 LocationManager.GPS_PROVIDER、 LocationManager.PASSIVE_PROVIDER
* <p>
* GPS_PROVIDER:这个就是手机里有GPS芯片,然后利用该芯片就能利用卫星获得自己的位置信息。可是在室内,GPS定位基本没用,非常难定位的到。
* <p>
* NETWORK_PROVIDER:这个就是利用网络定位,一般是利用手机基站和WIFI节点的地址来大致定位位置,
* 这样的定位方式取决于server,即取决于将基站或WIF节点信息翻译成位置信息的server的能力。
* 因为眼下大部分Android手机没有安装google官方的location manager库。
* 大陆网络也不同意。即没有server来做这个事情,自然该方法基本上没法实现定位。
* <p>
* PASSIVE_PROVIDER:被动定位方式。
* 这个意思也比較明显。就是用现成的,当其它应用使用定位更新了定位信息。
* 系统会保存下来。该应用接收到消息后直接读取就能够了。
* 比方假设系统中已经安装了百度地图,高德地图(室内能够实现精确定位)。
* 你仅仅要使用它们定位过后。再使用这样的方法在你的程序肯定是能够拿到比較精确的定位信息。
* <p>
* 仅仅有NETWORK_PROVIDER这样的模式才是室内定位可靠的方式,
* 因为大陆的特殊网络,且大部分厂商也不会用google的服务,这样的定位方式默认是没法用的。
* 推荐使用其他三方定位sdk
* <p>
* (1)GPS_PROVIDER:通过 GPS 来获取地理位置的经纬度信息;优点:获取地理位置信息精确度高;缺点:只能在户外使用,获取经纬度信息耗时,耗电;
* (2)NETWORK_PROVIDER:通过移动网络的基站或者 Wi-Fi 来获取地理位置;优点:只要有网络,就可以快速定位,室内室外都可;缺点:精确度不高;
* (3)PASSIVE_PROVIDER:被动接收更新地理位置信息,而不用自己请求地理位置信息。
* PASSIVE_PROVIDER 返回的位置是通过其他 providers 产生的,可以查询 getProvider() 方法决定位置更新的由来,需要 ACCESS_FINE_LOCATION 权限,但是如果未启用 GPS,则此 provider 可能只返回粗略位置匹配;
* (4)FUSED_PROVIDER:这个本来已经被废弃了,但是目前在Android12(即android api 31)上又重新使用了起来,但是它依赖GMS,所以国内暂时无法使用。
* 我们通常使用gps和network这两种方式。
* <p>
* 室内实测:GPS_PROVIDER无效、PASSIVE_PROVIDER无效、NETWORK_PROVIDER有效但不是特别准确
*
* @author CJF
*/
public class LocationManagerUtil {
private volatile static LocationManagerUtil locationManagerUtil = null;
private final String TAG = “LocationManagerUtil”;
private final Context context = RecordApp.context;
private final LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
private LocationManagerListener listener;
private final Handler handler = new Handler(Looper.myLooper());
/**
* 超时时间10秒
*/
private final long TIME_OUT = 10000;
/**
* 超时结束监听标记
*/
private boolean endlistenerFlag = false;
public static LocationManagerUtil getInstance() {
if (null == locationManagerUtil) {
synchronized (LocationManagerUtil.class) {
if (null == locationManagerUtil) {
locationManagerUtil = new LocationManagerUtil();
}
}
}
return locationManagerUtil;
}
/**
* 开始定位 单次定位
*
* @param listener
*/
public void startSingleLocation(LocationManagerListener listener) {
this.listener = listener;
endlistenerFlag = false;
if (null == locationManager) {
XLog.d(TAG, “locationManager=null return”);
return;
}
//获取当前网络状态
boolean networkState = CommonMethod.checkNetworkState();
if (!networkState) {
XLog.d(TAG, “无网络 return”);
return;
}
//检查权限
boolean permission = checkPermission();
if (!permission) {
XLog.d(TAG, “定位权限未开启 return”);
return;
}
String provider = LocationManager.NETWORK_PROVIDER;
XLog.d(TAG, “provider:” + provider);
//判断provider是否可用
boolean providerEnabled = locationManager.isProviderEnabled(provider);
if (!providerEnabled) {
XLog.d(TAG, provider + ” 不可用 return”);
return;
}
//获取缓存中的位置信息getLastKnownLocation
Location location = locationManager.getLastKnownLocation(provider);
if (null != location) {
String locationAddr = getLocationAddr(location.getLongitude(), location.getLatitude());
XLog.d(TAG, “缓存中的位置信息location:” + location.toString());
XLog.d(TAG, “缓存中的位置信息locationAddr:” + locationAddr);
//清除定位信息
location.reset();
}
// getWifi();
//
// getTelephonyManager();
// Criteria crite = new Criteria();
// crite.setAccuracy(Criteria.ACCURACY_FINE); //精度
// crite.setPowerRequirement(Criteria.POWER_LOW); //功耗类型选择
// String provider = locationManager.getBestProvider(crite, true);
// String networkProvider = LocationManager.NETWORK_PROVIDER;
// String gpsProvider = LocationManager.GPS_PROVIDER;
// String passiveProvider = LocationManager.PASSIVE_PROVIDER;
//添加地理围栏
// locationManager.addProximityAlert(38.234, 114.234, 5, -1, PendingIntent.getBroadcast(this, 1, new Intent(), 3));
// 可以设置一个区域,当进入或离开这个区域的时候会收到通知,前两个参数指定一个点,第三个参数是半径,第四个参数是超时时间,设置为-1表示不存在超时,最后一个是广播接收器。
// 触发的Intent将使用键KEY_PROXIMITY_ENTERING,如果值为true,则设备进入邻近区域,如果是false,说明设备离开该区域。
//获取一次定位结果requestSingleUpdate 单次定位
locationManager.requestSingleUpdate(provider, locationListener, handler.getLooper());
//超时结束定位
handler.postDelayed(new Runnable() {
@Override
public void run() {
locationManager.removeUpdates(locationListener);
handler.removeCallbacks(this);
if (!endlistenerFlag) {
XLog.d(TAG, “定位超时”);
onFailureListener();
}
}
}, TIME_OUT);
}
/**
* 开始定位 持续定位
*
* @param listener
*/
public void startLocationUpdates(LocationManagerListener listener) {
this.listener = listener;
endlistenerFlag = false;
if (null == locationManager) {
XLog.d(TAG, “locationManager=null return”);
return;
}
//获取当前网络状态
boolean networkState = CommonMethod.checkNetworkState();
if (!networkState) {
XLog.d(TAG, “无网络 return”);
return;
}
//检查权限
boolean permission = checkPermission();
if (!permission) {
XLog.d(TAG, “定位权限未开启 return”);
return;
}
String provider = LocationManager.NETWORK_PROVIDER;
XLog.d(TAG, “provider:” + provider);
//判断provider是否可用
boolean providerEnabled = locationManager.isProviderEnabled(provider);
if (!providerEnabled) {
XLog.d(TAG, provider + ” 不可用 return”);
return;
}
//获取缓存中的位置信息getLastKnownLocation
Location location = locationManager.getLastKnownLocation(provider);
if (null != location) {
String locationAddr = getLocationAddr(location.getLongitude(), location.getLatitude());
XLog.d(TAG, “缓存中的位置信息location:” + location.toString());
XLog.d(TAG, “缓存中的位置信息locationAddr:” + locationAddr);
//清除定位信息
location.reset();
}
// Criteria crite = new Criteria();
// crite.setAccuracy(Criteria.ACCURACY_FINE); //精度
// crite.setPowerRequirement(Criteria.POWER_LOW); //功耗类型选择
// String provider = locationManager.getBestProvider(crite, true);
// String networkProvider = LocationManager.NETWORK_PROVIDER;
// String gpsProvider = LocationManager.GPS_PROVIDER;
// String passiveProvider = LocationManager.PASSIVE_PROVIDER;
//添加地理围栏
// locationManager.addProximityAlert(38.234, 114.234, 5, -1, PendingIntent.getBroadcast(this, 1, new Intent(), 3));
// 可以设置一个区域,当进入或离开这个区域的时候会收到通知,前两个参数指定一个点,第三个参数是半径,第四个参数是超时时间,设置为-1表示不存在超时,最后一个是广播接收器。
// 触发的Intent将使用键KEY_PROXIMITY_ENTERING,如果值为true,则设备进入邻近区域,如果是false,说明设备离开该区域。
//持续定位:
//绑定监听,有4个参数
//参数1,设备:有GPS_PROVIDER、NETWORK_PROVIDER、PASSIVE_PROVIDER 三种
//参数2,位置信息更新周期,单位毫秒
//参数3,位置变化最小距离:当位置距离变化超过此值时,将更新位置信息
//参数4,监听
//备注:参数2和3,如果参数3不为0,则以参数3为准;参数3为0,则通过时间来定时更新;两者为0,则随时刷新
// 1分钟更新一次,或最小位移变化超过1米更新一次;
locationManager.requestLocationUpdates(provider, 60 * 1000, 0, locationListener, handler.getLooper());
//超时结束定位
handler.postDelayed(new Runnable() {
@Override
public void run() {
locationManager.removeUpdates(locationListener);
handler.removeCallbacks(this);
if (!endlistenerFlag) {
XLog.d(TAG, “定位超时”);
onFailureListener();
}
}
}, TIME_OUT);
}
/**
* 定位监听
*/
private final LocationListener locationListener = new LocationListener() {
/**
* 位置信息变化时触发
* 当位置发生改变后就会回调该方法,经纬度相关信息存在Location里面;
*/
@Override
public void onLocationChanged(Location location) {
//赋值为true
endlistenerFlag = true;
if (null != locationManager) {
//解除注册监听 结束定位
locationManager.removeUpdates(this);
}
String time = DateTimeUtility.formatDateTime(location.getTime(), 0);
final double longitude = location.getLongitude();
final double latitude = location.getLatitude();
double altitude = location.getAltitude();
double longitudeGd = location.getLongitude() + 0.0052719116;//经度 系统定位相对于高德定位坐标相差0.0052719116
double latitudeGd = location.getLatitude() + 0.0010604858;//纬度 系统定位相对于高德定位坐标相差0.0010604858
//获取地理位置
String locationAddr = getLocationAddr(longitude, latitude);
//获取高德经纬度地址
String locationAddrGd = getLocationAddr(longitudeGd, latitudeGd);
XLog.d(TAG, “时间:” + time);
XLog.d(TAG, “经度:” + longitude);
XLog.d(TAG, “纬度:” + latitude);
XLog.d(TAG, “海拔:” + altitude);
XLog.d(TAG, “位置:” + locationAddr);
XLog.d(TAG, “高德经度:” + longitudeGd);
XLog.d(TAG, “高德纬度:” + latitudeGd);
XLog.d(TAG, “高德位置:” + locationAddrGd);
if (TextUtils.isEmpty(locationAddr)) {
//失败回调
onFailureListener();
} else {
//成功回调
onSuccessListener(locationManager, location, longitudeGd, latitudeGd, locationAddr);
}
}
/**
* GPS状态变化时触发
* 我们所采用的provider状态改变时会回调
*/
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
switch (status) {
//GPS状态为可见时
case LocationProvider.AVAILABLE:
Log.d(TAG, “当前GPS状态为可见状态 provider可用”);
break;
//GPS状态为服务区外时
case LocationProvider.OUT_OF_SERVICE:
Log.d(TAG, “当前GPS状态为服务区外状态 无服务”);
break;
//GPS状态为暂停服务时
case LocationProvider.TEMPORARILY_UNAVAILABLE:
Log.d(TAG, “当前GPS状态为暂停服务状态 provider不可用”);
break;
default:
break;
}
}
/**
* GPS开启时触发
* 当provider可用时被触发,比如定位模式切换到了使用精确位置时GPSProvider就会回调该方法;
*/
@Override
public void onProviderEnabled(String provider) {
}
/**
* GPS禁用时触发
* 当provider不可用时被触发,比如定位模式切换到了使用使用网络定位时GPSProvider就会回调该方法;
*/
@Override
public void onProviderDisabled(String proider) {
}
};
/**
* 检查权限
*
* @return
*/
private boolean checkPermission() {
if (ActivityCompat.checkSelfPermission(context, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
CommonMethod.showToast(“请开启定位权限”);
return false;
}
return true;
}
/**
* wifi定位 不准确
*/
private void getWifi() {
WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
if (null == wifiManager) {
XLog.d(TAG, “null == wifiManager return”);
return;
}
if (!wifiManager.isWifiEnabled()) {
XLog.d(TAG, “wifi未启用 return”);
return;
}
WifiInfo connectionInfo = wifiManager.getConnectionInfo();
String ssid = connectionInfo.getSSID();
final String bssid = connectionInfo.getBSSID();
int ipAddress = connectionInfo.getIpAddress();
@SuppressLint(“HardwareIds”) String macAddress = connectionInfo.getMacAddress();
String string = connectionInfo.toString();
XLog.d(TAG, “wifi名称:” + ssid);
XLog.d(TAG, “wifi的mac:” + bssid);
XLog.d(TAG, “ipAddress:” + ipAddress);
XLog.d(TAG, “macAddress:” + macAddress);
XLog.d(TAG, “string:” + string);
ThreadPoolExecutorUtil.getInstance().startThread(new Runnable() {
@Override
public void run() {
try {
URL url = new URL(“http://api.cellocation.com:83/wifi/?mac=” + bssid + “&output=json”);
XLog.d(TAG, “url:” + url.toString());
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
//超时时间
connection.setConnectTimeout(3000);
//表示设置本次http请求使用GET方式
connection.setRequestMethod(“GET”);
//返回至为响应编号,如:HTTP_OK表示连接成功。
int responsecode = connection.getResponseCode();
if (responsecode == HttpURLConnection.HTTP_OK) {
InputStream inputStream = connection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
String result = bufferedReader.readLine();
XLog.d(TAG, “result:” + result);
} else {
XLog.d(TAG, “result responsecode:” + responsecode);
}
connection.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
/**
* 手机基站信息定位 不准确
*/
private void getTelephonyManager() {
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
TelephonyManager manager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
if (null == manager) {
return;
}
String networkOperator = manager.getNetworkOperator();
if (TextUtils.isEmpty(networkOperator)) {
return;
}
GsmCellLocation location = (GsmCellLocation) manager.getCellLocation();
final int mcc = Integer.parseInt(networkOperator.substring(0, 3));
final int mnc = Integer.parseInt(networkOperator.substring(3));
final int lac = location.getLac();
final int cid = location.getCid();
XLog.d(TAG, “mcc:” + mcc);
XLog.d(TAG, “mnc:” + mnc);
XLog.d(TAG, “lac:” + lac);
XLog.d(TAG, “cid:” + cid);
ThreadPoolExecutorUtil.getInstance().startThread(new Runnable() {
@Override
public void run() {
try {
URL url = new URL(“http://api.cellocation.com:83/cell/?mcc=” + mcc + “&mnc=” + mnc + “&lac=” + lac + “&ci=” + cid + “&output=json”);
XLog.d(TAG, “url:” + url.toString());
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
//超时时间
connection.setConnectTimeout(3000);
//表示设置本次http请求使用GET方式
connection.setRequestMethod(“GET”);
//返回至为响应编号,如:HTTP_OK表示连接成功。
int responsecode = connection.getResponseCode();
if (responsecode == HttpURLConnection.HTTP_OK) {
InputStream inputStream = connection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
String result = bufferedReader.readLine();
XLog.d(TAG, “result:” + result);
} else {
XLog.d(TAG, “result responsecode:” + responsecode);
}
connection.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
/**
* 获取网络位置
*
* @param longitude
* @param latitude
*/
private void getNetworkAddress(final double longitude, final double latitude) {
ThreadPoolExecutorUtil.getInstance().startThread(new Runnable() {
@Override
public void run() {
try {
URL url = new URL(“http://api.cellocation.com:83/regeo/?lat=” + latitude + “&lon=” + longitude + “&output=json”);
XLog.d(TAG, “url:” + url.toString());
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
//超时时间
connection.setConnectTimeout(3000);
//表示设置本次http请求使用GET方式
connection.setRequestMethod(“GET”);
//返回至为响应编号,如:HTTP_OK表示连接成功。
int responsecode = connection.getResponseCode();
if (responsecode == HttpURLConnection.HTTP_OK) {
InputStream inputStream = connection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
String result = bufferedReader.readLine();
XLog.d(TAG, “result:” + result);
} else {
XLog.d(TAG, “result responsecode:” + responsecode);
}
connection.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
/**
* 获取地理位置
*
* @param longitude
* @param latitude
* @return
*/
private String getLocationAddr(double longitude, double latitude) {
Geocoder geocoder = new Geocoder(context, Locale.getDefault());
boolean flag = Geocoder.isPresent();
if (!flag) {
XLog.d(TAG, “地理编码不可使用”);
return “”;
}
// locality(地址位置) 属性
// 并且有featureName(地址要素)
// 比如国家(countryName)
// 邮编(postalCode)
// 国家编码(countryCode)
// 省份(adminArea)
// 二级省份(subAdminArea)
// 二级城市(subLocality)
// 道路(thoroughfare) 等;
// getFromLocationName():返回描述地理位置信息的集合,maxResults是返回地址的数目,建议使用1-5;
// List<Address> addresses = geocoder.getFromLocationName(“西二旗”, 1);
// if (addresses.size() > 0) {
// //返回当前位置,精度可调
// Address address = addresses.get(0);
// if (address != null) {
// Log.e(“gzq”, “sAddress:” + address.getLatitude());
// Log.e(“gzq”, “sAddress:” + address.getLongitude());
// }
// }
try {
//根据经纬度返回对应的地理位置信息,参数maxResults表示返回地址的数目,建议使用1-5;
List<Address> addresses = geocoder.getFromLocation(latitude, longitude, 1);
if (addresses.size() == 0) {
XLog.d(TAG, “addresses.size() == 0 return”);
return “”;
}
Address address = addresses.get(0);
if (null == address) {
XLog.d(TAG, “null == address return”);
return “”;
}
//获取最大地址行索引
int maxAddressLineIndex = address.getMaxAddressLineIndex();
//循环打印周围位置地址
for (int i = 0; i < maxAddressLineIndex; i++) {
String addressStr = address.getAddressLine(i);
XLog.d(TAG, i + ” addressStr:” + addressStr);
}
StringBuilder addressBuilder = new StringBuilder();
String addressLine = address.getAddressLine(0);
String addressLine1 = address.getAddressLine(1);
if (null != addressLine) {
addressBuilder.append(addressLine);
}
if (null != addressLine1) {
addressBuilder.append(“靠近”).append(addressLine1);
}
XLog.d(TAG, “addressBuilder:” + addressBuilder);
return addressBuilder.toString();
} catch (IOException e) {
e.printStackTrace();
}
return “”;
}
public interface LocationManagerListener {
/**
* 定位成功数据回调
*/
void onSuccessLocationListener(LocationManager manager, Location location, double longitude, double latitude, String locationAddr);
/**
* 定位失败回调
*/
void onFailureLocationListener();
}
private void onSuccessListener(LocationManager manager, Location location, double longitude, double latitude, String locationAddr) {
if (null != listener) {
listener.onSuccessLocationListener(manager, location, longitude, latitude, locationAddr);
}
}
private void onFailureListener() {
if (null != listener) {
listener.onFailureLocationListener();
}
}
}
//调用工具类:
//调用代码 LocationManagerUtil.getInstance().startSingleLocation(new LocationManagerUtil.LocationManagerListener() { @Override public void onSuccessLocationListener(LocationManager manager, Location location, double longitude, double latitude, String locationAddr) { XLog.d(TAG, "定位成功"); //本次定位时间 long time = DateTimeUtil.getInstance().getNowLongTime(); XLog.d(TAG, "本次定位地址address:" + locationAddr); XLog.d(TAG, "本次定位经度longitude:" + longitude); XLog.d(TAG, "本次定位纬度latitude:" + latitude); XLog.d(TAG, "本次定位时间time:" + time + "-" + DateTimeUtil.getInstance().formatDateTime(time, 0)); XLog.d(TAG, "本次location.getTime()定位时间:" + location.getTime()); } @Override public void onFailureLocationListener() { XLog.d(TAG, "定位失败"); } });
//—————————————————————————————完———————————————————————————
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/118288.html