浅析Android地理定位(GPS)
淺析Android地理定位(GPS)
- 定位權限
- 介紹一下定位相關的一些API
- LocationManager
- 位置提供器
- requestLocationUpdates
- Geocoder
- Criteria 和 Address
- 實現代碼
- 實現效果
- 補充
關于手機的定位服務,相信大家都不陌生,如今國內安卓手機上大面積使用了北斗+GPS的定位方式。通過與衛星交互來獲取設備當前的經緯度,準確度較高。
GPS是英文Global Positioning System(全球定位系統)的簡稱。Android中定位的方式一般有這四種:GPS定位,WIFI定準,基站定位,AGPS定位(基站+GPS);
本篇主要介紹谷歌自帶的LocationManager 獲取手機定位的方法,以及通過谷歌服務Geocoder 來進行反地理編碼。但是由于Geocoder 進行反地理編碼需要一個未包含在android核心框架之中的后端服務,如果平臺中沒有這個后端服務,Geocoder查詢方法將返回空列表。不幸的是,國內很多手機廠商都沒有內置這種服務(例如百度、高德服務),所以Geocoder也就不能使用了。所以為了穩定,只能選擇國內的反地理編碼web服務了。
定位權限
1.Manifest文件添加權限
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>2.添加依賴
mplementation "com.google.code.gson:gson:2.8.5"implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.1"implementation "org.jetbrains.kotlinx:kotlinximplementation 'com.afollestad:assent:2.3.1' ##介紹一下定位相關的一些API
1)LocationManager
LocationManager lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);獲得了LocationManager對象后,我們可以調用下面這些常用的方法:
addGpsStatusListener(GpsStatus.Listener listener):添加一個GPS狀態監聽器
addProximityAlert(double latitude, double longitude, float radius, long expiration, PendingIntent intent):
添加一個臨界警告
getAllProviders():獲取所有的LocationProvider列表
getBestProvider(Criteria criteria, boolean enabledOnly):根據指定條件返回最優LocationProvider
getGpsStatus(GpsStatus status):獲取GPS狀態
getLastKnownLocation(String provider):根據LocationProvider獲得最近一次已知的Location
getProvider(String name):根據名稱來獲得LocationProvider
getProviders(boolean enabledOnly):獲取所有可用的LocationProvider
getProviders(Criteria criteria, boolean enabledOnly):根據指定條件獲取滿足條件的所有LocationProvider
isProviderEnabled(String provider):判斷指定名稱的LocationProvider是否可用
removeGpsStatusListener(GpsStatus.Listener listener):刪除GPS狀態監聽器
removeProximityAlert(PendingIntent intent):刪除一個臨近警告
requestLocationUpdates(long minTime, float minDistance, Criteria criteria, PendingIntent intent):
通過制定的LocationProvider周期性地獲取定位信息,并通過Intent啟動相應的組件
requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener):
通過制定的LocationProvider周期性地獲取定位信息,并觸發listener所對應的觸發器
2)LocationProvider(定位提供者)
這比是GPS定位組件的抽象表示,調用下述方法可以獲取該定位組件的相關信息!
常用的方法如下:
getAccuracy():返回LocationProvider精度
getName():返回LocationProvider名稱
getPowerRequirement():獲取LocationProvider的電源需求
hasMonetaryCost():返回該LocationProvider是收費還是免費的
**meetsCriteria(**Criteria criteria):判斷LocationProvider是否滿足Criteria條件
requiresCell():判斷LocationProvider是否需要訪問網絡基站
requiresNetwork():判斷LocationProvider是否需要訪問網絡數據
requiresSatellite():判斷LocationProvider是否需要訪問基于衛星的定位系統
supportsAltitude():判斷LocationProvider是否支持高度信息
supportsBearing():判斷LocationProvider是否支持方向信息
supportsSpeed():判斷是LocationProvider否支持速度信息
3)Location(位置信息)
位置信息的抽象類,我們可以調用下述方法獲取相關的定位信息!
常用方法如下:
float getAccuracy():獲得定位信息的精度
double getAltitude():獲得定位信息的高度
float getBearing():獲得定位信息的方向
double getLatitude():獲得定位信息的緯度
double getLongitude():獲得定位信息的精度
String getProvider():獲得提供該定位信息的LocationProvider
float getSpeed():獲得定位信息的速度
boolean hasAccuracy():判斷該定位信息是否含有精度信息
4)Criteria(過濾條件)
獲取LocationProvider時,可以設置過濾條件,就是通過這個類來設置相關條件的
常用方法如下:
setAccuracy(int accuracy):設置對的精度要求
setAltitudeRequired(boolean altitudeRequired):設置是否要求LocationProvider能提供高度的信息
setBearingRequired(boolean bearingRequired):設置是否要LocationProvider求能提供方向信息
setCostAllowed(boolean costAllowed):設置是否要求LocationProvider能提供方向信息
setPowerRequirement(int level):設置要求LocationProvider的耗電量
setSpeedRequired(boolean speedRequired):設置是否要求LocationProvider能提供速度信息
LocationManager
LocationManager 的api使用起來很簡單,難點在于不同android機型,不同系統可能存在著很多未知的坑。最大的坑就是有的手機系統底層的定位服務是直接連接的google服務器,手機廠商沒有將定位的服務器重定向為國內的定位服務商,致使我們通過LocationManager根本拿不到定位信息。
位置提供器
LocationManager 提供的位置提供器,默認為PASSIVE_PROVIDER,這是一個特殊的位置提供器,用來被動的接收位置信息,這個位置信息是由其他的服務提供的位置信息,而不是自己主動請求的,相當于共享了一個位置服務信息,不常用。使用比較多的還是GPS和網絡定位,這兩種定位方式各有特點,GPS定位精度高,但是比較耗電,而且室內很難獲取到GPS經緯度。而網絡定位雖然精度稍低,但耗電量比較小,而且在室內室外效果都很不錯。
lm = (LocationManager) mContext.getApplicationContext().getSystemService(Context.LOCATION_SERVICE);// 檢查是否有相關定位權限if(!Helper.checkPermission(mContext.getApplicationContext())){mListener.onFail("location no permission");return;}// 如果不傳配置類,則按默認配置if(mSiLoOption == null)mSiLoOption = new SiLoOption();mProvider = mSiLoOption.isGpsFirst ? Helper.getGPSProvider(lm) : Helper.getNetWorkProvider(lm);if(mProvider == null)mListener.onFail("location provider no exist");elsegetLocation(mProvider);獲取gps位置提供器的代碼片段:
/*** gps 提供器* @param locationManager* @return*/public static String getGPSProvider(LocationManager locationManager) {List<String> prodiverlist = locationManager.getProviders(true);// gps定位if(prodiverlist.contains(LocationManager.GPS_PROVIDER))return LocationManager.GPS_PROVIDER;return null;}requestLocationUpdates
獲取位置提供器成功后,就可以通過requestLocationUpdates 方法來請求經緯度了
下面是邏輯代碼片段:
Geocoder
Geocoder 的api很簡單,如果國內手機在自定義系統時能夠使用geooder的后端服務或已內置百度高德服務,那么使用Geocoder 反地理編碼功能會很方便。所以在使用前,我們可以先檢查服務是否可用,再決定使用哪家的web 反地理編碼服務。
if(!Geocoder.isPresent()){if(mListener != null)mListener.onFail(ResponseConstant.GOOGLE_API_OUT_OF_CONDITON, "geocoder is out of condition");return; }Criteria 和 Address
根據Criteria 指定的條件,設備可以自動選擇那種provider、是否要求海波、是否要求方向;設置電池消耗要求、設置方向的精準度等一系列的篩選條件。但這里需要注意的是,network一般根據wifi節點mac地址和基站地理位置來進行定位的,在精度上來說是比較差的,雖然有的手機返回的經緯度的精度級別非常高,但是其實際偏差卻是非常大的,所以我們不能完全信賴net定位點。
Address 是反編碼成功后的實體bean,并沒有什么特殊的地方,只是存儲了谷歌服務返回來的字段值罷了。例如我們平時常用的國家、城市、城市編碼、區、街道、POi名稱等信息。
實現代碼
獲取經緯度代碼:LocationManager獲取經緯度
import android.content.Context; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.location.LocationProvider; import android.os.Build; import android.os.Bundle;import androidx.annotation.Nullable;import com.mjzuo.location.bean.Latlng; import com.mjzuo.location.helper.ConverHelper; import com.mjzuo.location.helper.Helper; import com.mjzuo.location.util.LogUtil;ic class GoogleGeocoding implements IGeocoding {/** 當前系統定位manager*/private LocationManager lm;/** 位置提供器*/private String mProvider;/** 定位change監聽*/private MyLocationListener mChangeListener;/** 響應用戶的回調*/private ISiLoResponseListener mListener;/** 服務的參數配置類*/private SiLoOption mSiLoOption;/** 當前經緯度*/private Latlng latlng;/** 計數器*/private int mCounter;/** gps信號消失,嘗試network定位*/private static final int GPS_TIME_SPACE = 6;/** 嘗試network之后,同樣獲取不到定位,則錯誤回調,時間間隔 = NET_TIME_SPACE - GPS_TIME_SPACE*/private static final int NET_TIME_SPACE = 12;private Context mContext;public GoogleGeocoding(Context context) {this.mContext = context;this.mChangeListener = new MyLocationListener();}public void setSimpleLocationOption(@Nullable SiLoOption siLoOption) {this.mSiLoOption = siLoOption;}@Overridepublic void start(@Nullable ISiLoResponseListener listener) {if(listener != null)this.mListener = listener;if(mListener == null)return;lm = (LocationManager) mContext.getApplicationContext().getSystemService(Context.LOCATION_SERVICE);// 檢查是否有相關定位權限if(!Helper.checkPermission(mContext.getApplicationContext())){mListener.onFail("location no permission");return;}// 如果不傳配置類,則按默認配置if(mSiLoOption == null)mSiLoOption = new SiLoOption();mProvider = mSiLoOption.isGpsFirst ? Helper.getGPSProvider(lm) : Helper.getNetWorkProvider(lm);if(mProvider == null)mListener.onFail("location provider no exist");elsegetLocation(mProvider);}@Overridepublic void reStart() {start(null);}@Overridepublic void stop() {mProvider = null;if(lm != null)lm.removeUpdates(mChangeListener);lm = null;mListener = null;mChangeListener = null;}@SuppressWarnings("all")private String getLocation(String provider) {if(provider == null)return null;lm.requestLocationUpdates(provider, mSiLoOption.time, mSiLoOption.distance, mChangeListener);return provider;}class MyLocationListener implements LocationListener {@Overridepublic void onLocationChanged(Location location) {if(mProvider == null)return;latlng = location != null ? ConverHelper.loConverToLatlng(location) : latlng;mListener.onSuccess(latlng);if(mSiLoOption.isGpsFirst){if(location != null){if(mProvider == LocationManager.GPS_PROVIDER)mCounter = 0;else{mCounter += mSiLoOption.time/1000;if(mCounter > NET_TIME_SPACE){mProvider = getLocation(Helper.getGPSProvider(lm));mCounter = 0;}}}else{// gps無信號時,嘗試network獲取mCounter += mSiLoOption.time/1000;if(mCounter >= GPS_TIME_SPACE && mCounter < NET_TIME_SPACE){mProvider = getLocation(Helper.getNetWorkProvider(lm));}else if(mCounter > NET_TIME_SPACE){// 只要最后一個net點失敗,就拋出回調;前兩個點,由于開始,可能為空,不做強制判斷處理mListener.onFail("location latlng = null , provider = "+ mProvider);}}}else{// 當network獲取不到定位if(location == null)mListener.onFail("location latlng = null , provider = "+ mProvider);}}@Overridepublic void onStatusChanged(String s, int state, Bundle bundle) {if(mListener == null)return;if(Build.VERSION.SDK_INT > 28){LogUtil.e("after api 29 always AVAILABLE");}else{switch (state){case LocationProvider.OUT_OF_SERVICE:case LocationProvider.TEMPORARILY_UNAVAILABLE:LogUtil.e("current provider out of condition");break;}}}@Overridepublic void onProviderEnabled(String s) {}@Overridepublic void onProviderDisabled(String s) {}}public static class SiLoOption {/*** gps 優先否*/private boolean isGpsFirst = false;/*** 監聽定位變化最短時間間隔,默認time s*/private int time = 2000;/*** 監聽變化的最小距離*/private int distance = 10;public boolean isGpsFirst() {return isGpsFirst;}public SiLoOption setGpsFirst(boolean gpsFirst) {isGpsFirst = gpsFirst;return this;}public int getTime() {return time;}public SiLoOption setTime(int time) {this.time = time;return this;}public int getRequestTepe() {return distance;}public SiLoOption setRequestTepe(int requestTepe) {this.distance = requestTepe;return this;}} }獲取經緯度代碼:定位類
import android.content.Context;import androidx.annotation.Nullable;import com.mjzuo.location.constant.Constant; import com.mjzuo.location.helper.GeReFactory; import com.mjzuo.location.location.GoogleGeocoding; import com.mjzuo.location.location.IGeocoding; import com.mjzuo.location.util.LogUtil;ic class GeocodingManager {private IGeocoding mGeocoding;private IGeocoding.ISiLoResponseListener mListener;private Context mContext;public GeocodingManager(Context context) {mContext = context;mGeocoding = GeReFactory.getGeocodingType(mContext, Constant.LM_API);}public GeocodingManager(Context context, @Nullable GeoOption option) {mContext = context;mGeocoding = GeReFactory.getGeocodingType(mContext, option.getGeoType());if(mGeocoding instanceof GoogleGeocoding)((GoogleGeocoding) mGeocoding).setSimpleLocationOption(option.getOption());}public void start(IGeocoding.ISiLoResponseListener listener) {if(listener != null)mListener = listener;if(mListener == null){LogUtil.e("simple location response listener null");}mGeocoding.start(mListener);}public void reStart(){start(null);}public void stop(){mGeocoding = null;mListener = null;}public static class GeoOption {/*** 定位的類型** LocationManager或基站定位*/private int GeoType = Constant.LM_API;/*** 這是locationManager的配置類*/private GoogleGeocoding.SiLoOption option;public int getGeoType() {return GeoType;}public GeoOption setGeoType(int geoType) {GeoType = geoType;return this;}public GoogleGeocoding.SiLoOption getOption() {return option;}public GeoOption setOption(GoogleGeocoding.SiLoOption option) {this.option = option;return this;}}}百度API接口:
import android.content.Context; import android.os.AsyncTask;import androidx.annotation.Nullable;import com.mjzuo.location.ReverseGeocodingManager; import com.mjzuo.location.bean.Latlng; import com.mjzuo.location.constant.UrlConstant; import com.mjzuo.location.helper.Helper; import com.mjzuo.location.net.NetUtil; import com.mjzuo.location.util.CommonUtil; import com.mjzuo.location.util.LogUtil;import org.json.JSONObject;import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.LinkedHashMap; import java.util.Map;public class BaiduGeRe implements IReGe {private String ak = "KHVTQZiP2UGuv7SkNbqYPKu4co7kbkS4";private String sk = "cTqIacm4uvDnQWpWWCZGElhbIx4Nxv3q";private String host = "/reverse_geocoding/v3/";private LinkedHashMap<String, String> paramsMap;// 默認使用sn校驗方式private boolean isSn = true;private MyAsyncTask task;private IReGeListener mListener;@Overridepublic void init(@Nullable Context context) {paramsMap = new LinkedHashMap<>();paramsMap.put("ak", ak);paramsMap.put("coordtype", "wgs84ll");}@Overridepublic void setOptions(@Nullable ReverseGeocodingManager.ReGeOption options) {this.isSn = options.isSn();if(options.getKey() != null && !options.getKey().isEmpty())this.ak = options.getKey();if(options.getSk() != null && !options.getSk().isEmpty())this.sk = options.getSk();}@Overridepublic void reGeToAddress(Latlng latlng) {paramsMap.put("location", latlng.getLatitude() + "," + latlng.getLongitude());paramsMap.put("output", "json");if(isSn) {String paramsStr;try {paramsStr = toQueryString(paramsMap);}catch (UnsupportedEncodingException e){LogUtil.e("error:"+e.getMessage());return;}String wholeStr = new String(host + "?" + paramsStr + sk);try {wholeStr = URLEncoder.encode(wholeStr, "UTF-8");}catch (Exception e){LogUtil.e("error:"+e.getMessage());return;}String sn = CommonUtil.MD5(wholeStr);paramsMap.put("sn", sn);}task = new MyAsyncTask(Helper.toAppendUrl(paramsMap, UrlConstant.BAIDU_URL, host));task.execute();}@Overridepublic void stop() {if(paramsMap != null)paramsMap.clear();paramsMap = null;task = null;}@Overridepublic void addReGeListener(IReGeListener listener) {mListener = listener;}class MyAsyncTask extends AsyncTask<Void, Void, String>{String mUrl;public MyAsyncTask(String url) {mUrl = url;}@Overrideprotected String doInBackground(Void... voids) {return NetUtil.doHttpGet(mUrl);}@Overrideprotected void onPostExecute(String json) {super.onPostExecute(json);fromJson(json);task = null;}}/*** 對Map內所有value作utf8編碼,拼接返回結果* @param data* @return* @throws UnsupportedEncodingException*/private String toQueryString(Map<?, ?> data)throws UnsupportedEncodingException {StringBuffer queryString = new StringBuffer();for (Map.Entry<?, ?> pair : data.entrySet()) {queryString.append(pair.getKey() + "=");queryString.append(URLEncoder.encode((String) pair.getValue(),"UTF-8") + "&");}if (queryString.length() > 0) {queryString.deleteCharAt(queryString.length() - 1);}return queryString.toString();}/*** 解析json*/private void fromJson(String json) {LogUtil.e("json:"+json);if(json == null || json.isEmpty())return;if(mListener == null)return;JSONObject jsonObject = null;try {jsonObject = new JSONObject(json);}catch (Exception e){LogUtil.e("error:" + e.getMessage());return;}if(jsonObject.has("status")){Integer state;try {state = (Integer) jsonObject.get("status");// 0請求成功標志碼if(state != 0){if(jsonObject.has("message"))mListener.onFail(state, jsonObject.getString("message"));return;}if(jsonObject.has("result")){JSONObject obj;JSONObject objAddress;try{obj = jsonObject.getJSONObject("result");objAddress = obj.getJSONObject("addressComponent");Latlng latlng = new Latlng();latlng.setCountry(objAddress.getString("country"));latlng.setCountryCode(objAddress.getString("country_code"));latlng.setCity(objAddress.getString("city"));latlng.setSublocality(objAddress.getString("district"));latlng.setCityCode(obj.getInt("cityCode")+"");latlng.setAddress(objAddress.getString("street"));latlng.setName(obj.getString("business"));mListener.onSuccess(state, latlng);}catch (Exception e){LogUtil.e("error:"+e.getMessage());return;}}}catch (Exception e){LogUtil.e("error:" + e.getMessage());return;}}} }反向地理編碼:
/** 百度api返地理編碼*/ public static final String BAIDU_URL = "https://api.map.baidu.com";/**特定經緯度的反向地理編碼:*/ import android.content.Context;import androidx.annotation.Nullable;import com.mjzuo.location.bean.Latlng; import com.mjzuo.location.constant.Constant; import com.mjzuo.location.helper.GeReFactory; import com.mjzuo.location.regelocation.IReGe; import com.mjzuo.location.util.LogUtil;lic class ReverseGeocodingManager {IReGe mGeRe;Context mContext;public ReverseGeocodingManager(Context context) {mContext = context;mGeRe = GeReFactory.getReGeByType(Constant.GOOGLE_API);mGeRe.init(mContext);}public ReverseGeocodingManager(Context context, @Nullable ReGeOption option) {mContext = context;mGeRe = GeReFactory.getReGeByType(option.getReGeType());mGeRe.setOptions(option);mGeRe.init(mContext);}public void reGeToAddress(@Nullable Latlng latlng) {mGeRe.reGeToAddress(latlng);}public void stop() {mGeRe.stop();}public void addReGeListener(@Nullable IReGe.IReGeListener listener) {mGeRe.addReGeListener(listener);}public static class ReGeOption {/*** api類型,默認谷歌服務** 注意:個別機型內部移除了谷歌服務,如果不能請求,請切換別的api接口*/private int reGeType = Constant.GOOGLE_API;/*** 是否sn校驗,默認簽名校驗方式,而非白名單方式*/private boolean isSn = true;/*** key*/private String key = "";/*** sk*/private String sk = "";/*** 是否打開log*/private boolean islog = true;public int getReGeType() {return reGeType;}public ReGeOption setReGeType(int reGeType) {this.reGeType = reGeType;return this;}public boolean isSn() {return isSn;}public ReGeOption setSn(boolean sn) {isSn = sn;return this;}public boolean isIslog() {return LogUtil.DEBUG;}public ReGeOption setIslog(boolean islog) {LogUtil.DEBUG = islog;return this;}public String getKey() {return key;}public String getSk() {return sk;}public ReGeOption setKey(String key) {this.key = key;return this;}public ReGeOption setSk(String sk) {this.sk = sk;return this;}} }LocationTaskActivity:
import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity;import android.Manifest; import android.os.Bundle; import android.util.Log; import android.widget.TextView;import com.mjzuo.location.GeocodingManager; import com.mjzuo.location.bean.Latlng; import com.mjzuo.location.constant.Constant; import com.mjzuo.location.location.GoogleGeocoding; import com.mjzuo.location.location.IGeocoding; import com.mjzuo.location.regelocation.IReGe; import com.mjzuo.location.ReverseGeocodingManager;import java.util.List;import pub.devrel.easypermissions.EasyPermissions;public class LocationTaskActivity extends AppCompatActivity implements EasyPermissions.PermissionCallbacks{private static final String LOG_TAG = "tag_sl";/** 所要申請的權限*/String[] perms = {Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.INTERNET,Manifest.permission.READ_PHONE_STATE};/** 定位獲取經緯度,包括LocationManager、基站地位*/GeocodingManager siLoManager;/** 反地理編碼的manager,包括google反地理、百度反地理*/ReverseGeocodingManager reGeManager;TextView tvSimpleLo;TextView tvSimpleAd;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.simple_location_activity);tvSimpleLo = findViewById(R.id.tv_simple_location_txt);tvSimpleAd = findViewById(R.id.tv_simple_address_txt);if (!EasyPermissions.hasPermissions(this, perms)) {EasyPermissions.requestPermissions(this, "必要的權限", 0, perms);}ReverseGeocodingManager.ReGeOption reGeOption = new ReverseGeocodingManager.ReGeOption().setReGeType(Constant.BAIDU_API)// 百度api返地理編碼.setSn(true)// sn 簽名校驗方式.setIslog(true);// 打印logreGeManager = new ReverseGeocodingManager(this, reGeOption);reGeManager.addReGeListener(new IReGe.IReGeListener() {@Overridepublic void onSuccess(int state, Latlng latlng) {Log.e(LOG_TAG,"reGeManager onSuccess:" + latlng);tvSimpleAd.setText("country:"+ latlng.getCountry()+ "\n,city:" + latlng.getCity()+ "\n,sublocality:" + latlng.getSublocality()+ "\n,address:" + latlng.getAddress()+ "\n,name:" + latlng.getName());}@Overridepublic void onFail(int errorCode, String error) {Log.e(LOG_TAG,"error:" + error);tvSimpleAd.setText("errorCode:"+errorCode+", error:" + error);}});GeocodingManager.GeoOption option = new GeocodingManager.GeoOption().setGeoType(Constant.LM_API) // 使用openCellid服務器的基站地位.setOption(new GoogleGeocoding.SiLoOption().setGpsFirst(true));// locationManager定位方式時,gps優先siLoManager = new GeocodingManager(this, option);siLoManager.start(new IGeocoding.ISiLoResponseListener() {@Overridepublic void onSuccess(Latlng latlng) {Log.e(LOG_TAG,"siLoManager onSuccess:" + latlng);tvSimpleLo.setText("latlng:" + latlng.getLatitude()+ "\n,long:" + latlng.getLongitude()+ "\n,provider:" + latlng.getProvider());reGeManager.reGeToAddress(latlng);}@Overridepublic void onFail(String msg) {Log.e(LOG_TAG,"error:" + msg);tvSimpleAd.setText("error:" + msg);}});}@Overrideprotected void onDestroy() {super.onDestroy();if(siLoManager != null)siLoManager.stop();if(reGeManager != null){reGeManager.stop();}}@Overridepublic void onPermissionsGranted(int requestCode, @NonNull List<String> perms) {if(requestCode == 0 && siLoManager != null)siLoManager.reStart();}@Overridepublic void onPermissionsDenied(int requestCode, @NonNull List<String> perms) {}@Overridepublic void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);// Forward results to EasyPermissionsEasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);} }實現效果
請求用戶權限
不開啟GPS定位下的效果
開啟定位服務
上地圖查一下,結果十分的正確
補充
百度API使用方法官網鏈接
檢測到GPS未打開時間,讓用戶自行打開
——————————————————————————————
參考鏈接:https://www.runoob.com/w3cnote/android-tutorial-gps.html.
參考鏈接:https://blog.csdn.net/MingJieZuo/article/details/79755357.
總結
以上是生活随笔為你收集整理的浅析Android地理定位(GPS)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一个门外汉的产品设计漫谈:从初级到神级的
- 下一篇: 互联网专用计算机屏保,18个Window