博客
关于我
Android 原生定位
阅读量:211 次
发布时间:2019-02-28

本文共 7141 字,大约阅读时间需要 23 分钟。

Android原生定位框架:核心组件与实践应用

定位方式比较

在移动应用开发中,定位功能是非常实用的功能之一。现有的定位方式主要有两种:GPS定位网络定位

GPS定位的优势

  • 精确度高:GPS定位能够提供较为精确的地理位置信息。
  • 适用范围广:在大多数情况下都是适用的。

GPS定位的局限

  • 依赖GPS信号:在室内环境下无法获取准确的位置数据。
  • 性能消耗大:持续获取GPS定位会对设备电池造成较大消耗。

网络定位的优势

  • 适用性强:无论在室内还是室外都能获取定位信息。
  • 性能优越:网络定位的获取速度较快,且对设备电池的消耗较低。

网络定位的局限

  • 精度有限:相比GPS定位,网络定位的位置精度一般较低。

Android原生定位框架的核心组件

在Android系统中,定位功能的实现主要依赖于以下几个核心组件:

1. 系统服务

  • 获取方式:无需实例化,可以通过getSystemService(Context.LOCATION_SERVICE)获取LocationManager实例。
  • 功能说明:作为定位功能的核心管理器,负责协调各个定位提供商(如GPS和网络定位)的工作。

2. 定位监听器

  • 回调机制:通过定义LocationListener接口,实现对定位事件的响应处理。
  • 事件类型
    • onLocationChanged(Location location):定位信息更新时的回调。
    • onStatusChanged(String provider, int status, Bundle extras):定位提供商状态变化的回调。
    • onProviderEnabled(String provider):定位提供商启用的回调。
    • onProviderDisabled(String provider):定位提供商禁用的回调。

3. 定位更新请求

  • API调用:通过requestLocationUpdates方法请求定位更新。
  • 参数说明
    • LocationManager.NETWORK_PROVIDER:网络定位提供商。
    • LocationManager.GPS_PROVIDER:GPS定位提供商。
    • 更新周期:0(持续更新)。
    • 更新间隔:0(每隔0ms更新一次)。

定位权限管理

在使用定位功能时,需要注意以下几点:

1. 必要权限申请

  • 网络定位权限:如果使用NETWORK_PROVIDER,则需要申请ACCESS_COARSE_LOCATION权限。
  • 精度定位权限:如果使用GPS_PROVIDER或同时使用两种定位方式,则需要申请ACCESS_FINE_LOCATION权限。

2. 权限申请流程

  • Android 5.0以上版本:需要显式申请以下权限:
    • android.hardware.location.network
    • android.hardware.location.gps

3. 权限获取方法

  • 动态权限申请:使用ContextCompat.checkSelfPermission检查权限状态,并根据需要申请权限。

地址与位置转换

在定位过程中,需要将获取到的经纬度坐标转换为具体的地址信息,可以使用Geocoder类完成。

