/**
* 位置相關工具類
* <p>
* 需添加的權限:
* {@code <uses-permission android:name="android.permission.INTERNET"/>}
* {@code <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>}
* {@code <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>}
* </p>
*/
public class LocationUtil {
private static LocationManager mLocationManager;
private static MyLocationListener myLocationListener;
private static OnLocationChangeListener mLocationChangedListener;
private static OnProviderStatusListener mProviderStatusListener;
private LocationUtil() {
throw new UnsupportedOperationException("cannot be instantiated");
}
/**
* 判斷 Gps 是否可用
*
* @return {@code true}: 是<br>{@code false}: 否
*/
public static boolean isGpsEnabled(Context context) {
LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
return lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
}
/**
* 判斷定位是否可用
*
* @return {@code true}: 是<br>{@code false}: 否
*/
public static boolean isLocationEnabled(Context context) {
LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
return lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER) || lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
}
/**
* 設置 Provider 狀態監聽器
* <p>請在{@link #register(Context context, long minTime, long minDistance, OnLocationChangeListener listener)}前調用</p>
*
* @param listener {@link OnProviderStatusListener}
*/
public static void setProviderStatusListener(OnProviderStatusListener listener) {
mProviderStatusListener = listener;
}
/**
* 註冊
* <p>使用完記得調用{@link #unregister()}</p>
* <p>需添加權限 {@code <uses-permission android:name="android.permission.INTERNET"/>}</p>
* <p>需添加權限 {@code <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>}</p>
* <p>需添加權限 {@code <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>}</p>
* <p>如果{@code minDistance}爲0,則通過{@code minTime}來定時更新;</p>
* <p>{@code minDistance}不爲0,則以{@code minDistance}爲準;</p>
* <p>兩者都爲0,則隨時刷新。</p>
*
* @param minTime 位置信息更新週期(單位:毫秒)
* @param minDistance 位置變化最小距離:當位置距離變化超過此值時,將更新位置信息(單位:米)
* @param listener 位置刷新的回調接口
* @return {@code true}: 初始化成功<br>{@code false}: 初始化失敗
*/
public static boolean register(Context context, long minTime, long minDistance, OnLocationChangeListener listener) {
if (listener == null) return false;
mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
mLocationChangedListener = listener;
if (!isLocationEnabled(context)) {
ToastUtil.show("無法定位,請打開定位服務");
return false;
}
String provider = mLocationManager.getBestProvider(getCriteria(), true);
Location location = mLocationManager.getLastKnownLocation(provider);
if (location != null) listener.getLastKnownLocation(location);
if (myLocationListener == null) myLocationListener = new MyLocationListener();
// 定位監聽
// 參數 1,設備:有 GPS_PROVIDER 和 NETWORK_PROVIDER 兩種
// 參數 2,位置信息更新週期,單位毫秒
// 參數 3,位置變化最小距離:當位置距離變化超過此值時,將更新位置信息
// 參數 4,監聽
// 備註:參數 2 和 3,如果參數 3 不爲 0,則以參數 3 爲準;參數 3 爲 0,則通過時間來定時更新;兩者爲 0,則隨時刷新
// 1 秒更新一次,或最小位移變化超過1米更新一次;
// 注意:此處更新準確度非常低,推薦在 service 裏面啓動一個 Thread,在 run 中 sleep(10000); 然後執行 handler.sendMessage(), 更新位置
mLocationManager.requestLocationUpdates(provider, minTime, minDistance, myLocationListener);
return true;
}
/**
* 註銷
*/
public static void unregister() {
if (mLocationManager != null) {
if (myLocationListener != null) {
mLocationManager.removeUpdates(myLocationListener);
myLocationListener = null;
}
mLocationManager = null;
}
if (mLocationChangedListener != null) mLocationChangedListener = null;
if (mProviderStatusListener != null) mProviderStatusListener = null;
}
/**
* 設置定位參數
*/
private static Criteria getCriteria() {
Criteria criteria = new Criteria();
// 設置定位精確度 Criteria.ACCURACY_COARSE 比較粗略,Criteria.ACCURACY_FINE 則比較精細
criteria.setAccuracy(Criteria.ACCURACY_FINE);
// 設置是否要求速度
criteria.setSpeedRequired(true);
// 設置是否允許運營商收費
criteria.setCostAllowed(false);
// 設置是否需要方位信息
criteria.setBearingRequired(true);
// 設置是否需要海拔信息
criteria.setAltitudeRequired(true);
// 設置對電源的需求
criteria.setPowerRequirement(Criteria.POWER_LOW);
return criteria;
}
/**
* 根據經緯度獲取地理位置
*
* @param latitude 緯度
* @param longitude 經度
* @return {@link Address}
*/
public static Address getAddress(double latitude, double longitude) {
Geocoder geocoder = new Geocoder(SUtils.getApp(), Locale.getDefault());
try {
List<Address> addresses = geocoder.getFromLocation(latitude, longitude, 1);
if (addresses.size() > 0) {
return addresses.get(0);
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* 根據經緯度獲取所在國家
*
* @param latitude 緯度
* @param longitude 經度
* @return 所在國家
*/
public static String getCountry(double latitude, double longitude) {
Address address = getAddress(latitude, longitude);
return address == null ? "unknown" : address.getCountryName();
}
/**
* 根據經緯度獲取所在地
*
* @param latitude 緯度
* @param longitude 經度
* @return 所在地
*/
public static String getLocality(double latitude, double longitude) {
Address address = getAddress(latitude, longitude);
return address == null ? "unknown" : address.getLocality();
}
/**
* 根據經緯度獲取所在街道
*
* @param latitude 緯度
* @param longitude 經度
* @return 所在街道
*/
public static String getStreet(double latitude, double longitude) {
Address address = getAddress(latitude, longitude);
return address == null ? "unknown" : address.getAddressLine(0);
}
private static class MyLocationListener implements LocationListener {
/**
* 當座標改變時觸發此函數,如果 Provider 傳進相同的座標,它就不會被觸發
*
* @param location 座標
*/
@Override
public void onLocationChanged(Location location) {
if (mLocationChangedListener != null) {
mLocationChangedListener.onLocationChanged(location);
}
}
/**
* Provider 在可用、暫時不可用和無服務三個狀態直接切換時觸發此函數
*
* @param provider 提供者
* @param status 狀態
* @param extras Provider 可選包
*/
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
if (mLocationChangedListener != null) {
mLocationChangedListener.onStatusChanged(provider, status, extras);
}
switch (status) {
case LocationProvider.AVAILABLE:
LogUtil.d("LocationListener onStatusChanged ========> ", "當前GPS狀態爲可見狀態");
break;
case LocationProvider.OUT_OF_SERVICE:
LogUtil.d("LocationListener onStatusChanged ========> ", "當前GPS狀態爲服務區外狀態");
break;
case LocationProvider.TEMPORARILY_UNAVAILABLE:
LogUtil.d("LocationListener onStatusChanged ========> ", "當前GPS狀態爲暫停服務狀態");
break;
}
}
/**
* Provider 被 enable 時觸發此函數,比如GPS被打開
*/
@Override
public void onProviderEnabled(String provider) {
if (mProviderStatusListener != null) {
mProviderStatusListener.providerEnabled(provider);
}
}
/**
* Provider 被 disable 時觸發此函數,比如GPS被關閉
*/
@Override
public void onProviderDisabled(String provider) {
if (mProviderStatusListener != null) {
mProviderStatusListener.providerDisabled(provider);
}
}
}
public interface OnLocationChangeListener {
/**
* 獲取最後一次保留的座標
*
* @param location 座標
*/
void getLastKnownLocation(Location location);
/**
* 當座標改變時觸發此函數,如果 Provider 傳進相同的座標,它就不會被觸發
*
* @param location 座標
*/
void onLocationChanged(Location location);
/**
* Provider 在可用、暫時不可用和無服務三個狀態直接切換時觸發此函數
*
* @param provider 提供者
* @param status 狀態
* @param extras Provider 可選包
*/
void onStatusChanged(String provider, int status, Bundle extras);// 位置狀態發生改變
}
/**
* Provider 狀態監聽器
*/
public interface OnProviderStatusListener {
/**
* Provider 被 enable 時觸發此函數,比如GPS被打開
*/
void providerEnabled(String provider);
/**
* Provider 被 disable 時觸發此函數,比如GPS被關閉
*/
void providerDisabled(String provider);
}
}
位置相關工具類
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.