Android通过原生方式获取经纬度与城市信息的方法

 更新时间:2020年07月30日 08:43:00   作者:SoarYuan  
这篇文章主要给大家介绍了关于Android通过原生方式获取经纬度与城市信息的相关资料,文中通过示例代码介绍的非常详细,对各位Android开发者们具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧

一、概述

在项目中需要获取用户所在位置的经纬度和城市上送给风控系统。一般来说,定位有两种方式:

  1. 用第三方SDK定位,如百度地图、高德地图、谷歌地图;
  2. 用Android原生SDK中的api定位;

本文讲述定位的第二种方式--用Android原生的SDK中的api定位,如果项目定位要求较高还是建议使用第三方地图库。

二、Android原生SDK中的api定位

Android原生方式获取经纬度两种定位方式:GPS定位和Wifi定位

  • GPS定位相比Wifi定位更精准且可在无网络情况下使用,但在室内基本暴毙无法使用。
  • WiFi定位没有室内外限制,也不需要开启GPS但需要联网。但测试发现WiFi定位时onLocationChanged函数(用于监听经纬度变化)触发间隔无法小于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, "没有可用的位置提供器", Toast.LENGTH_SHORT).show();
   return;
  }

  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
   //获取权限(如果没有开启权限,会弹出对话框,询问是否开启权限)
   if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) 
     != PackageManager.PERMISSION_GRANTED || 
    ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) 
     != PackageManager.PERMISSION_GRANTED) {
    //请求权限
    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION,
      Manifest.permission.ACCESS_COARSE_LOCATION}, LOCATION_CODE);
   } else {
    //3.获取上次的位置,一般第一次运行,此值为null
    Location location = locationManager.getLastKnownLocation(locationProvider);
    if (location!=null){
     Toast.makeText(this, location.getLongitude() + " " + 
           location.getLatitude() + "",Toast.LENGTH_SHORT).show();
     Log.v("TAG", "获取上次的位置-经纬度:"+location.getLongitude()+" "+location.getLatitude());
     getAddress(location);

    }else{
     //监视地理位置变化,第二个和第三个参数分别为更新的最短时间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", "获取上次的位置-经纬度:"+location.getLongitude()+" "+location.getLatitude());
    getAddress(location);

   }else{
    //监视地理位置变化,第二个和第三个参数分别为更新的最短时间minTime和最短距离minDistace
    locationManager.requestLocationUpdates(locationProvider, 3000, 1,locationListener);
   }
  }
 }

 public LocationListener locationListener = new LocationListener() {
  // Provider的状态在可用、暂时不可用和无服务三个状态直接切换时触发此函数
  @Override
  public void onStatusChanged(String provider, int status, Bundle extras) {
  }
  // Provider被enable时触发此函数,比如GPS被打开
  @Override
  public void onProviderEnabled(String provider) {
  }
  // Provider被disable时触发此函数,比如GPS被关闭
  @Override
  public void onProviderDisabled(String provider) {
  }
  //当坐标改变时触发此函数,如果Provider传进相同的坐标,它就不会被触发
  @Override
  public void onLocationChanged(Location location) {
   if (location != null) {
    //如果位置发生变化,重新显示地理位置经纬度
    Toast.makeText(TestLocationActivity.this, location.getLongitude() + " " + 
               location.getLatitude() + "", Toast.LENGTH_SHORT).show();
    Log.v("TAG", "监视地理位置变化-经纬度:"+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, "申请权限", 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", "获取上次的位置-经纬度:"+location.getLongitude()+" "+location.getLatitude());
      }else{
       // 监视地理位置变化,第二个和第三个参数分别为更新的最短时间minTime和最短距离minDistace
       locationManager.requestLocationUpdates(locationProvider, 0, 0,locationListener);
      }

     }catch (SecurityException e){
      e.printStackTrace();
     }
    } else {
     Toast.makeText(this, "缺少权限", 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加权限

<!-- 粗略的位置权限 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission> 
<!-- 精确的位置权限 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
<uses-permission android:name="android.permission.INTERNET"></uses-permission>

三、总结

首先将手机定位服务设置,调到下图所示:

这可能会获取不到经纬度。为什么在网络和GPS都可用的情况下只执行GPS而不是网络?也许是从精确度考虑的,但是走GPS进入监听的listener后,不会执行onLocationChanged()方法,因为我是在室内,没有移动,所以如果你获取不到经纬度,就要将定位服务调到仅使用网络定位或者关闭手机GPS这样就可以获取到了。

总结

到此这篇关于Android通过原生方式获取经纬度与城市信息的文章就介绍到这了,更多相关Android原生获取经纬度与城市信息内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 自定义滑动按钮为例图文剖析Android自定义View绘制

    自定义滑动按钮为例图文剖析Android自定义View绘制

    这篇文章主要介绍了自定义滑动按钮的例子,图文剖析Android自定义View绘制,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-03-03
  • Android SeekBar充当Progress实现兔兔进度条Plus

    Android SeekBar充当Progress实现兔兔进度条Plus

    这篇文章主要为大家介绍了Android SeekBar充当Progress实现兔兔进度条Plus示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-02-02
  • Android TextView显示Html类解析的网页和图片及自定义标签用法示例

    Android TextView显示Html类解析的网页和图片及自定义标签用法示例

    这篇文章主要介绍了Android TextView显示Html类解析的网页和图片及自定义标签用法,实例分析了Android中TextView控件的使用技巧,需要的朋友可以参考下
    2016-07-07
  • Android OpenGL ES实现简单绿幕抠图

    Android OpenGL ES实现简单绿幕抠图

    这篇文章主要为大家介绍了Android OpenGL ES实现简单绿幕抠图示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • Android 自定义可拖拽View界面渲染刷新后不会自动回到起始位置

    Android 自定义可拖拽View界面渲染刷新后不会自动回到起始位置

    这篇文章主要介绍了Android 自定义可拖拽View界面渲染刷新后不会自动回到起始位置的实现代码,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2017-02-02
  • 如何利用adb卸载手机预装软件(系统软件)

    如何利用adb卸载手机预装软件(系统软件)

    对于Android手机通常有很多不必要的预置软件,但是又无法卸载,占用桌面有很难受,所以本次使用adb工具来实现从电脑命令来卸载或停用软件,下面这篇文章主要给大家介绍了关于如何利用adb卸载手机预装软件(系统软件)的相关资料,需要的朋友可以参考下
    2022-09-09
  • Android开发之加载图片的方法

    Android开发之加载图片的方法

    这篇文章主要介绍了Android开发之加载图片的方法,涉及Android图片操作的相关技巧,需要的朋友可以参考下
    2015-05-05
  • Android中Permission权限机制的具体使用

    Android中Permission权限机制的具体使用

    这篇文章主要介绍了Android中Permission权限机制的具体使用,本文讲解了权限级别 protection level、ICC(inter-component communication)权限保护等内容,需要的朋友可以参考下
    2015-04-04
  • Android存储访问框架的使用小结

    Android存储访问框架的使用小结

    这篇文章主要介绍了Android存储访问框架的使用,存储访问框架API和MediaStore API的差异,在于存储访问框架API,是基于系统文件选择框的,用户选择了文件,那么相当于授权了, 可以访问所有类型的文件,需要的朋友可以参考下
    2022-01-01
  • Android自定义相机实现自动对焦和手动对焦

    Android自定义相机实现自动对焦和手动对焦

    这篇文章主要为大家详细介绍了android手动实现相机自动和手动对焦功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-12-12

最新评论