<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
現在的應用,幾乎每一個 App 都存在定位的邏輯,方便更好的推薦產品或服務,獲取當前裝置的經緯度是必備的功能了。有些 App 還是以LBS(基於位置服務)為基礎來實現的,比如美團,餓了嗎,不獲取到位置都無法使用的。
有些同學覺得不就是獲取到經緯度麼,Android 自帶的就有位置服務 LocationManager ,我們無需引入第三方服務,就可以很方便的實現定位邏輯。
確實 LocationManager 的使用很簡單,獲取經緯度很方便,我們就無需第三方的服務了嗎? 或者說 LocationManager 有沒有坑呢?相容性問題怎麼樣?獲取不到位置有沒有什麼兜底策略?
由於是Android的系統服務,直接 getSystemService 可以獲取到
LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
一般獲取位置有兩種方式 NetWork 與 GPS 。我們可以指定方式,也可以讓系統自動提供最好的方式。
// 獲取所有可用的位置提供器 List<String> providerList = locationManager.getProviders(true); // 可以指定優先GPS,再次網路定位 if (providerList.contains(LocationManager.GPS_PROVIDER)) { provider = LocationManager.GPS_PROVIDER; } else if (providerList.contains(LocationManager.NETWORK_PROVIDER)) { provider = LocationManager.NETWORK_PROVIDER; } else { // 當沒有可用的位置提供器時,彈出Toast提示使用者 return; }
當然我更推薦由系統提供,當我的裝置在室內的時候就會以網路的定位提供,當裝置在室外的時候就可以提供GPS定位。
String provider = locationManager.getBestProvider(criteria, true);
我們可以實現一個定位的Service實現這個邏輯
/** * 獲取定位服務 */ public class LocationService extends Service { private LocationManager lm; private MyLocationListener listener; @Override public IBinder onBind(Intent intent) { return null; } @SuppressLint("MissingPermission") @Override public void onCreate() { super.onCreate(); lm = (LocationManager) getSystemService(LOCATION_SERVICE); listener = new MyLocationListener(); Criteria criteria = new Criteria(); criteria.setAccuracy(Criteria.ACCURACY_COARSE); criteria.setAltitudeRequired(false);//不要求海拔 criteria.setBearingRequired(false);//不要求方位 criteria.setCostAllowed(true);//允許有花費 criteria.setPowerRequirement(Criteria.POWER_LOW);//低功耗 String provider = lm.getBestProvider(criteria, true); YYLogUtils.w("定位的provider:" + provider); Location location = lm.getLastKnownLocation(provider); YYLogUtils.w("location-" + location); if (location != null) { //不為空,顯示地理位置經緯度 String longitude = "Longitude:" + location.getLongitude(); String latitude = "Latitude:" + location.getLatitude(); YYLogUtils.w("getLastKnownLocation:" + longitude + "-" + latitude); stopSelf(); } //第二個引數是間隔時間 第三個引數是間隔多少距離,這裡我試過了不同的各種組合,能獲取到位置就是能,不能獲取就是不能 lm.requestLocationUpdates(provider, 3000, 10, listener); } class MyLocationListener implements LocationListener { // 位置改變時獲取經緯度 @Override public void onLocationChanged(Location location) { String longitude = "Longitude:" + location.getLongitude(); String latitude = "Latitude:" + location.getLatitude(); YYLogUtils.w("onLocationChanged:" + longitude + "-" + latitude); stopSelf(); // 獲取到經緯度以後,停止該service } // 狀態改變時 @Override public void onStatusChanged(String provider, int status, Bundle extras) { YYLogUtils.w("onStatusChanged - provider:"+provider +" status:"+status); } // 提供者可以使用時 @Override public void onProviderEnabled(String provider) { YYLogUtils.w("GPS開啟了"); } // 提供者不可以使用時 @Override public void onProviderDisabled(String provider) { YYLogUtils.w("GPS關閉了"); } } @Override public void onDestroy() { super.onDestroy(); lm.removeUpdates(listener); // 停止所有的定位服務 } }
使用:定義並動態申請許可權之後即可開啟服務
fun testLocation() { extRequestPermission(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION) { startService(Intent(mActivity, LocationService::class.java)) } }
這樣我們啟動這個服務就可以獲取到當前的經緯度,只是獲取一次,大家如果想再後臺持續定位,那麼實現的方式就不同了,我們服務要設定為前臺服務,並且需要額外申請後臺定位許可權。
話說回來,這麼使用就一定能獲取到經緯度嗎?有沒有相容性問題
Android 5.0 Oppo
Android 6.0 Oppo海外版
Android 7.0 華為
Android 11 三星海外版
Android 12 vivo
目前測試不多,也能發現問題,特別是一些低版本,老系統的手機就可能無法獲取位置,應該是系統的問題,這種服務跟網路沒關係,開不開代理都是一樣的。
並且隨著測試系統的變高,越來越完善,提供的最好定位方式還出現混合定位 fused 的選項。
那是不是6.0的Oppo手機太老了,不支援定位了?並不是,百度定位可以獲取到位置的。
既然只使用 LocationManager 有風險,有可能無法獲取到位置,那怎麼辦?
其實目前百度,高度的定位Api的服務SDK也不算大,相比地圖導航等比較重的功能,定位的SDK很小了,並且目前都支援海外的定位服務。並且定位服務是免費的哦。
既然 LocationManager 有可能獲取不到位置,那我們就加入第三方定位服務,比如百度定位。我們同時使用 LocationManager 和百度定位,哪個先成功就用哪一個。(如果LocationManager可用的話,它的定位比百度定位更快的)
完整程式碼如下:
@SuppressLint("MissingPermission") public class LocationService extends Service { private LocationManager lm; private MyLocationListener listener; private LocationClient mBDLocationClient = null; private MyBDLocationListener mBDLocationListener; @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); createNativeLocation(); createBDLocation(); } /** * 第三方百度定位服務 */ private void createBDLocation() { mBDLocationClient = new LocationClient(UIUtils.getContext()); mBDLocationListener = new MyBDLocationListener(); //宣告LocationClient類 mBDLocationClient.registerLocationListener(mBDLocationListener); //設定百度定位的選項 LocationClientOption option = new LocationClientOption(); option.setLocationMode(LocationClientOption.LocationMode.Battery_Saving); option.setCoorType("WGS84"); option.setScanSpan(10000); option.setIsNeedAddress(true); option.setOpenGps(true); option.SetIgnoreCacheException(false); option.setWifiCacheTimeOut(5 * 60 * 1000); option.setEnableSimulateGps(false); mBDLocationClient.setLocOption(option); //開啟百度定位 mBDLocationClient.start(); } /** * 原生的定位服務 */ private void createNativeLocation() { lm = (LocationManager) getSystemService(LOCATION_SERVICE); listener = new MyLocationListener(); Criteria criteria = new Criteria(); criteria.setAccuracy(Criteria.ACCURACY_COARSE); criteria.setAltitudeRequired(false);//不要求海拔 criteria.setBearingRequired(false);//不要求方位 criteria.setCostAllowed(true);//允許有花費 criteria.setPowerRequirement(Criteria.POWER_LOW);//低功耗 String provider = lm.getBestProvider(criteria, true); YYLogUtils.w("定位的provider:" + provider); Location location = lm.getLastKnownLocation(provider); YYLogUtils.w("location-" + location); if (location != null) { //不為空,顯示地理位置經緯度 String longitude = "Longitude:" + location.getLongitude(); String latitude = "Latitude:" + location.getLatitude(); YYLogUtils.w("getLastKnownLocation:" + longitude + "-" + latitude); stopSelf(); } lm.requestLocationUpdates(provider, 3000, 10, listener); } class MyLocationListener implements LocationListener { // 位置改變時獲取經緯度 @Override public void onLocationChanged(Location location) { String longitude = "Longitude:" + location.getLongitude(); String latitude = "Latitude:" + location.getLatitude(); YYLogUtils.w("onLocationChanged:" + longitude + "-" + latitude); stopSelf(); // 獲取到經緯度以後,停止該service } // 狀態改變時 @Override public void onStatusChanged(String provider, int status, Bundle extras) { YYLogUtils.w("onStatusChanged - provider:" + provider + " status:" + status); } // 提供者可以使用時 @Override public void onProviderEnabled(String provider) { YYLogUtils.w("GPS開啟了"); } // 提供者不可以使用時 @Override public void onProviderDisabled(String provider) { YYLogUtils.w("GPS關閉了"); } } /** * 百度定位的監聽 */ class MyBDLocationListener extends BDAbstractLocationListener { @Override public void onReceiveLocation(BDLocation location) { double latitude = location.getLatitude(); //獲取緯度資訊 double longitude = location.getLongitude(); //獲取經度資訊 YYLogUtils.w("百度的監聽 latitude:" + latitude); YYLogUtils.w("百度的監聽 longitude:" + longitude); YYLogUtils.w("onBaiduLocationChanged:" + longitude + "-" + latitude); stopSelf(); // 獲取到經緯度以後,停止該service } } @Override public void onDestroy() { super.onDestroy(); // 停止所有的定位服務 lm.removeUpdates(listener); mBDLocationClient.stop(); mBDLocationClient.unregisterLocationListener(mBDLocationListener); } }
其實邏輯都是很簡單的,並且省略了不少回撥通訊的邏輯,這裡只涉及到定位的邏輯,別的邏輯我就儘量不涉及到。
百度定位服務的API申請與初始化請自行完善,這裡只是簡單的使用。並且座標系統一為國際座標,如果需要轉gcj02的座標系,可以網上找個工具類,或者看我之前的文章。
獲取到位置之後,如何Service與Activity通訊,就由大家自由發揮了,有興趣的可以看我之前的文章。
所以說Android原生定位服務 LocationManager 還是有問題啊,低版本的裝置可能不行,高版本的Android系統又很行,相容性有問題!讓人又愛又恨。
很羨慕iOS的定位服務,真的好用,我們 Android 的定位服務真是拉跨,居然還有相容性問題。
我們使用第三方定位服務和自己的 LocationManager 並行獲取位置,這樣可以增加容錯率。是比較好用的,為什麼要加上 LocationManager 呢?
我直接單獨用第三方的定位服務不香嗎?可以是可以,但是如果裝置支援 LocationManager 的話,它會更快一點,體驗更好。
以上就是Android原生定位服務LocationManager的詳細內容,更多關於Android定位LocationManager的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45