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

本文共 7028 字,大约阅读时间需要 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/

    你可能感兴趣的文章
    Nio ByteBuffer组件读写指针切换原理与常用方法
    查看>>
    NIO Selector实现原理
    查看>>
    nio 中channel和buffer的基本使用
    查看>>
    NIO基于UDP协议的网络编程
    查看>>
    NISP一级,NISP二级报考说明,零基础入门到精通,收藏这篇就够了
    查看>>
    Nitrux 3.8 发布!性能全面提升,带来非凡体验
    查看>>
    NI笔试——大数加法
    查看>>
    NLog 自定义字段 写入 oracle
    查看>>
    NLog类库使用探索——详解配置
    查看>>
    NLP 基于kashgari和BERT实现中文命名实体识别(NER)
    查看>>
    NLP 项目:维基百科文章爬虫和分类【01】 - 语料库阅读器
    查看>>
    NLP_什么是统计语言模型_条件概率的链式法则_n元统计语言模型_马尔科夫链_数据稀疏(出现了词库中没有的词)_统计语言模型的平滑策略---人工智能工作笔记0035
    查看>>
    NLP学习笔记:使用 Python 进行NLTK
    查看>>
    NLP的神经网络训练的新模式
    查看>>
    NLP问答系统:使用 Deepset SQUAD 和 SQuAD v2 度量评估
    查看>>
    NLP:使用 SciKit Learn 的文本矢量化方法
    查看>>
    Nmap扫描教程之Nmap基础知识
    查看>>
    Nmap端口扫描工具Windows安装和命令大全(非常详细)零基础入门到精通,收藏这篇就够了
    查看>>
    NMAP网络扫描工具的安装与使用
    查看>>
    NMF(非负矩阵分解)
    查看>>