使用手机的 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 地图的上面你绘制文本,标记和其它形状。

更多相关文章

  1. android解析XML文件的三方法之SAX
  2. android文件下载与保存
  3. android 扫描文件(sdcard添加新的音乐文件时候后,可扫描到)
  4. Android stutio 中怎么将XML中文件快速findById——Android Layo
  5. init进程 && 解析Android启动脚本init.rc && 修改它使不启动andr
  6. Android Developers:保存文件
  7. Android中读取assets目录下的文件详细介绍
  8. android studio导入gbk编码的工程文件导致的乱码问题

随机推荐

  1. FregServer进程,封装进程间通信数据
  2. 关于android linux kernel
  3. Android中获得SD卡中的值
  4. Android中获得SD卡中的值
  5. QT Creator 构建android apk失败问题
  6. Android练习—修改背景颜色
  7. Android性能检测--traceview工具各个参数
  8. Android(安卓)示例之 notepad
  9. delphi android 中 Toast 的实现(老外写
  10. android 相机 前后摄像头判断