使用手机的 GPS 功能

关键技能  &  概念
●  使用 Android 的定位服务 APIs
●  从 GPS 硬件获得坐标数据
●  改变活动的外观并且和 RelativeLayout 接触
●  使用一个 MapView 来绘制你的当前位置
●  使用谷歌地图来找到你的当前位置
在本章中,你将学习关于 Android 定位的 API。本章的作用是非常重要的,如果
你想要让 Android 和 GPS 硬件一起工作的话。你将使用位置基础的 API 来收集你
当前的位置并把它在屏幕上显示出来。到本章的结尾,你将在手机上使用谷歌地
图来显示你的当前位置。
你还会学习到一些关于活动的更深,创新的技巧。资源,如 RelativeLayouts
和小按钮将允许你创建更友好,可视的活动。第一节,你将学习使用设备的 GPS
硬件来获得当前的位置。但是,在跳到那个部分之前,你需要先创建一个项目。
在 Eclipse 中创建一个项目并命名为 AndroidLBS。
使用 Android 位置基础 API
Android  SDK 包含了一个 API,它被定制为帮助接口活动与设备上任何的 GPS 硬
件。这章假定你的设备包含 GPS 硬件。
警告
Android 平台的手机不要求包含一个照相机,也不要求包含 GPS 硬件,虽然很多
的型号可能包含照相机和 GPS 硬件。Android 包含了 Android 位置基础 API 预期
GPS 硬件会被包含在很多手机上。
因为你工作在一个软件模拟器中,并且不是一个真的设备,GPS 硬件没有被模拟 。
在本例中,Android 在 adb 服务器中提供了一个文件模拟 GPS 硬件。这个文件放
置在 data/misc/location/<provider> , <provider> 代表 位置 信 息提 供 者。
Android 提供的<provider>是 data/misc/location/gps
提示
你可以有多重的提供者来模拟不同的方案。因此,你可以创建一个提供者为 test
或者 gps1;无论你愿意用哪个。在具体的 provider 的文件夹内可以用任何数量
的文件保留你想要 Android 使用的例子。当你使用 Android 模拟器,你可以使用
下面类型的文件来储存/找回 GPS 文体的坐标。每一个文件类型有个不同的格式
来提供信息给 Android 位置基础 API
●  kml
●  nmea
●  track
我们来看看每一个文件都做些什么并且互相之间有什么不同。
创建一个 kml 文件114
一个.kml 文件 Keyhole  Markup 语言文件。这些文件通常被开发用于并且可以被
Google  Earth(一款 Google 软件)。Adnroid 位置基础 API 可以分析一个.kml
文件来模拟一个 GPS。
注意
假如你没有 Google  Earth。可以从 Google 免费下载。如果你想要开发更多的
Android 位置基础 API 活动,安装这个软件是值得的。
要从 Google  Earth 创建一个.kml 文件,打开 Google  Earth 并且导航到一个位
置。选择文件|另存为并选择 KML。在本例中,它为你所导航到的地点产生一
个.kml 文件。下面的.kml 代码就是来自这个文件。仔细看看<coordinates>标签 ,
那就是 Android 位置基础 API 会读取的。
<?xml  version="1.0"  encoding="UTF-8"?>
<kml  xmlns="http://earth.google.com/kml/2.2">
<Document>
<name>Tampa,  FL.kml</name>
<Styleid="default+icon=http://maps.google.com/mapfiles/kml/pal3/icon52.png">
<IconStyle>
<scale>1.1</scale>
<Icon>
<href>http://maps.google.com/mapfiles/kml/pal3/icon52.png</href>
</Icon>
</IconStyle>
<LabelStyle>
<scale>1.1</scale>
</LabelStyle>
</Style>
<Styleid="default+icon=http://maps.google.com/mapfiles/kml/pal3/icon60.png">
<IconStyle>
<Icon>
<href>http://maps.google.com/mapfiles/kml/pal3/icon60.png</href>
</Icon>
</IconStyle>
</Style>
<StyleMapid="default+nicon=http://maps.google.com/mapfiles/kml/pal3/
icon60.png+hicon=http://maps.google.com/mapfiles/kml/pal3/icon52.png">
<Pair>
<key>normal</key>
<styleUrl>#default+icon=http://maps.google.com/mapfiles/kml/pal3/
icon60.png</styleUrl>
</Pair>
<Pair>
<key>highlight</key>115
你可以用 Google  Earth 来创建自己的.kml 文件来模拟不同的位置。当你想要制
作一个相应用户不同位置的活动时,这个非常有用。创建.kml 文件如此简单使
得模拟 GPS 硬件非常的灵活。
什么是轨迹文件
什么是轨迹文件  第九章(2)  (2)  (2)  (2)
Android 提供的在 gps 文件夹里的文件是一个.nmea 文件(国家海事电子协会文
件)。一个.nmea 文件可以从任何通用的 GPS 产品中输出。这些文件是常用格式
并且可以包含多重坐标和海拔,来表现行程和轨迹。下面的部分讨论并且在
Windows 和 Linux 下各自打开这个文件。
在 Windows 中得到 nmea 文件
Android 提供的 nmea 文件展示了一个贯穿旧金山的短的线路。让我们看看 nmea
文件的内部。使用 adb 工具把文件从服务器中 pull 到你的桌面:
adb  pull<远程文件><本地文件>
<styleUrl>#default+icon=http://maps.google.com/mapfiles/kml/pal3/
icon52.png</styleUrl>
</Pair>
</StyleMap>
<Placemark>
<name>Tampa,  FL</name>
<open>1</open>
<address>Tampa,  FL</address>
<LookAt>
<longitude>-82.451142</longitude>
<latitude>27.98146</latitude>
<altitude>0</altitude>
<range>38427.828125</range>
<tilt>0</tilt>
<heading>0</heading>
</LookAt>
<styleUrl>#default+nicon=http://maps.google.com/mapfiles/kml/pal3/
icon60.png+hicon=http://maps.google.com/mapfiles/kml/pal3/icon52.png</styleUrl>
<Point>
<coordinates>-82.451142,27.98146,0</coordinates>
</Point>
</Placemark>
</Document>
</kml>116
下面的插图描述使用 adb 工具 pull 命令来检索文件(略)。如果命令执行成功,
你应当看到一条消息指示文件下载的大小。导航到  C:\Android  文件夹,你可以
看到 adb  pull 工具放在这里。
现在 nmea 文件在桌面上,把它与 Notepad 关联。最后打开它来看看它的内容。
你会看到很多的坐标数据。
在 Linux 中得到 nmea 文件
如果你在使用 Linux 开发 Android,启动一个终端部分来进入 adb 服务器。让我
们来看看如何在 Linux 中检索并且编辑 nmea 文件。
注意(和插图有关,略)
第 一 步 是 打 开 一 个 新 的 终 端 部 分    (Applications   |  System   Tools   |
Terminal)。
下一步,使用 adb  pull 命令来 pull  nmea 文件到 Android 文件夹:
adb  pull  data/misc/location/gps/nmea  Android/
如果你读了关于 Windows 如何得到 nmea 文件的说明,你会发现语法上的不同。C:\
是没有必要的因为路径结构的不同。
从终端中执行了命令后,结果应当如下所示:
使用 Is 命令来在 Android 文件夹中列出文件。如果命令执行正确,nmea 文件应
当出现。我使用 Fedora  GUI 来导航并且使用系统的 Text  Editor 打开它。
提示
你也可以使用 vi 编辑器从命令行来打开,读取并且编辑 nmea 文件。
现在你已经查看了 nmea 文件并且知道模拟一个 GPS 设备的不同方式,你可以开
始来使用 Android 位置基础 API 来创建一个完整特性的活动了。
使用 Android 位置基础 API 读取 GPS
使用 Android         Android         Android         Android 位置基础 API  API  API  API 读取 GPS  GPS  GPS  GPS 第九章(3)  (3)  (3)  (3)
本章剩下的部分是致力于建造一个活动,AndroidLBS,它会从服务器中 nmea 文
件中识别用户的位置。本活动的第一个过程非常的简单。
你会创建一个简单的过程,该过程会得到用户当前的 GPS 位置。然后你可以在屏
幕上显示这个位置的坐标。在做这个的时候,你会了解到一个对 Android 位置基
础 API 比较到位的介绍和它的功用。
创建 AndroidLBS 活动
下面是创建这个简单活动的步骤:117
1.调整许可的权限
2.创建活动的布局
3.书写代码来允许活动。
4.运行活动。
调整许可的权限
使用 Android 位置基础 API 是调整认可的权限。使用 Android 位置基础本身不要
求任何特别的许可。但是在 GPS 使用 Android 位置基础来存取位置信息需要。
从 Eclipse 中有两种方式可以设置许可。第一个是通过 Android  Manifest 许可
向导,这个你在第七章用过。在 Eclipse 中,双击 AndroidManifest.xml 来打开
Android  Manifest  综 览 窗 口 。 点 击 许 可 链 接 并 使 用 第 七 章 的 方 法 增 加
ACCESS_GPS  和  ACCESS_LOCATION  使用许可。
第二种方法是,你可以手动编辑 AndroidManifest.xml 文件增加许可值到活动
中。你会需要下面的代码行到 AndroidManifest.xml 中:
这里的语句是用来在<uses-permission>标签中增加许可名称。
当你结束了增加许可,你的 AndroidManifest.xml 文件应当像下面的代码片段。
这样的代码应当非常的熟悉了。你在 Intent 过滤器内使用了一个活动和一对许
可。
创建你的布局
<uses-permission  android:name="android.permission.ACCESS_GPS">
</uses-permission>
<uses-permission  android:name="android.permission.ACCESS_LOCATION">
</uses-permission>
<?xml  version="1.0"  encoding="utf-8"?>
<manifest  xmlns:android=http://schemas.android.com/apk/res/android
package="android_programmers_guide.AndroidLBS">
<application  android:icon="@drawable/icon">
<activity  android:name=".AndroidLBS"
android:label="@string/app_name">
<intent-filter>
<action  android:name="android.intent.action.MAIN"  />
<category  android:name="android.intent.category.LAUNCHER"  />
</intent-filter>
</activity>
</application>
<uses-permission  android:name="android.permission.ACCESS_GPS">
</uses-permission><uses-permission
android:name="android.permission.ACCESS_LOCATION">
</uses-permission></manifest>118
要开始创建布局,在 Eclipse 中打开 main.xml,你会一共增加一个按钮和 4 个
TextViews 到布局中。按钮可以从 GPS 呼叫信息并显示到 TextViews 中。
按照下面设置按钮,也就是在屏幕的顶部并使用“Where  am  I”作为显示文本。
下一步,设置 4 个 Texviews,你应当在布局中安排它们,2 个 TextViews 会显示
在另外 2 个 TextViews 之上。这样可以把其中的 2 个作为另外 2 个的标签来使用 。
要完成这个工作,你需要多两个 LinearLayouts.
请注意在 main.xml 文件中的所有元素是包含在一个 LinearLayout 标签中。这个
标签用某些规则来绑定内含的元素。对于 LinearLayouts,元素被以依次水平或
者垂直的方乡堆栈。
LinerLayout 的方向由 android:orientation 属性管理。假如属性没有被赋值,
初始的设定是水平方式。
请注意,有一些槽(或者架子)是垂直放置的。你可以在屏幕上的这些槽上放置
元素。总之,如果你要在立式 LinearLayout 布局的同一个架子上放置少量的条
目,你需要先在架子上放置一个水平的 LinearLayout。
现在你可以上下左右的码放这些元素了。这是个在本活动中需要利用的概念。因
此,在按钮的下面,增加一个水平的 LinearLayout 来放置 2 个 TextViews。
<Button
android:id="@+id/gpsButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Where  Am  I"
/>
<LinearLayout  xmlns:android=http://schemas.android.com/apk/res/android
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<TextView
android:id="@+id/latLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Latitude:  "
/>
<TextView
android:id="@+id/latText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
Figure  9-2  Vertical  LinearLayout  with  embedded  horizontal  LinearLayout
Horizontal  LinearLayout
Android  screen
/>119
这两个 TextViews 保留标签和你将要从 GPS 中采集的纬度数据。下一个,增加另
一个水平 LinearLayout 来保留剩下的 TextViews:
这个为特定的活动提供了比较好的布局。你完成的 main.xml 文件应当如下:
</LinearLayout>
<LinearLayout  xmlns:android=http://schemas.android.com/apk/res/android
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<TextView
android:id="@+id/lngLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Longitude:  "
/>
<TextView
android:id="@+id/lngText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
<?xml  version="1.0"  encoding="utf-8"?>
<LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<Button
android:id="@+id/gpsButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Where  Am  I"
/>
<LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<TextView
android:id="@+id/latLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Latitude:  "120
书写代码来允许活动
书写代码来允许活动  第九章(4)  (4)  (4)  (4)
现在已经创建了布局,你可以开始写代码来允许活动了。你的按钮需要从 GPS
中来呼叫用户当前的位置。一旦你有了这些信息,你可以发送纬度和经度坐标到
TextViews 中了。
首先,你需要增加输入声明。你需要输入 4 个包装:
和一个 Android 位置基础 API:
下一步,为按钮创建代码。目标是从 GPS 中检索当前坐标信息。你已经在本书中
创建了一些按钮了,而且这个的格式没有不同。你需要设置按钮并且从 main.xml
/>
<TextView
android:id="@+id/latText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
<LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<TextView
android:id="@+id/lngLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Longitude:  "
/>
<TextView
android:id="@+id/lngText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
</LinearLayout>
import  android.view.View;
import  android.widget.TextView;
import  android.content.Context;
import  android.widget.Button;
import  android.location.LocationManager;121
中装载布局。然后你可以设置 onClick 事件来呼叫一个函数,LoadCoords()。
创建活动的最后步骤是填充代码到 LoadCoords()函数中。创建 TextViews 需要
接受坐标数据:
注意
你没必要必须创建两个 TextViews 来作为标签,因为你不会发送任何东西到它
们。
现在,创建一个可以 pull 坐标数据的 LocationManager。这个示例的重要部分
是你必须要传递给 LocationManager 一个上下文;使用 LOCATION_SERVICE:
要从 myManager 中 pull 坐标,使用 getCurrentLocation()方法。这个方法需要
一个参数,一个提供者,它们会展示 API 将要从中 pull 的坐标。在这种情况下,
Android 提供了一个本章早些时候讨论过的包含 nmea 文件的模拟位置 GPS:
最后,拿去双击数据并且把它们传递到 TextViews:
final  Button  gpsButton  =  (Button)  findViewById(R.id.gpsButton);
gpsButton.setOnClickListener(new  Button.OnClickListener()  {
public  void  onClick(View  v){
LoadCoords();
}});
TextView  latText  =  (TextView)  findViewById(R.id.latText);
TextView  lngText  =  (TextView)  findViewById(R.id.lngText);
LocationManager  myManager  =
(LocationManager)getSystemService(Context.LOCATION_SERVICE);
Double  latPoint  =  myManager.getCurrentLocation("gps").getLatitude();
Double  lngPoint  =  myManager.getCurrentLocation("gps").getLongitude();
latText.setText(latPoint.toString());
lngText.setText(lngPoint.toString());
Your  finished  code  should  look  like  this:
package  android_programmers_guide.AndroidLBS;
import  android.app.Activity;
import  android.os.Bundle;
import  android.location.LocationManager;
import  android.view.View;
import  android.widget.TextView;
import  android.content.Context;
import  android.widget.Button;
public  class  AndroidLBS  extends  Activity  {
/**  Called  when  the  activity  is  first  created.  */
@Override
public  void  onCreate(Bundle  icicle)  {122
运行活动
在 Android 模拟器中运行你的活动。该活动将会打开如下的屏幕(略)。点击
“Where  Am  I”按钮。你将会看到图片中显示的坐标。
传递坐标到 Google 地图
传递坐标到 Google       Google       Google       Google 地图  第九章(5)  (5)  (5)  (5)
在本节中,你将继续在前一节的基础上构造。对 AndroidLBS 活动的主要修改就
是传递坐标到 Google 地图中。你将使用 Google 地图来显示用户的当前位置。在
main.xml 文件中的唯一修改指出就是为 MpaView 增加一个布局。在目前版本的
Android  SDK 中,MapView 被建立为一个类 View。可能在将来的版本中 MapView
会相当于这个布局。
完成后的 main.xml 文件应当像这样:
super.onCreate(icicle);
setContentView(R.layout.main);
final  Button  gpsButton  =  (Button)  findViewById(R.id.gpsButton);
gpsButton.setOnClickListener(new  Button.OnClickListener()  {
public  void  onClick(View  v){
LoadCoords();
}});
}
public  void  LoadCoords(){
TextView  latText  =  (TextView)  findViewById(R.id.latText);
TextView  lngText  =  (TextView)  findViewById(R.id.lngText);
LocationManager  myManager  =  (LocationManager)
getSystemService(Context.LOCATION_SERVICE);
Double  latPoint  =  myManager.getCurrentLocation("gps").getLatitude();
Double  lngPoint  =  myManager.getCurrentLocation("gps").getLongitude();
latText.setText(latPoint.toString());
lngText.setText(lngPoint.toString());
}
}
<view  class="com.google.android.maps.MapView"
android:id="@+id/myMap"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<?xml  version="1.0"  encoding="utf-8"?>
<LinearLayout  xmlns:android=http://schemas.android.com/apk/res/android
android:orientation="vertical"
android:layout_width="fill_parent"123
android:layout_height="fill_parent"
>
<Button
android:id="@+id/gpsButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Where  Am  I"
/>
<LinearLayout  xmlns:android=http://schemas.android.com/apk/res/android
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<TextView
android:id="@+id/latLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Latitude:  "
/>
<TextView
android:id="@+id/latText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
<LinearLayout  xmlns:android=http://schemas.android.com/apk/res/android
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<TextView
android:id="@+id/lngLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Longitude:  "
/>
<TextView
android:id="@+id/lngText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
<view  class="com.google.android.maps.MapView"
android:id="@+id/myMap"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>124
因为在这个活动中嵌入 MapView,你需要改变类的定义。现在,主要类扩展了活
动。但是要正确的使用 Google  MapView,你必须扩展 MapActivity。因此,你需
要输入 MapActivity 包装并且替换在头部的 Activity  包装。
输入下列包装:
Point 包装将被用于保留 point 的值,它就是展示地图坐标的,而 MapController
将你的 point 置于地图中央。这两个包装在使用 MapView 时非常的关键。
现在准备增加建立地图并传递坐标的代码。首先,设置一个一个 MapView,并且
从 main.xml 文件中把它赋值到布局:
下一步,设置一个 Point 并且把从 GPS 检索的数值赋值给 latPoint 和 IngPoint:
现在,可以创建 MapController 了,它将被用于移动 Google 地图来定位你定义
的 Point。从 MapView 使用 getController()方法在定制的地图中建立一个控制
器:
唯一剩下的工作就是使用控制器来移动地图到你的位置(要让地图更容易辨认,
把 zoom 设定为 9):
你刚才所写的所有代码就是从活动中利用 Google 地图。完整的类应当像这样:
</LinearLayout>
import  com.google.android.maps.MapActivity;
import  com.google.android.maps.MapView;
import  com.google.android.maps.Point;
import  com.google.android.maps.MapController
MapView  myMap  =  (MapView)  findViewById(R.id.myMap);
Point  myLocation  =  new  Point(latPoint.intValue(),lngPoint.intValue());
MapController  myMapController  =  myMap.getController();
myMapController.centerMapTo(myLocation,  false);
myMapController.zoomTo(9);
package  android_programmers_guide.AndroidLBS;
import  android.os.Bundle;
import  android.location.LocationManager;
import  android.view.View;
import  android.widget.TextView;
import  android.content.Context;
import  android.widget.Button;
import  com.google.android.maps.MapActivity;
import  com.google.android.maps.MapView;
import  com.google.android.maps.Point;
import  com.google.android.maps.MapController;125
在模拟器中运行活动。活动应当打开一个空白的地图。点击“Where  Am  I”按钮 ,
应当会看到地图聚焦并且放大到旧金山。看看下图就会知道地图会如何出现
(略)。
增加缩放控制
增加缩放控制  第九章(6)  (6)  (6)  (6)
本章的最后一个练习是再增加两个按钮到 AndroidLBS 活动中。这些按钮将控制
Google  MapView 放大和缩小 的方法 。让这个修改有一点不同的是我将为
main.xml 文件介绍一个布局的新类型:RelativeLayout。LinearLayouts 允许你
直接的一个接一个的放置 Views,RelativeLayouts 允许你在每一个 View 上放置 。
对于这个活动,将会放置两个按钮到 Google  Map 上,要实现这个效果,你可以
public  class  AndroidLBS  extends  MapActivity  {
/**  Called  when  the  activity  is  first  created.  */
@Override
public  void  onCreate(Bundle  icicle)  {
super.onCreate(icicle);
setContentView(R.layout.main);
final  Button  gpsButton  =  (Button)  findViewById(R.id.gpsButton);
gpsButton.setOnClickListener(new  Button.OnClickListener()  {
public  void  onClick(View  v){
LoadProviders();
}});
}
public  void  LoadProviders(){
TextView  latText  =  (TextView)  findViewById(R.id.latText);
TextView  lngText  =  (TextView)  findViewById(R.id.lngText);
LocationManager  myManager  =  (LocationManager)
getSystemService(Context.LOCATION_SERVICE);
Double  latPoint  =
myManager.getCurrentLocation("gps").getLatitude()*1E6;
Double  lngPoint  =
myManager.getCurrentLocation("gps").getLongitude()*1E6;
latText.setText(latPoint.toString());
lngText.setText(lngPoint.toString());
MapView  myMap  =  (MapView)  findViewById(R.id.myMap);
Point  myLocation  =  new  Point(latPoint.intValue(),lngPoint.intValue());
MapController  myMapController  =  myMap.getController();
myMapController.centerMapTo(myLocation,  false);
myMapController.zoomTo(9);
}
}126
增加在地图上的按钮。
现在可以增加另外的两个按钮了。它们会出现在 MapView 的左上方和左下方。你
需要对 Button 布局做一个修改。按照默认的方式,RelativeLayout 增加 Button
来和锚视图顶部的边缘排列,本例中,就是这个 MapView。因此,在这个布局,
使用 android:layout_alignBottom 属性并赋值 MapView 的 id。这样就排列按钮
到地图的底部了。
提示
仔细看一下按钮的布局属性。我使用一个新的属性,style,来把这个按钮改小。
完整的 main.xml 应当看上去像这样:
<RelativeLayout  xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<view  class="com.google.android.maps.MapView"
android:id="@+id/myMap"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
<Button  android:id="@+id/buttonZoomIn"
style="?android:attr/buttonStyleSmall"
android:text="+"
android:layout_width="wrap_content"
android:layout_height="wrap_content"  />
<Button  android:id="@+id/buttonZoomOut"
style="?android:attr/buttonStyleSmall"
android:text="-"
android:layout_alignBottom="@+id/myMap"
android:layout_width="wrap_content"
android:layout_height="wrap_content"  />
<?xml  version="1.0"  encoding="utf-8"?>
<LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<Button
android:id="@+id/gpsButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Where  Am  I"127
/>
<LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<TextView
android:id="@+id/latLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Latitude:  "
/>
<TextView
android:id="@+id/latText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
<LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<TextView
android:id="@+id/lngLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Longitude:  "
/>
<TextView
android:id="@+id/lngText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
<RelativeLayout  xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<view  class="com.google.android.maps.MapView"
android:id="@+id/myMap"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button  android:id="@+id/buttonZoomIn"
style="?android:attr/buttonStyleSmall"128
你会去适当的修改这个代码。除了为新的 views 增加代码之外,你需要移除现存
的一些代码。为了让活动更灵活,你需要移除 MapView 的示例和类主要部分的
MapController。这样将会允许你传递这些项目到其它所需的函数(比如将要创
建的放大和缩小特性)。
现在可以创建两个新按钮的代码了。和你之前创建的按钮一样,增加呼叫到下一
步将要构建的函数:
最后,创建控制放大缩小特性的函数。最大放大位置是 21 并且最小是 1.因 此 ,
在函数中,在调整前测试当前的位置。这样将确保不会出现任何的运行问题。
android:text="+"
android:layout_width="wrap_content"
android:layout_height="wrap_content"  />
<Button  android:id="@+id/buttonZoomOut"
style="?android:attr/buttonStyleSmall"
android:text="-"
android:layout_alignBottom="@+id/myMap"
android:layout_width="wrap_content"
android:layout_height="wrap_content"  />
</RelativeLayout>
</LinearLayout>
final  MapView  myMap  =  (MapView)  findViewById(R.id.myMap);
final  MapController  myMapController  =  myMap.getController();
final  Button  zoomIn  =  (Button)  findViewById(R.id.buttonZoomIn);
zoomIn.setOnClickListener(new  Button.OnClickListener()  {
public  void  onClick(View  v){
ZoomIn(myMap,myMapController);
}});
final  Button  zoomOut  =  (Button)  findViewById(R.id.buttonZoomOut);
zoomOut.setOnClickListener(new  Button.OnClickListener()  {
public  void  onClick(View  v){
ZoomOut(myMap,myMapController);
}});
public  void  ZoomIn(MapView  mv,  MapController  mc){
if(mv.getZoomLevel()!=21){
mc.zoomTo(mv.getZoomLevel()+  1);
}
}
public  void  ZoomOut(MapView  mv,  MapController  mc){
if(mv.getZoomLevel()!=1){
mc.zoomTo(mv.getZoomLevel()-  1);
}129
注意你传递 MapView 和 MapController 到函数中,从那里,对缩放位置进行整数
处理非常简单。唯一的关键是这个函数是 MapController 本身移动 MapView 到希
望的缩放位置,而 MapView 本身保留缩放位置。
提示
想想这个关系和一个遥控器和电视机相类似。遥控器切换电视到第 5 频道,但是
频道本身是储存在电视上的。
你完成的 AndroidLBS.java 文件应当看上去像这样:
}
package  android_programmers_guide.AndroidLBS;
import  android.os.Bundle;
import  android.location.LocationManager;
import  android.view.View;
import  android.widget.TextView;
import  android.content.Context;
import  android.widget.Button;
import  com.google.android.maps.MapActivity;
import  com.google.android.maps.MapView;
import  com.google.android.maps.Point;
import  com.google.android.maps.MapController;
public  class  AndroidLBS  extends  MapActivity  {
/**  Called  when  the  activity  is  first  created.  */
@Override
public  void  onCreate(Bundle  icicle)  {
super.onCreate(icicle);
setContentView(R.layout.main);
final  MapView  myMap  =  (MapView)  findViewById(R.id.myMap);
final  MapController  myMapController  =  myMap.getController();
final  Button  zoomIn  =  (Button)  findViewById(R.id.buttonZoomIn);
zoomIn.setOnClickListener(new  Button.OnClickListener()  {
public  void  onClick(View  v){
ZoomIn(myMap,myMapController);
}});
final  Button  zoomOut  =  (Button)  findViewById(R.id.buttonZoomOut);
zoomOut.setOnClickListener(new  Button.OnClickListener()  {
public  void  onClick(View  v){
ZoomOut(myMap,myMapController);
}});
final  Button  gpsButton  =  (Button)  findViewById(R.id.gpsButton);
gpsButton.setOnClickListener(new  Button.OnClickListener()  {
public  void  onClick(View  v){
LoadProviders(myMap,myMapController);130
在 Android 模拟器中运行这个活动。活动会打开一个新的 MapView,如图所示放
了按钮(略)。
试一下放大和缩小按钮。当你放大,你应当看到和下面类似的图形(略)。
试试这个:在 MapView 之间转换
试试这个:在 MapView         MapView         MapView         MapView 之间转换  第九章(7)  (7)  (7)  (7)
标 准 视 图 和 卫 星 视 图 再 编 辑 AndroidLBS 活 动 一 次 。 再 增 加 两 个 按 钮 到
RelativeLayout。这些按钮可以转换标准视图和卫星视图。下面是需要考虑的地
方:
●  使用排列布局属性使这转换按钮在 MapView 的另外一面。
●  研究 MapView 来找到转换的方式。
●  创建一个可以传递并转换 MapView 的函数。
}});
}
public  void  LoadProviders(MapView  mv,  MapController  mc){
TextView  latText  =  (TextView)  findViewById(R.id.latText);
TextView  lngText  =  (TextView)  findViewById(R.id.lngText);
LocationManager  myManager  =  (LocationManager)
getSystemService(Context.LOCATION_SERVICE);
Double  latPoint  =  myManager.getCurrentLocation("gps").getLatitude()*1E6;
Double  lngPoint  =
myManager.getCurrentLocation("gps").getLongitude()*1E6;
latText.setText(latPoint.toString());
lngText.setText(lngPoint.toString());
Point  myLocation  =  new  Point(latPoint.intValue(),lngPoint.intValue());
mc.centerMapTo(myLocation,  false);
mc.zoomTo(9);
}
public  void  ZoomIn(MapView  mv,  MapController  mc){
if(mv.getZoomLevel()!=21){
mc.zoomTo(mv.getZoomLevel()+  1);
}
}
public  void  ZoomOut(MapView  mv,  MapController  mc){
if(mv.getZoomLevel()!=1){
mc.zoomTo(mv.getZoomLevel()-  1);
}
}
}131
完成的 main.xml 和 AndroidLBS.java 文件应当如下:
main.xml
<?xml  version="1.0"  encoding="utf-8"?>
<LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<Button
android:id="@+id/gpsButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Where  Am  I"
/>
<LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<TextView
android:id="@+id/latLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Latitude:  "
/>
<TextView
android:id="@+id/latText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
<LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<TextView
android:id="@+id/lngLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Longitude:  "
/>
<TextView
android:id="@+id/lngText"
android:layout_width="wrap_content"132
AndroidLBS.java
android:layout_height="wrap_content"
/>
</LinearLayout>
<RelativeLayout  xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<view  class="com.google.android.maps.MapView"
android:id="@+id/myMap"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button  android:id="@+id/buttonZoomIn"
style="?android:attr/buttonStyleSmall"
android:text="+"
android:layout_width="wrap_content"
android:layout_height="wrap_content"  />
<Button  android:id="@+id/buttonMapView"
style="?android:attr/buttonStyleSmall"
android:text="Map"
android:layout_alignRight="@+id/myMap"
android:layout_width="wrap_content"
android:layout_height="wrap_content"  />
<Button  android:id="@+id/buttonSatView"
style="?android:attr/buttonStyleSmall"
android:text="Sat"
android:layout_alignRight="@+id/myMap"
android:layout_alignBottom="@+id/myMap"
android:layout_width="wrap_content"
android:layout_height="wrap_content"  />
<Button  android:id="@+id/buttonZoomOut"
style="?android:attr/buttonStyleSmall"
android:text="-"
android:layout_alignBottom="@+id/myMap"
android:layout_width="wrap_content"
android:layout_height="wrap_content"  />
</RelativeLayout>
</LinearLayout>
package  android_programmers_guide.AndroidLBS;
import  android.os.Bundle;
import  android.location.LocationManager;
import  android.view.View;133
import  android.widget.TextView;
import  android.content.Context;
import  android.widget.Button;
import  com.google.android.maps.MapActivity;
import  com.google.android.maps.MapView;
import  com.google.android.maps.Point;
import  com.google.android.maps.MapController;
public  class  AndroidLBS  extends  MapActivity  {
/**  Called  when  the  activity  is  first  created.  */
@Override
public  void  onCreate(Bundle  icicle)  {
super.onCreate(icicle);
setContentView(R.layout.main);
final  MapView  myMap  =  (MapView)  findViewById(R.id.myMap);
final  MapController  myMapController  =  myMap.getController();
final  Button  zoomIn  =  (Button)  findViewById(R.id.buttonZoomIn);
zoomIn.setOnClickListener(new  Button.OnClickListener()  {
public  void  onClick(View  v){
ZoomIn(myMap,myMapController);
}});
final  Button  zoomOut  =  (Button)  findViewById(R.id.buttonZoomOut);
zoomOut.setOnClickListener(new  Button.OnClickListener()  {
public  void  onClick(View  v){
ZoomOut(myMap,myMapController);
}});
final  Button  gpsButton  =  (Button)  findViewById(R.id.gpsButton);
gpsButton.setOnClickListener(new  Button.OnClickListener()  {
public  void  onClick(View  v){
LoadProviders(myMap,myMapController);
}});
final  Button  viewMap  =  (Button)  findViewById(R.id.buttonMapView);
viewMap.setOnClickListener(new  Button.OnClickListener()  {
public  void  onClick(View  v){
ShowMap(myMap);
}});
final  Button  viewSat  =  (Button)  findViewById(R.id.buttonSatView);
viewSat.setOnClickListener(new  Button.OnClickListener()  {
public  void  onClick(View  v){
ShowSat(myMap);
}});
}
public  void  LoadProviders(MapView  mv,  MapController  mc){
TextView  latText  =  (TextView)  findViewById(R.id.latText);
TextView  lngText  =  (TextView)  findViewById(R.id.lngText);134
当你运行活动时,应当可以启动和关闭卫星视图,如下图(略)。
在下一章,你将进入更深层次的 Google  API。第十章将一步一步学习使用 Google
API 从 Android 手机发送信息到 GTalk。
问专家
Q:最终版本的 Android 还会继续使用.kml 或者.nmea 文件吗?
A:本书写的时候,最终的 Android 还没有发布,可以假定的是,是的,最后版本
的 Android 还会利用.kml 和/或者.nmea 文件。这将允许应用程序开发者在应用
程序内使用包括静态坐标文件。
Q:有没有可能来创建有标记的 Google  Map?
LocationManager  myManager  =  (LocationManager)
getSystemService(Context.LOCATION_SERVICE);
Double  latPoint  =
myManager.getCurrentLocation("gps").getLatitude()*1E6;
Double  lngPoint  =
myManager.getCurrentLocation("gps").getLongitude()*1E6;
latText.setText(latPoint.toString());
lngText.setText(lngPoint.toString());
Point  myLocation  =  new  Point(latPoint.intValue(),lngPoint.intValue());
mc.centerMapTo(myLocation,  false);
mc.zoomTo(9);
}
public  void  ZoomIn(MapView  mv,  MapController  mc){
if(mv.getZoomLevel()!=21){
mc.zoomTo(mv.getZoomLevel()+  1);
}
}
public  void  ZoomOut(MapView  mv,  MapController  mc){
if(mv.getZoomLevel()!=1){
mc.zoomTo(mv.getZoomLevel()-  1);
}
}
public  void  ShowMap(MapView  mv){
if  (mv.isSatellite()){
mv.toggleSatellite();
}
}
public  void  ShowSat(MapView  mv){
if  (!mv.isSatellite()){
mv.toggleSatellite();
}
}
}A:是的,在第十一章,你将学习如何熟练操作 Google  地图  Overlays。这些视
图允许在 Google 地图的上面你绘制文本,标记和其它形状。

