模块8: 根据定位获取天气

1. 基于位置的服务

基于位置的服务(Location Based Service, LBS)广泛运用于移动设备,成为移动互联网应用区别于普通互联网应用的重要特色之一。
定位技术是LBS的基础技术,用以获取设备当前所在的地理位置(通常以经纬度来表示)。
在定位技术的基础上,提供LBS服务的厂商还需要采集和提供巨量的服务数据,如地理信息、社会服务位置等等。用户通过定位,即可从服务提供商那里

高德地图: 驾车路线
饿了么: 周边美食

2. 地理信息开放平台

许多厂商提供地图、位置等相关的开放平台编程接口。通过申请这些开放平台的SDK嵌入到应用项目中,普通开发者也可以设计、实现自己的LBS应用。

高德地图开放平台
百度地图开放平台

3. 申请地图开放平台服务

申请开放平台服务我们并不陌生。在前面的课程里我们已经通过“和风天气”开放平台的服务为iWeather应用获取到了天气数据。地图开放平台服务的申请大同小异,首先注册账号,然后注册需要定位服务的App,最后获取APP Key和SDK(开发包)。
以高德地图开放平台为例(https://lbs.amap.com),注册完毕后信息如下:

高德开放平台应用管理页面

从图中可以看到,iWeather应用已经注册成功,App Key如下:

c81a94b41cc152bac3a8ae23a9413717

同时,我们可以从高德平台提供的文档中找到定位功能相关开发包的导入方法:

表中最后一项即为定位功能对应的开发包,只是根据Android Studio最新版本的要求,格式上略有不同,写作:

implementation 'com.amap.api:location:latest.integration'

3. 定位服务开发包导入

在开始编写程序,需要对我们的项目做一些准备工作:

  • 嵌入AppKey:没有这个Key,高德将不会发送定位数据
  • 导入开发包
  • 声明所需要的权限
  • 导入高德定位服务组件com.amap.api.location.APSService

3.1 嵌入App Key

进入AndroidManifest.xml文件,在<application> ... </application>范围内部增加一条表示Key的<meta-data>标签如下:

        <meta-data android:name="com.amap.api.v2.apikey"
            android:value="c81a94b41cc152bac3a8ae23a9413717"/>

注意这个"amap",它是高德地图的英文名字。

3.2 导入开发包

进入app/build.gradle,找到我们之前导入其它模块的dependencies { ... }区域,在其中添加导入语句:

        implementation 'com.amap.api:location:latest.integration'

3.3 声明权限

用户设备所在位置、定位的精确程度等等都需要用户赋予权限,否则系统将禁止使用。在AndroidManifest.xml中已有的权限声明位置增加新的权限声明:

<!--用于进行网络定位-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
<!--用于访问GPS定位-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
<!--用于获取运营商信息,用于支持提供运营商信息相关的接口-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
<!--用于访问wifi网络信息,wifi信息会用于进行网络定位-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
<!--用于获取wifi的获取权限,wifi信息会用来进行网络定位-->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>
<!--用于访问网络,网络定位需要上网-->
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<!--用于读取手机当前的状态-->
<uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
<!--用于写入缓存数据到扩展存储卡-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<!--用于申请调用A-GPS模块-->
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"></uses-permission>
<!--用于申请获取蓝牙信息进行室内定位-->
<uses-permission android:name="android.permission.BLUETOOTH"></uses-permission>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"></uses-permission>

运行一下程序查看效果。目前只是对程序做出了一定的配置,没有编写实际的代码,因此这里运行只是保证前期工作没有引入错误。

3.4 导入定位服务组件

高德的定位服务通过一个Android Service组件来完成发起定位、位置获取以及结束定位等工作。同Activity类似,Service组件也需要在AndroidManifest.xml文件中声明之后才能使用。

进入AndroidManifest.xml文件,在<application> ... </application>范围内部增加对com.amap.api.location.APSService的声明:

        <service android:name="com.amap.api.location.APSService" />

4. 实现位置的获取

现在编写代码,调用高德的定位接口来获取当前设备所在的经纬度。

定位程序编写一般都遵循如下的步骤:

  • 启动定位服务:通过AMapLocationClient对象配置定位参数,然后启动定位。定位服务将按照设定的时间间隔持续的报告当前位置。
  • 监听位置变化:通过定义AMapLocationListener监听器对象并注册到client。每当定位服务报告位置信息,监听器即被通知到。通过编写监听器代码,就可使实现对定位数据的应用了。

4.1 定义位置客户端和监听器对象

首先在MainActivity类中定义一个AMapLocationClient类型的成员mLocationClient

然后定义位置监听器成员mLocationListener

4.2 启动定位

启动定位服务代码较多,因此这里专门为这个过程定义一个名为initLocation()的私有方法并在onCreate()末尾调用它:

然后为initLocation()方法编写代码。

  • 第一步:初始化mLocationClient成员并设置监听器:

    创建对象并关联监听器

  • 第二步:设置定位参数
    开发者可以对定位服务的一些选项进行定制。具体的是创建一个AMapLocationClientOption类的对象,然后为它设置若干参数,最后将其关联到定位客户端对象mLocationClient

AMapLocationClientOption的意思就是“高德定位客户端选项”

我们根据需求做如下设置:
a. 选择使用高精度定位。
b. 每10秒钟报告一次位置
c. 允许模拟定位(模拟器调试无法真正的获取定位数据)

具体操作如下:

设置定位参数
  • 启动定位服务

最终,通过定位客户端对象mLocationClient启动定位。

这里有个技巧性的做法,在启动定位之前先强制停止一次,以防意外。

启动定位

4.3 监听定位数据

前面设置了每10秒报告一次定位数据。我们将来要通过这个定位数据去获取对应位置的天气。我们先暂时简单的通过日志来展示得到的定位数据。
在监听器对象mLocationListeneronLocationChanged()方法中编写代码。该方法的参数aMapLocation即封装了每次报告的定位数据:

  • 读取经度和纬度:
  • 输出日志:


运行程序,并在屏幕下方视图中切换至“Logcat”标签页,设置筛选标记为“iWeather”的日志如图:

可以看到获取到的经纬度都是0,说明定位失败。我们还需要配置一下运行环境。

4.4 配置运行环境

由于虚拟设备本身不具备真正的定位部件,所以我们需要设置模拟定位,使高德定位服务能够获取到一个我们指定的位置。另外,我们要在手机模拟器上设置应用程序权限,使系统允许iWeather获取定位。

  • 开启定位权限
    退回手机桌面,在App列表中选择“Settings”,然后依次选择“Apps & notifications” -> “爱天气” -> “Permissions”,将看到如下的App权限设置页面:

将其中的几个选项全部打开:

  • 设置模拟定位
    点击模拟器面板最下方的“...”按钮:

进入设置对话框,选择左侧选项列表第一项,在右侧出现的定位设置面板中,将“Latitude”(纬度)和“Longitude”(经度)两项设置成如下数值(北京后海附近):

Latitude: 39.93497349279733
Longitude: 116.3912593266754

如图:

点击“Send”按钮,关闭对话框。
退出并再次运行iWeather,查看日志。如果不出意外,应当可以在日志中看到刚才设置的经纬度了:

2019-06-04 14:52:28.130 7612-7612/com.dmtech.iw D/iWeather: 当前位置:0.0, 0.0
2019-06-04 14:52:34.268 7612-7612/com.dmtech.iw D/iWeather: 当前位置:116.39750217013889, 39.936375054253475
2019-06-04 14:52:34.392 7612-7612/com.dmtech.iw D/iWeather: 当前位置:116.39750217013889, 39.936375054253475
2019-06-04 14:52:36.199 7612-9496/com.dmtech.iw D/iWeather: Request: https://free-api.heweather.net/s6/weather?location=CN101010800&key=d2ae781d61744d65a2ef2156eef2cb64
2019-06-04 14:52:36.250 7612-7612/com.dmtech.iw D/iWeather: 当前位置:116.39750217013889, 39.936375054253475
2019-06-04 14:52:36.421 7612-9496/com.dmtech.iw D/iWeather: Request: https://free-api.heweather.net/s6/weather?location=CN101131012&key=d2ae781d61744d65a2ef2156eef2cb64
2019-06-04 14:52:36.538 7612-9496/com.dmtech.iw D/iWeather: Request: https://free-api.heweather.net/s6/weather?location=CN101310304&key=d2ae781d61744d65a2ef2156eef2cb64
2019-06-04 14:52:36.661 7612-9496/com.dmtech.iw D/iWeather: Request: https://free-api.heweather.net/s6/weather?location=US3290097&key=d2ae781d61744d65a2ef2156eef2cb64
2019-06-04 14:52:36.774 7612-9496/com.dmtech.iw D/iWeather: Request: https://free-api.heweather.net/s6/weather?location=AU2147714&key=d2ae781d61744d65a2ef2156eef2cb64

4.5 增加实时位置的天气

只要把定位服务提供的位置信息加入到我们的天气队列中,即可从天气服务平台获取该位置的天气。

  • 在位置列表数组LOCATION_IDS最前面添加一个位置,令其固定的表示实时定位的到的位置。默认设置为下图的值(天安门):
  • 根据实时位置改写位置列表第一项

修改位置监听器对象mLocationListener的代码,用当前得到的经纬度值拼接成新的字符串,替代位置列表数组LOCATION_IDS的第一项。然后,重新执行获取天气数据的异步任务:

4.6 使用更具体的地址信息

我们在获取天气数据的同时能够得到对应的地址信息并显示在主页面的标题栏。但是天气平台提供的地址(区级)不如高德地图给出的定位具体(街道)。我们来尝试在显示实时位置天气页面时用后者替代前者,即当显示天气数据中第0个的时候,采用高德定位得到的地址信息。

首先增加一个AMapLocation类的成员mLocation

修改位置监听器对象mLocationListener的代码,将mLocation设置为当前报告的位置:

找到实现设置标题栏地址信息的函数setTitleAddress()

对绿线标出的这一行代码进行改写,使其进行判断:

  • 如果当前页面顺序为0,则使用定位得到的地址
  • 否则使用天气数据中的地址

代码如下:

运行程序,等待一段时间,即可看到如下的效果:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,602评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,442评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,878评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,306评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,330评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,071评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,382评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,006评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,512评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,965评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,094评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,732评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,283评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,286评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,512评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,536评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,828评论 2 345

推荐阅读更多精彩内容