使用步骤

  • 创建Geocoder实例
    Geocoder gc = new Geocoder(this, Locale.getDefault());
  • 获取地址信息
    List
    locationList = gc.getFromLocation(latitude, longitude, 1);
  • 处理地址信息
    • 提取国家、省份、城市等信息。
    • 逐步清除地址信息中的冗余部分(如国家名称、行政区域名称、城市名称),保留用户关注的核心地址信息。
  • 示例代码解析

    以下是一个完整的定位功能实现示例:

    public class LocationActivity extends Activity implements View.OnClickListener {
    private static final String TAG = LocationActivity.class.getSimpleName();
    private LocationManager locationManager;
    private LocationListener locationListener;
    private TextView tv;
    private Button btnStart;
    private Button btnEnd;
    private Button btnClean;
    private StringBuilder stringBuilder;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_location);
    setTitle("原生定位");
    tv = findViewById(R.id.tv);
    btnStart = findViewById(R.id.btnStart);
    btnEnd = findViewById(R.id.btnEnd);
    btnClean = findViewById(R.id.btnClean);
    btnStart.setOnClickListener(this);
    btnEnd.setOnClickListener(this);
    btnClean.setOnClickListener(this);
    tv.setMovementMethod(ScrollingMovementMethod.getInstance());
    locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    locationListener = new LocationListener() {
    @Override
    public void onLocationChanged(Location location) {
    stringBuilder.append(getTime()).append("\t定位信息:\n");
    stringBuilder.append("\t").append(location.getLatitude()).append("\n");
    stringBuilder.append("\t").append(location.getLongitude()).append("\n");
    stringBuilder.append("\t").append(location.getProvider()).append("\n");
    tv.setText(stringBuilder);
    Geocoder gc = new Geocoder(LocationActivity.this, Locale.getDefault());
    List
    locationList = null;
    try {
    locationList = gc.getFromLocation(location.getLatitude(), location.getLongitude(), 1);
    } catch (IOException e) {
    e.printStackTrace();
    }
    Address address = locationList.get(0);
    if (address == null) {
    return;
    }
    stringBuilder.append(getTime()).append("\t地址信息:\n");
    String countryName = address.getCountryName();
    if (!TextUtils.isEmpty(countryName)) {
    stringBuilder.append(countryName);
    }
    String adminArea = address.getAdminArea();
    if (!TextUtils.isEmpty(adminArea)) {
    stringBuilder.append(adminArea);
    }
    String locality = address.getLocality();
    if (!TextUtils.isEmpty(locality)) {
    stringBuilder.append(locality);
    }
    for (int i = 0; address.getAddressLine(i) != null; i++) {
    String addressLine = address.getAddressLine(i);
    if (!TextUtils.isEmpty(addressLine)) {
    if (addressLine.contains(countryName)) {
    addressLine = addressLine.replace(countryName, "");
    }
    if (addressLine.contains(adminArea)) {
    addressLine = addressLine.replace(adminArea, "");
    }
    if (addressLine.contains(locality)) {
    addressLine = addressLine.replace(locality, "");
    }
    if (!TextUtils.isEmpty(addressLine)) {
    stringBuilder.append(addressLine);
    }
    }
    }
    String featureName = address.getFeatureName();
    if (!TextUtils.isEmpty(featureName)) {
    stringBuilder.append(featureName).append("\n");
    }
    tv.setText(stringBuilder);
    }
    // 其他回调方法(onStatusChanged、onProviderEnabled、onProviderDisabled)可以根据需要添加
    };
    }
    @Override
    public void onClick(View v) {
    switch (v.getId()) {
    case R.id.btnStart:
    stringBuilder.append(getTime()).append("\t开始定位\n");
    tv.setText(stringBuilder);
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_DENIED) {
    return;
    }
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_DENIED) {
    return;
    }
    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
    locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
    break;
    case R.id.btnEnd:
    locationManager.removeUpdates(locationListener);
    stringBuilder.append(getTime()).append("\t结束定位\n\n");
    tv.setText(stringBuilder);
    break;
    case R.id.btnClean:
    stringBuilder.delete(0, stringBuilder.length());
    tv.setText(stringBuilder);
    break;
    default:
    break;
    }
    }
    private String getTime() {
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss", Locale.getDefault());
    return simpleDateFormat.format(new Date(System.currentTimeMillis()));
    }
    }

    总结

    通过上述内容可以看出,Android原生定位框架提供了一套完整的API,开发者可以根据实际需求选择合适的定位方式和定位提供商。在实现定位功能时,需要注意权限申请和使用的同时要确保定位服务的稳定性和用户体验的良好。

    转载地址:http://dles.baihongyu.com/

    你可能感兴趣的文章
    Nginx 学习总结(16)—— 动静分离、压缩、缓存、黑白名单、性能等内容温习
    查看>>
    Nginx 学习总结(17)—— 8 个免费开源 Nginx 管理系统,轻松管理 Nginx 站点配置
    查看>>
    Nginx 学习(一):Nginx 下载和启动
    查看>>
    nginx 常用指令配置总结
    查看>>
    Nginx 常用配置清单
    查看>>
    nginx 常用配置记录
    查看>>
    nginx 开启ssl模块 [emerg] the “ssl“ parameter requires ngx_http_ssl_module in /usr/local/nginx
    查看>>
    Nginx 我们必须知道的那些事
    查看>>
    Nginx 的 proxy_pass 使用简介
    查看>>
    Nginx 的配置文件中的 keepalive 介绍
    查看>>
    Nginx 结合 consul 实现动态负载均衡
    查看>>
    Nginx 负载均衡与权重配置解析
    查看>>
    Nginx 负载均衡详解
    查看>>
    nginx 配置 单页面应用的解决方案
    查看>>
    nginx 配置https(一)—— 自签名证书
    查看>>
    nginx 配置~~~本身就是一个静态资源的服务器
    查看>>
    Nginx 配置清单(一篇够用)
    查看>>
    Nginx 配置解析:从基础到高级应用指南
    查看>>
    nginx+php的搭建
    查看>>
    nginx+tomcat+memcached
    查看>>