22、Android之 使用手机的 GPS 功能相关推荐

  1. 在Android模拟器上怎样模拟GPS功能

    我们都知道,在我们开发时需要在模拟器上模拟GPS,可在Location的时候总是null,上网查了一下,发现如下解决:  网上大侠的解决方案:  在模拟器上获取GPS信息时,使用Location lo ...

  2. 诺基亚手机使用GPS功能费用问题的解释

    诺基亚手机使用GPS功能费用问题的解释   [ 录入者:pub | 时间:2008-10-22 09:53:29 | 作者: | 来源:本站原创 | 浏览:9519次 ] 本文为原创文章,如果您需要转 ...

  3. 【Android App】定位导航GPS中开启手机定位功能讲解及实战(附源码和演示 超详细)

    需要源码请点赞关注收藏后评论区留言私信~~~ 一.开启定位功能 手机定位分为卫星定位和网络定位两大类. (1)卫星定位 卫星定位服务由几个全球卫星导航系统提供. 卫星定位的原理是根据多颗卫星与导航芯片 ...

  4. 教你把gps服务器修改为中国加速搜星,手机导航-GPS搜星速度优化(android手机)...

    提回来4个月,关于导航的问题曾经纠结过很久:弄个一体机吧,贵,安装还麻烦,新地图也麻烦(其实主要是贵...),家里装宽带电信送华为C8812跟华为C8650,一直都是拿这两个手机当导航用,但 ...

  5. android 隐藏功能介绍,安卓手机隐藏的功能介绍,有没有你不知道的?

    前几日就连销声匿迹一段时间的诺基亚手机也发出信号说即将生产安卓系统的手机.由此可见在智能手机市场中安卓手机的地位绝对是不可动摇的.除了苹果系统的手机之外,基本上目前市面的所有手机都是安卓系统,所以我们 ...

  6. gpsone 位置服务器,【图】手机导航-GPS搜星速度优化(android手机)

    小三提回来4个月了,关于导航的问题曾经纠结过很久:弄个一体机吧,贵,安装还麻烦,更新地图也麻烦(其实主要是贵...),家里装宽带电信送了华为C8812跟华为C8650,一直都是拿这两个手机当导航用,但 ...

  7. Android项目:手机安全卫士(7)—— 手机防盗功能

    Android项目:手机安全卫士(7)-- 手机防盗功能 1 介绍 前面已经将手机防盗的界面.业务代码逻辑完成了,现在就是最后的功能实现了,手机防盗主要有这么几个功能: 短信:发送警报短信,接收命令短 ...

  8. Android开发之手机拍照功能的实现(源代码分享)

    Android系统里调用手机拍照的功能有两种方法一种直接调用手机自带的相机另一种就是使用自己做的拍照应用.比如Camera360 一款于各操作系统都有的的功能强大的手机摄影软件:能拍摄出不同风格,不同 ...

  9. 同步android wear音乐,Android Wear首次更新:添加离线音乐 GPS功能等

    凤凰科技讯 北京时间10月24日消息,据科技博客TechCrunch报道,Android Wear日前迎来了其发布后的首次大更新.谷歌为这一可穿戴设备的操作系统添加了离线音乐.蓝牙耳机以及GPS定位等 ...

