Google Play Services Location:显示位置的地址

2023-10-31

在前面的blog中讲述了怎样获取最后已知位置和接收位置更新后如何从location对象中获取用户的位置,包含经纬度的坐标。 虽然纬度和经度是用于计算距离或显示地图的位置,在许多情况下,位置的地址是更为有用的。 例如,如果你想让你的用户知道他们是在哪,或他们正在接近什么,所以街道地址比位置的地理坐标(纬度/经度)更有意义。

利用Geocoder在Android框架位置API类,您可以将地址转换为相应的地理坐标。 这个过程被称为地理编码 。 或者,您可以地理位置转换为一个地址。 地址查找功能也被称为反向地理编码 。

本课向您展示如何使用getFromLocation()方法来地理位置转换为一个地址。 该方法返回对应于给定的纬度和经度的估计的街道地址。

获取地理位置

该设备的最后已知​​位置是地址查找功能一个有用的起点。 关于课程获得最后一个已知的位置展示了如何使用getLastLocation()所提供的方法融合位置提供可以找到设备的最新位置。

要访问融合位置提供者,你需要创建谷歌Play服务API客户端的一个实例。 要了解如何连接您的客户端,请参阅连接到谷歌播放服务 。

为了使融合的位置提供检索精确的街道地址,应用清单来设置位置权限ACCESS_FINE_LOCATION ,如下面的例子:


  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

定义一个Intent服务,以获取地址

所述getFromLocation()由所提供的方法Geocoder类接受纬度和经度,并且返回地址的列表。 该方法是同步的,可能需要很长的时间来完成工作,所以你不应该从主,用户界面​​(UI),您的应用程序的线程中调用它。

该IntentService类 ​​提供了在后台线程运行任务的结构。 使用这个类,你可以处理一个长时间运行的操作,而不会影响你的用户界面的响应速度。 需要注意的是AsyncTask类还允许您进行后台操作,但它专为短期操作。 一个AsyncTask当装置旋转时不应该参考保持到UI如果活性被重新创建,例如。 与此相反,一个IntentService不需要时的活性被重建被取消。

定义一个FetchAddressIntentService扩展类IntentService 。 这个类是你的地址查找服务。 这样做的目的服务异步处理的工作线程的意图,当它运行的工作停止本身。 意图额外提供由该服务所需要的数据,其中包括一个Location为变换对象到一个地址,和一个ResultReceiver对象来处理的地址查找的结果。 该服务使用Geocoder来获取的地址的位置,并把结果发送到ResultReceiver 。

定义意图服务于应用清单

将一个条目添加到您的应用清单定义的意图服务:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.google.android.gms.location.sample.locationaddress" >
    <application
        ...
        <service
            android:name=".FetchAddressIntentService"
            android:exported="false"/>
    </application>
    ...
</manifest>

注: 在manifest元素并不需要包括意图过滤器,因为您的主要活动通过指定类的名称要使用的意图创建一个明确的意图。

创建地理编码

地理位置转换为地址的过程被称为反向地理编码 。 要执行的意图服务的主要工作,就是你的反向地理编码要求,落实onHandleIntent()的范围内FetchAddressIntentService类 ​​。 创建一个Geocoder对象来处理反向地理编码。

区域设置代表一个特定的地理或语言区域。 区域对象用于调整的信息的呈现,诸如数字或日期,以适合的约定在由区域设置所表示的区域。 传递一个Locale对象的Geocoder对象,以确保最终的地址定位于用户的地理区域。

@Override
protected void onHandleIntent(Intent intent) {
    Geocoder geocoder = new Geocoder(this, Locale.getDefault());
    ...
}

检索街道地址数据

下一步是检索来自解析器的街道地址,处理可能发生的任何错误,并把结果发送回请求的地址的活性。 要报告地理编码过程的结果,你需要两个数字常量指示成功或失败。 定义一个Constants类包含的值,如本代码片段:

public final class Constants {
    public static final int SUCCESS_RESULT = 0;
    public static final int FAILURE_RESULT = 1;
    public static final String PACKAGE_NAME =
        "com.google.android.gms.location.sample.locationaddress";
    public static final String RECEIVER = PACKAGE_NAME + ".RECEIVER";
    public static final String RESULT_DATA_KEY = PACKAGE_NAME +
        ".RESULT_DATA_KEY";
    public static final String LOCATION_DATA_EXTRA = PACKAGE_NAME +
        ".LOCATION_DATA_EXTRA";
}

要得到相应的地理位置一个街道地址,调用getFromLocation()它传递的纬度和经度从位置对象,你想返回的地址的最大数量。 在这种情况下,要只是一个地址。 地理编码器返回地址的数组。 如果没有发现地址匹配给定的位置,它返回一个空列表。 如果没有可用的后端地理编码服务,地理编码器返回null。

检查以下错误,如下面的代码示例所示。 如果出现错误,将在相应的错误信息errorMessage变量,这样你就可以将其发送回请求的活动:

没有提供位置数据 -其意图演员不包括Location的反向地理编码所需的对象。
无效的纬度或经度使用 -所提供的纬度和/或经度值Location的对象是无效的。
没有可用的地理编码器 -后台地理编码服务不可用,由于网络错误或IO异常。
很抱歉,没有找到地址 -地址解析器找不到地址为给定的纬度/经度。
为了得到一个地址对象的个别线路,使用getAddressLine()所提供的方法Address类。 再加入行到准备返回给请求地址的活动地址片段的列表。

将结果发送回请求活动 ​​,调用deliverResultToReceiver()方法(在定义的返回地址给请求者 )。 结果由前述的数字成功/失败的代码和一个串。 在一个成功的反向地理编码的情况下,字符串包含的地址。 在发生故障的情况下,该字符串包含错误消息,如下面的代码示例:

Override
protected void onHandleIntent(Intent intent) {
    String errorMessage = "";

    // Get the location passed to this service through an extra.
    Location location = intent.getParcelableExtra(
            Constants.LOCATION_DATA_EXTRA);

    ...

    List<Address> addresses = null;

    try {
        addresses = geocoder.getFromLocation(
                location.getLatitude(),
                location.getLongitude(),
                // In this sample, get just a single address.
                1);
    } catch (IOException ioException) {
        // Catch network or other I/O problems.
        errorMessage = getString(R.string.service_not_available);
        Log.e(TAG, errorMessage, ioException);
    } catch (IllegalArgumentException illegalArgumentException) {
        // Catch invalid latitude or longitude values.
        errorMessage = getString(R.string.invalid_lat_long_used);
        Log.e(TAG, errorMessage + ". " +
                "Latitude = " + location.getLatitude() +
                ", Longitude = " +
                location.getLongitude(), illegalArgumentException);
    }

    // Handle case where no address was found.
    if (addresses == null || addresses.size()  == 0) {
        if (errorMessage.isEmpty()) {
            errorMessage = getString(R.string.no_address_found);
            Log.e(TAG, errorMessage);
        }
        deliverResultToReceiver(Constants.FAILURE_RESULT, errorMessage);
    } else {
        Address address = addresses.get(0);
        ArrayList<String> addressFragments = new ArrayList<String>();

        // Fetch the address lines using getAddressLine,
        // join them, and send them to the thread.
        for(int i = 0; i < address.getMaxAddressLineIndex(); i++) {
            addressFragments.add(address.getAddressLine(i));
        }
        Log.i(TAG, getString(R.string.address_found));
        deliverResultToReceiver(Constants.SUCCESS_RESULT,
                TextUtils.join(System.getProperty("line.separator"),
                        addressFragments));
    }
}

返回地址给请求者

意图服务必须做的最后一件事是发送地址回ResultReceiver在活动启动该服务。 该ResultReceiver类允许你发送一个数字结果代码以及包含结果数据的消息。 数字代码是报告地址解析请求的成功或失败非常有用。 在一个成功的反向地理编码的情况下,该消息包含的地址。 在出现故障的情况下,该消息包含一些文本描述用于失败的原因。

