一、概述
在項(xiàng)目中需要獲取用戶(hù)所在位置的經(jīng)緯度和城市上送給風(fēng)控系統(tǒng)狈惫。一般來(lái)說(shuō)睛蛛,定位有兩種方式:
用第三方SDK定位,如百度地圖胧谈、高德地圖忆肾、谷歌地圖;
用Android原生SDK中的api定位菱肖;
本文講述定位的第二種方式--用Android原生的SDK中的api定位客冈,如果項(xiàng)目定位要求較高還是建議使用第三方地圖庫(kù)。
二稳强、Android原生SDK中的api定位
Android原生方式獲取經(jīng)緯度兩種定位方式:GPS定位和Wifi定位
GPS定位相比Wifi定位更精準(zhǔn)且可在無(wú)網(wǎng)絡(luò)情況下使用场仲,但在室內(nèi)基本暴斃無(wú)法使用。
WiFi定位沒(méi)有室內(nèi)外限制退疫,也不需要開(kāi)啟GPS但需要聯(lián)網(wǎng)渠缕。但測(cè)試發(fā)現(xiàn)WiFi定位時(shí)onLocationChanged函數(shù)(用于監(jiān)聽(tīng)經(jīng)緯度變化)觸發(fā)間隔無(wú)法小于30s。
示例代碼如下:
public class TestLocationActivity extends AppCompatActivity {
? ? public static final int LOCATION_CODE = 301;
? ? private LocationManager locationManager;
? ? private String locationProvider = null;
? ? @Override
? ? protected void onCreate(@Nullable Bundle savedInstanceState) {
? ? ? ? super.onCreate(savedInstanceState);
? ? ? ? getLocation();
? ? }
? ? private void getLocation(){
? ? ? ? //1.獲取位置管理器
? ? ? ? locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
? ? ? ? //2.獲取位置提供器褒繁,GPS或是NetWork
? ? ? ? List<String> providers = locationManager.getProviders(true);
? ? ? ? if (providers.contains(LocationManager.GPS_PROVIDER)) {
? ? ? ? ? ? //如果是GPS
? ? ? ? ? ? locationProvider = LocationManager.GPS_PROVIDER;
? ? ? ? ? ? Log.v("TAG", "定位方式GPS");
? ? ? ? } else if (providers.contains(LocationManager.NETWORK_PROVIDER)) {
? ? ? ? ? ? //如果是Network
? ? ? ? ? ? locationProvider = LocationManager.NETWORK_PROVIDER;
? ? ? ? ? ? Log.v("TAG", "定位方式Network");
? ? ? ? }else {
? ? ? ? ? ? Toast.makeText(this, "沒(méi)有可用的位置提供器", Toast.LENGTH_SHORT).show();
? ? ? ? ? ? return;
? ? ? ? }
? ? ? ? if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
? ? ? ? ? ? //獲取權(quán)限(如果沒(méi)有開(kāi)啟權(quán)限亦鳞,會(huì)彈出對(duì)話框,詢(xún)問(wèn)是否開(kāi)啟權(quán)限)
? ? ? ? ? ? if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
? ? ? ? ? ? ? ? ? ? != PackageManager.PERMISSION_GRANTED ||
? ? ? ? ? ? ? ? ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
? ? ? ? ? ? ? ? ? ? != PackageManager.PERMISSION_GRANTED) {
? ? ? ? ? ? ? ? //請(qǐng)求權(quán)限
? ? ? ? ? ? ? ? ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION,
? ? ? ? ? ? ? ? ? ? ? ? Manifest.permission.ACCESS_COARSE_LOCATION}, LOCATION_CODE);
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? //3.獲取上次的位置棒坏,一般第一次運(yùn)行燕差,此值為null
? ? ? ? ? ? ? ? Location location = locationManager.getLastKnownLocation(locationProvider);
? ? ? ? ? ? ? ? if (location!=null){
? ? ? ? ? ? ? ? ? ? Toast.makeText(this, location.getLongitude() + " " +
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? location.getLatitude() + "",Toast.LENGTH_SHORT).show();
? ? ? ? ? ? ? ? ? ? Log.v("TAG", "獲取上次的位置-經(jīng)緯度:"+location.getLongitude()+"? "+location.getLatitude());
? ? ? ? ? ? ? ? ? ? getAddress(location);
? ? ? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? ? ? //監(jiān)視地理位置變化,第二個(gè)和第三個(gè)參數(shù)分別為更新的最短時(shí)間minTime和最短距離minDistace
? ? ? ? ? ? ? ? ? ? locationManager.requestLocationUpdates(locationProvider, 3000, 1,locationListener);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? } else {
? ? ? ? ? ? Location location = locationManager.getLastKnownLocation(locationProvider);
? ? ? ? ? ? if (location!=null){
? ? ? ? ? ? ? ? Toast.makeText(this, location.getLongitude() + " " +
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? location.getLatitude() + "", Toast.LENGTH_SHORT).show();
? ? ? ? ? ? ? ? Log.v("TAG", "獲取上次的位置-經(jīng)緯度:"+location.getLongitude()+"? "+location.getLatitude());
? ? ? ? ? ? ? ? getAddress(location);
? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? //監(jiān)視地理位置變化坝冕,第二個(gè)和第三個(gè)參數(shù)分別為更新的最短時(shí)間minTime和最短距離minDistace
? ? ? ? ? ? ? ? locationManager.requestLocationUpdates(locationProvider, 3000, 1,locationListener);
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ? public LocationListener locationListener = new LocationListener() {
? ? ? ? // Provider的狀態(tài)在可用徒探、暫時(shí)不可用和無(wú)服務(wù)三個(gè)狀態(tài)直接切換時(shí)觸發(fā)此函數(shù)
? ? ? ? @Override
? ? ? ? public void onStatusChanged(String provider, int status, Bundle extras) {
? ? ? ? }
? ? ? ? // Provider被enable時(shí)觸發(fā)此函數(shù),比如GPS被打開(kāi)
? ? ? ? @Override
? ? ? ? public void onProviderEnabled(String provider) {
? ? ? ? }
? ? ? ? // Provider被disable時(shí)觸發(fā)此函數(shù)徽诲,比如GPS被關(guān)閉
? ? ? ? @Override
? ? ? ? public void onProviderDisabled(String provider) {
? ? ? ? }
? ? ? ? //當(dāng)坐標(biāo)改變時(shí)觸發(fā)此函數(shù)刹帕,如果Provider傳進(jìn)相同的坐標(biāo),它就不會(huì)被觸發(fā)
? ? ? ? @Override
? ? ? ? public void onLocationChanged(Location location) {
? ? ? ? ? ? if (location != null) {
? ? ? ? ? ? ? ? //如果位置發(fā)生變化谎替,重新顯示地理位置經(jīng)緯度
? ? ? ? ? ? ? ? Toast.makeText(TestLocationActivity.this, location.getLongitude() + " " +
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? location.getLatitude() + "", Toast.LENGTH_SHORT).show();
? ? ? ? ? ? ? ? Log.v("TAG", "監(jiān)視地理位置變化-經(jīng)緯度:"+location.getLongitude()+"? "+location.getLatitude());
? ? ? ? ? ? }
? ? ? ? }
? ? };
? ? @Override
? ? public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
? ? ? ? switch (requestCode) {
? ? ? ? ? ? case LOCATION_CODE:
? ? ? ? ? ? ? ? if(grantResults.length > 0 && grantResults[0] == getPackageManager().PERMISSION_GRANTED
? ? ? ? ? ? ? ? ? ? ? ? && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
? ? ? ? ? ? ? ? ? ? Toast.makeText(this, "申請(qǐng)權(quán)限", Toast.LENGTH_LONG).show();
? ? ? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? ? ? List<String> providers = locationManager.getProviders(true);
? ? ? ? ? ? ? ? ? ? ? ? if (providers.contains(LocationManager.NETWORK_PROVIDER)) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? //如果是Network
? ? ? ? ? ? ? ? ? ? ? ? ? ? locationProvider = LocationManager.NETWORK_PROVIDER;
? ? ? ? ? ? ? ? ? ? ? ? }else if (providers.contains(LocationManager.GPS_PROVIDER)) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? //如果是GPS
? ? ? ? ? ? ? ? ? ? ? ? ? ? locationProvider = LocationManager.GPS_PROVIDER;
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? Location location = locationManager.getLastKnownLocation(locationProvider);
? ? ? ? ? ? ? ? ? ? ? ? if (location!=null){
? ? ? ? ? ? ? ? ? ? ? ? ? ? Toast.makeText(this, location.getLongitude() + " " +
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? location.getLatitude() + "", Toast.LENGTH_SHORT).show();
? ? ? ? ? ? ? ? ? ? ? ? ? ? Log.v("TAG", "獲取上次的位置-經(jīng)緯度:"+location.getLongitude()+"? "+location.getLatitude());
? ? ? ? ? ? ? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? ? ? ? ? ? ? // 監(jiān)視地理位置變化,第二個(gè)和第三個(gè)參數(shù)分別為更新的最短時(shí)間minTime和最短距離minDistace
? ? ? ? ? ? ? ? ? ? ? ? ? ? locationManager.requestLocationUpdates(locationProvider, 0, 0,locationListener);
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? }catch (SecurityException e){
? ? ? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? Toast.makeText(this, "缺少權(quán)限", Toast.LENGTH_LONG).show();
? ? ? ? ? ? ? ? ? ? finish();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? break;
? ? ? ? }
? ? }
? ? //獲取地址信息:城市蹋辅、街道等信息
? ? private List<Address> getAddress(Location location) {
? ? ? ? List<Address> result = null;
? ? ? ? try {
? ? ? ? ? ? if (location != null) {
? ? ? ? ? ? ? ? Geocoder gc = new Geocoder(this, Locale.getDefault());
? ? ? ? ? ? ? ? result = gc.getFromLocation(location.getLatitude(),
? ? ? ? ? ? ? ? ? ? ? ? location.getLongitude(), 1);
? ? ? ? ? ? ? ? Toast.makeText(this, "獲取地址信息:"+result.toString(), Toast.LENGTH_LONG).show();
? ? ? ? ? ? ? ? Log.v("TAG", "獲取地址信息:"+result.toString());
? ? ? ? ? ? }
? ? ? ? } catch (Exception e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? ? ? return result;
? ? }
? ? @Override
? ? protected void onDestroy() {
? ? ? ? super.onDestroy();
? ? ? ? locationManager.removeUpdates(locationListener);
? ? }
}
在AndroidManifest.xml加權(quán)限
<!-- 粗略的位置權(quán)限 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
<!-- 精確的位置權(quán)限 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
三钱贯、總結(jié)
首先將手機(jī)定位服務(wù)設(shè)置,調(diào)到下圖所示:
這可能會(huì)獲取不到經(jīng)緯度侦另。為什么在網(wǎng)絡(luò)和GPS都可用的情況下只執(zhí)行GPS而不是網(wǎng)絡(luò)秩命?也許是從精確度考慮的尉共,但是走GPS進(jìn)入監(jiān)聽(tīng)的listener后,不會(huì)執(zhí)行onLocationChanged()方法弃锐,因?yàn)槲沂窃谑覂?nèi)袄友,沒(méi)有移動(dòng),所以如果你獲取不到經(jīng)緯度霹菊,就要將定位服務(wù)調(diào)到僅使用網(wǎng)絡(luò)定位或者關(guān)閉手機(jī)GPS這樣就可以獲取到了剧蚣。
一點(diǎn)題外話:
我們有《Android學(xué)習(xí)、面試旋廷;文檔鸠按、視頻資源免費(fèi)獲取》,可復(fù)制鏈接后用石墨文檔 App 或小程序打開(kāi)鏈接或者私信我資料領(lǐng)取饶碘。
https://shimo.im/docs/TG8PDh9D96WGTT8W