最新文章

  1. Java基础语法运算和控制符
  2. 用人工智能打击人工智能
  3. asp.net序列化
  4. VMware网络设置详解 打造超级虚拟网络 (说的最为复杂和全面的)
  5. ZYAR20A 亚克力2驱 蓝牙 298寻迹避障机器人 —— 小车前进实验调试
  6. 给sublime设置格式化代码的快捷键
  7. MarkDown之typora
  8. matlab如何实现降维,matlab怎么把矩阵降维
  9. 【bzoj3669】[Noi2014]魔法森林【LCT】
  10. Script component 用法
  11. UDP \TCP详详详详解,你想要的全都有(呕心沥血)
  12. 解决Ajax异步请求中传数组参数,后台无法接收问题
  13. Python-Matplotlib可视化(9)——精通更多实用图形的绘制
  14. 《Core Data应用开发实践指南》一导读
  15. 第三章:数组[4Arrays]
  16. python函数的规则_Python函数的作用域规则和闭包
  17. 基于SpringBoot的图书管理系统
  18. 黑客帝国装逼的代码雨
  19. 档案目录管理--chmod
  20. ZInt支持中文例子

热门文章

  1. 花粉的基本功效(收藏)
  2. 算法学习之——矩形切割思想
  3. [音乐心情]高品位精品音乐:百听不厌的醉人曲调欣赏
  4. wps怎么删除分节符以及段落边框产生分隔线的取消方法
  5. 【洛谷P3386】【模板】二分图匹配【网络流】
  6. 计算机机房内宜配置灭火器,GB/T 9361-2011_计算机场地安全要求(8页)-原创力文档...
  7. ftp文件服务器与nas性能,nas和ftp服务器的区别
  8. 用 Python 快速获取基金持仓增减情况 | 更新版
  9. Golang图片码+压缩伪装+远程调用组合拳
  10. 行逻辑连接的顺序表实现稀疏矩阵乘法