你已经从地理编码检索到的地址,困可能出现的任何错误,并称为deliverResultToReceiver()方法。 现在,你需要定义deliverResultToReceiver()发送一个结果代码和消息捆绑到结果接收方法。

对于结果代码,使用已传递给值deliverResultToReceiver()的方法resultCode参数。 构造消息包,并置RESULT_DATA_KEY从恒定Constants类(定义在检索街道地址数据 ),并在该值message传递给参数deliverResultToReceiver()方法,如下面的示例中:

public class FetchAddressIntentService extends IntentService {
    protected ResultReceiver mReceiver;
    ...
    private void deliverResultToReceiver(int resultCode, String message) {
        Bundle bundle = new Bundle();
        bundle.putString(Constants.RESULT_DATA_KEY, message);
        mReceiver.send(resultCode, bundle);
    }
}

启动服务意向

意图的服务,如在上一节中所定义,在后台运行并负责获取对应于给定地理区域的地址。 当您启动该服务,Android框架实例,如果它没有运行启动该服务,并在需要时创建一个进程。 如果该服务已经运行,那么它仍然运行。 因为把服务延伸IntentService ,什么时候所有的意图都被处理自动关闭。

开始从你的应用程序的主活动服务,并创建一个Intent将数据传递到该服务。 你需要一个明确的意图,因为你只想要你的服务的意图做出回应。 欲了解更多信息,请参阅意图类型 。

要创建一个明确的意图,指定类使用该服务的名称: FetchAddressIntentService.class 。 通过在意图额外两条信息:

一个ResultReceiver处理地址查找的结果。
一个Location包含要转换到一个地址的经纬度对象。
下面的代码示例演示如何启动的意图服务:

public class MainActivity extends ActionBarActivity implements
        ConnectionCallbacks, OnConnectionFailedListener {

    protected Location mLastLocation;
    private AddressResultReceiver mResultReceiver;
    ...

    protected void startIntentService() {
        Intent intent = new Intent(this, FetchAddressIntentService.class);
        intent.putExtra(Constants.RECEIVER, mResultReceiver);
        intent.putExtra(Constants.LOCATION_DATA_EXTRA, mLastLocation);
        startService(intent);
    }
}

调用上面startIntentService()当用户需要一个需要地理编码地址查找的操作方法。 例如,用户可以按你的应用程序的UI中获取地址按钮。 开始的意图服务之前,您需要检查到谷歌Play服务连接存在。 下面的代码片段展示了调用startIntentService()在按钮处理程序方法:

public void fetchAddressButtonHandler(View view) {
    // Only start the service to fetch the address if GoogleApiClient is
    // connected.
    if (mGoogleApiClient.isConnected() && mLastLocation != null) {
        startIntentService();
    }
    // If GoogleApiClient isn't connected, process the user's request by
    // setting mAddressRequested to true. Later, when GoogleApiClient connects,
    // launch the service to fetch the address. As far as the user is
    // concerned, pressing the Fetch Address button
    // immediately kicks off the process of getting the address.
    mAddressRequested = true;
    updateUIWidgets();
}

当建立到谷歌播放服务的连接,如果用户已经点击了您的应用程序的UI按钮,您还必须启动的意图服务。 下面的代码片段展示了调用startIntentService()方法中onConnected()由谷歌API客户端提供的回调:

public class MainActivity extends ActionBarActivity implements
        ConnectionCallbacks, OnConnectionFailedListener {
    ...
    @Override
    public void onConnected(Bundle connectionHint) {
        // Gets the best and most recent location currently available,
        // which may be null in rare cases when a location is not available.
        mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
                mGoogleApiClient);

        if (mLastLocation != null) {
            // Determine whether a Geocoder is available.
            if (!Geocoder.isPresent()) {
                Toast.makeText(this, R.string.no_geocoder_available,
                        Toast.LENGTH_LONG).show();
                return;
            }

            if (mAddressRequested) {
                startIntentService();
            }
        }
    }
}

获得地理编码结果

这样做的目的服务已处理的地址解析请求,并使用ResultReceiver的结果返回给发出请求的活性。 在发出请求的活动,定义一个AddressResultReceiver延伸ResultReceiver处理从响应FetchAddressIntentService 。

结果包括数字结果代码( resultCode ),以及含有该结果数据的消息( resultData )。 如果反向地理编码过程是成功的,该resultData包含地址。 在出现故障的情况下,该resultData包含描述失败原因文本。 对于可能出现的错误的详细信息,请参阅返回地址给请求者 。

覆盖onReceiveResult()方法来处理结果传递到结果接收器,如下面的代码示例:

public class MainActivity extends ActionBarActivity implements
        ConnectionCallbacks, OnConnectionFailedListener {
    ...
    class AddressResultReceiver extends ResultReceiver {
        public AddressResultReceiver(Handler handler) {
            super(handler);
        }

        @Override
        protected void onReceiveResult(int resultCode, Bundle resultData) {

            // Display the address string
            // or an error message sent from the intent service.
            mAddressOutput = resultData.getString(Constants.RESULT_DATA_KEY);
            displayAddressOutput();

            // Show a toast message if an address was found.
            if (resultCode == Constants.SUCCESS_RESULT) {
                showToast(getString(R.string.address_found));
            }

        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Google Play Services Location:显示位置的地址 的相关文章

随机推荐

  • deepin下linux找不到mysql头文件的解决方法

    在deepin下安装好mysql后 发现在c语言中没有
  • What went wrong: Could not determine the dependencies of task :url_launcher:compileDebugAidl

    运行项目时候出来这个错误 1 先 flutter doctor 如果有错误 按照提示改错误 2 在运行 flutter pub cache repair 上述方法并未完全解决该问题 运行几次后还会出现上述问题 最后我把flutterSDK替
  • 数据库并发技术

    数据库并发技术 并发的提出与问题 并发造成的数据不一致 并发控制技术 封锁 封锁带来的问题与解决策略 并发调度 封锁的粒度 意向锁 并发的提出与问题 并发造成的数据不一致 并发控制技术 封锁 1 排他锁 2 共享锁 封锁带来的问题与解决策略
  • Python3.x 提示 ‘xxx ’is not a registered namespace

    产生问题场景 引入a href标签时显示student没有注册命名空间 解决办法 1 检查项目中的settings文件是否注册了应用名名称 2 在app urls下加上app name from django urls import pat
  • stylegan2 训练终极解决(包括训练环境搭建)

    背景 需要搭建stylegan2训练环境 训练自己的MAT模型 python环境依赖真实烦人 用docker镜像是方案 谚词 懂原理 可灵活搭建 要符合大脑的学习规律 懂了 而且要懂原理 stylegan2官方的github网址 GitHu
  • GO+Selenium批量关注各大网站实战 2 (今日头条,批量关注)

    作为第一个练习 我选择的是今日头条批量关注好友这个功能 今日头条每天关注量有200人限制 满了再点击关注 就会提示已达上限 所以我刷了几天 现在是4600个人 我们先来讲讲思路 1 登录自己的头条号 2 打开头条号的粉丝列表页 3 获取关注
  • HDMI接口协议

    文章目录 背景 一 HDMI简介 1 高清多媒体接口 2 DIV与HDMI 1 DVI接口 2 DVI编码 1 DVI编码时序图 2 DVI编码器示意图 3 HDMI接口 1 接口类型 2 A型接口引脚图 4 HDMI编码机制图 二 TMD
  • C++基础语法——内存管理

    目录 1 C C 中的内存管理 2 C C 中的动态内存管理 C语言的动态内存管理 C 的动态内存管理 操作内置类型 操作自定义类型 3 operator new与operator delete函数 4 new与delete的实现原理 操作
  • 关于idea中maven,pom.xml文件导jar包时没有提示,以及阿里云镜像不能用的解决办法

    最近电脑由于自己改注册表 被自己搞挂了 无奈重新装系统 之前用的idea为2019 3 5版本的 想尝尝新 随整了个2020 1 4版本的 但出现了pom xml文件导jar包没有提示的问题 网上搜的大部分都是这样 点击update按钮更新
  • STM32CubeMX时钟树(72MHZ主频配置)

    目录 一些基础概念 时钟树配置图 第一步 第二步 这里我只是配置常用的72MHZ主频 很多时候新手都在时钟树这里被劝退了 其实不知道没关系 我用STM32这么久了 也只知道大概 我们绝大多数时候不需要配置这个时钟 记住72MHZ主频配置即可
  • Bayer模型的颜色插值算法

    图像采集的功能一般用CCD和CMOS传感器来实现 但是这两种图像传感器在一个像素上只能采集 RGB颜色的一个分量 为了获得最佳的图像效果 需要3个图像传感器分别采集不同的颜色分量 但考虑 到产品的成本及设计复杂度 通常的数字成像设备用一个传
  • ​JVM第五讲 JVM内存结构

    JDK体系结构 Java语言的跨平台特性 JVM整体结构及内存模型 在minor gc过程中对象挪动后 引用如何修改 对象在堆内部挪动的过程其实是复制 原有区域对象还在 一般不直接清理 JVM内部清理过程只是将对象分配指针移动到区域的头位置
  • robot framework 使用三:他们主动浏览器的兼容性

    robot framework 浏览器兼容性测试 上图中黄色圈的地方默认什么都不写 是firefox浏览器 写上ie就是ie浏览器了 firefox最新版本号即可 ie须要设置 1 IE选项设置的安全页中 4个区域的启用保护模式的勾选都勾上
  • ARTS挑战打卡第十六周

    Algorithm 一周至少一道算法题 Review 阅读并点评至少一篇英文技术文章 Tip 学习至少一个技术技巧 总结和归纳在日常工作中所遇到的知识点 Share 分享一篇有观点和思考的技术文章 01 Algorthm https lee
  • 用java写个管理系统

    如果要用 Java 写一个管理系统 可以这样做 首先 确定管理系统的功能 然后设计系统的数据结构和架构 这可以通过绘制 UML 类图或流程图来完成 安装 Java 开发工具包 JDK 和集成开发环境 IDE 比如 Eclipse 或 Int
  • python报错:RuntimeError

    python报错 RuntimeError fails to pass a sanity check due to a bug in the windows runtime这种类型的错误 这种错误原因 1 当前的python与numpy版本
  • Gradle项目运行报错Could not find method XXX及解决方案

    Could not find method testCompile for arguments dependencies testCompile group junit name junit version 4 13 1 原因是较新版的gr
  • 计算机截屏窗口快捷键,电脑截屏的快捷键是什么

    电脑截屏的快捷键是什么 截屏是一种截取图片或文字的途径 也是一种计算机运用技术 通过这种技术可以从网上截取下自己感兴趣的文章图片供自己使用观看 可以帮助人们更好的去理解使用知识 是一种人人都能使用并且学会方法 可以通过一些软件实现截屏功能
  • XSS-Game level 7

    第七关过滤了 script 但未过滤尖括号 lt gt 使用双写绕过 源码中过滤了大小写 script 以及一些属性 并将参数拼接到 value 值 使用 htmlspecialchars 过滤标签 但未重新赋值给 str 所以不会产生影响
  • Google Play Services Location:显示位置的地址

    在前面的blog中讲述了怎样获取最后已知位置和接收位置更新后如何从location对象中获取用户的位置 包含经纬度的坐标 虽然纬度和经度是用于计算距离或显示地图的位置 在许多情况下 位置的地址是更为有用的 例如 如果你想让你的用户知道他们是