开发基于 Google Map 的 Android 应用

张 谦, 软件工程师, IBM
吴 校军, 高级软件工程师, IBM
苏 琳, 软件工程师, IBM

简介: 随着移动互联网应用的迅速发展,利用智能手机提供的实时地理位置信息服务功能扩展出众多 LBS(Location Based Service) 应用,将实时地理位置信息与手机的便捷、移动特性结合,为人们提供多种多样的应用场景,比如实时定位、导航、搜索周围好友、基于地理位置的信息推荐等。本文通过实例介绍如何开发基于 Google Map 的 Android 应用。

本文的标签:  开发工具, 移动和嵌入式系统

标记本文!

发布日期: 2012 年 6 月 28 日 
级别: 初级 
访问情况 : 2743 次浏览 
评论: 0 (查看 | 添加评论 - 登录)

 平均分 (1个评分)
为本文评分

概述

本文以实例介绍如何开发基于 Google Map 的 Android 应用,共分为五部分:1. 开发 Android 应用的准备以及 Google Map API 密钥的获取;2. 将 google 地图控件放入 Android 工程中;3. 添加地图缩放组件,以及地图模式,缩放比例的调整;4. 使用 Android 系统提供的地理位置信息的服务获取当前地理位置信息;5. 将当前地理位置信息以图标的方式显示在地图上。

回页首

开发 android 应用的准备

本文将主要介绍如何在 Android 系统上开发基于 Google 地图的应用。在开始阅读这篇文章之前,需要具备基本的 Android 开发的相关知识。读者需要了解如何在 eclipse 开发简单的 android 应用程序,例如 Eclipse IDE 的配置和 Android SDK 的安装。

  • Eclipse IDE(http://www.eclipse.org/downloads/)
  • AndroidSDK(http://developer.android.com/sdk/index.html)

为了开发基于 Google map 的 Android 应用,同时还需要安装 Google APIs Add-on,以及创建包含有 Google API 的 Android 模拟器。

  • Google APIs Add-on(http://code.google.com/android/add-ons/google-apis/installing.html)
  • AndroidVirtual device Targeting Google APIs(http://developer.android.com/guide/developing/devices/index.html)

回页首

获取 Google 地图 API key,以及生成 keyStore 文件

使用 google map 第一步是要获得 google map API 密钥,一个密钥只对一个"目录"或者"域"有效,对于 Google 来说,获取密钥的过程其实也是认证的过程,在你获取密钥时,需要同意 Google 所列出的一些法律条款,所以在你使用获取密钥后,Google 默认你已经同意了其地图使用的条款。

获取密钥的过程可以简单分为两个阶段:

阶段 1:获得 MD5 指纹并创建证书

通过 JDK( 本文中所指的 JDK 均为 Oracle JDK) 中自带的 Keytool.exe 工具来生成证书,Keytool.exe 可以在 %JAVA_HOME%\jdk1.6.0_21\bin 里找到,

图 1. 创建证书

为了开发和调试基于 Google Map 的 Android 应用,我们可以使用在 Android 应用调试模式下的证书 debug.keystore,该文件一般存放在 : %userprofile%/.android/

在笔者的 Windows XP 系统中,该文件的存放路径为

C:\Documents and Settings\Administrator\.android\

将 debug.keystore 文件复制到 Keytool 工具的目录下,然后通过下面的命令来获取证书的 MD5 值 : keytool.exe -list -alias androiddebugkey -keystore debug.keystore -storepass android -keypass android

图 2. 获取证书的 MD5 值

阶段 2:获取 Google Map 的 API 密钥

登陆 http://code.google.com/android/maps-api-signup.html,通过使用之前获得的 MD5 值,来完成 Google Map API 密钥的申请。图 3 为申请成功的截图。

图 3. 申请 Google Map API 密钥界面

回页首

创建一个 Android 工程

  1. 建立新的 Android 工程,并命名为 GoogleMapExample,开发基于 Google Map 的应用需要指定该工程的 build target 为 Google APIs。

    图 4. 创建 Android 工程界面

  2. 开发 Android 应用可以在手机或者模拟器上进行调试,如果使用模拟器进行开发,首先需要创建 Android 模拟器,并且指定该模拟器的 target 为 Google APIs。 

    图 5. 创建 Android 模拟器界面

  3. 设置示例工程的运行环境,确保示例工程运行在包含有 Google API 的目标模拟器上。 

    图 6. 设置示例工程运行环境界面

  4. 在模拟器上运行 GoogleMapExample 示例工程,模拟器应该有如图 7 的输出。自此,开发基于 Google Map 应用的工程就初步搭建起来了,接下来我们一步一步来将地图控件添加进 GoogleMapExample 应用中。 

    图 7. 运行结果界面

回页首

将 Google Map 控件添加到 GoogleMapExample 工程中

首先,在 AndroidManifest.xml 文件中添加对于 Google Map 库的引用。通过使用 uses-library 标签来添加 google map 库到当前应用中。

清单 1. 添加对于 Google Map 库的引用

               <uses-library android:name="com.google.android.maps" />

添加的相应的访问权限:

  • android.permission.ACCESS_COARSE_LOCATION: 允许应用通过网络信息获取当前地理位置信息的权限。
  • android.permission.ACCESS_FINE_LOCATION: 允许应用通过 GPS 获取当前地理位置信息的权限,较网络获得的地理位置信息更为精确。
  • android.permission.INTERNET: 允许应用访问网络的权限。

最终的 AndroidManifest.xml 文件示例如下:

清单 2. AndroidManifest.xml 文件

             <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"   package="com.android.mapExample"android:versionCode="1"android:versionName="1.0"> <uses-sdk android:minSdkVersion="3" />    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <application android:icon="@drawable/icon" android:label="@string/app_name"> <uses-library android:name="com.google.android.maps" /> <activity android:name=".GoogleMapExampleActivity" 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> </manifest>

其次,将 MapView 控件添加进布局文件 main.xml 中,并将 1.3 中获得的 API 填入 MapView 控件的声明中。

清单 3. 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"> <com.google.android.maps.MapView android:id="@+id/mapView"android:layout_width="fill_parent"android:layout_height="fill_parent"android:clickable="true"android:apiKey="0gtIEXVeu0g96nXpxjvByVW9hs7V0mDiuNHRwRw" /> </LinearLayout>

第三,将 GoogleMapExampleActivity 的继承类修改为 MapActivity,并添加 com.google.android.maps.MapActivity包,重写 isRouteDisplayed 方法,由于示例中没有正在显示的路线信息,这里我们返回 false 即可。

清单 4. GoogleMapExampleActivity 类

             public class GoogleMapExampleActivity extends MapActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } @Override protected boolean isRouteDisplayed() { return false; } }

编译并且运行,将会得到如图 8 所示的地图,这时地图控件已经被我们成功的添加进示例工程中了。

图 8. 世界地图界面

回页首

添加缩放控件并控制缩放比例,切换地图显示类型(卫星,地图,街道)

Google 地图 MapView 对象自带有控制缩放比例的组件,我们可以通过调用 MapView 对象的 setBuiltInZoomControls方法来完成添加或者移除缩放控件。

  1. 通过在 layout 文件 main.xml 中的 id 获取找到 MapView 对象

    清单 5. 获取 MapView 对象

                 mapView = (MapView) findViewById(R.id.mapView);
    
  2. 在 mapView 对象上调用 setBuiltInZoomControls 方法,这里传入 boolean 类型的参数,true 和 false 分别表示添加或者移除缩放组件 

    清单 6. 调用 setBuiltInZoomControls 方法

                   mapView.setBuiltInZoomControls(true);
    

需要提到的是,如果添加了缩放控件,它会在第一次触击地图的时候生效,如图 9 所示。

图 9. 地图的缩放控件

通过 MapControl 来控制缩放比例,通过获取 MapView 的 MapControl 对象,控制缩放比例。这里我们设置 16 档为当前缩放大小。

清单 7. 控制缩放比例

                mapController = mapView.getController(); mapController.setZoom(16);

Google 地图缩放比例共分为 21 档,具体的缩放划分可以参考 google 文档,以及链接 http://greg-koppel.site88.net/maps/InfoDisplay.html

切换地图的显示类型,Google 地图提供了三种地图的显示方式,分别为卫星,地图,街道,默认设置为街道模式,这些模式的切换可以通过调用 MapView 对象提供的相应方法来完成切换。

最终的代码示例:

清单 8. 切换地图的显示类型

             @Override public void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState); setContentView(R.layout.main);  mapView = (MapView) findViewById(R.id.mapView);  // 街道模式(默认设置)mapView.setStreetView(true); // 卫星模式//mapView.setSatellite(true); // 是否显示交通信息// mapView.setTraffic(true); mapView.setBuiltInZoomControls(true);  mapController = mapView.getController(); mapController.setZoom(16); }

回页首

获取当前地理位置信息

Android 系统提供的获取地理位置信息的服务,通过该服务开发者不仅可以方便的获取当前 Android 设备的地理位置信息,并且还提供定制地理位置信息获取的方式,位置变化追踪等。

LocationManager,LocationProviders 这两个类在 Android 系统中,提供获取当前地理位置信息的功能。

  • LocationManager: 提供访问 Android 地理信息服务的接口。
  • LocationProvider: 提供多种定位方式供开发者选择(GPS, NETWORK 定位等)。
  • Critieria:设置一系列的查询条件,来获取相应的 Location Provider。

下面通过一个具体的示例来说明,如何获取 Android 系统中最后一次更新的地理位置信息。

  1. 根据应用需求创建 Criteria 对象,设定获取地理位置信息的精度,方向信息等。
  2. 获取当前符合步骤 1 定义的规则最优的 LocationProvider。
  3. 获取 LocationManager 对象来访问 android 系统地理位置信息服务。
  4. 通过 LocationManager 对象提供的方法获取系统最后一次更新的地理位置信息。

示例代码如下:

清单 9. 获取 Android 系统中最后一次更新的地理位置信息

               mapView = (MapView) findViewById(R.id.mapView); private LocationManager locationManager = null; private String bestProvider = null; private String getBestProvider(Context context){ Criteria criteria = new Criteria(); criteria.setAccuracy(Criteria.ACCURACY_COARSE); // 设置精度criteria.setAltitudeRequired(false); // 设置是否需要提供海拔信息criteria.setBearingRequired(false); // 是否需要方向信息criteria.setCostAllowed(false); // 设置找到的 Provider 是否允许产生费用criteria.setPowerRequirement(Criteria.POWER_LOW); // 设置耗电locationManager=(LocationManager)context.getSystemService(Context.LOCATION_SERVICE); String provider=locationManager.getBestProvider(criteria, true); // 这里可能返回 null, 地理位置信息服务未开启return provider; }  public Location getLastKnowLocation(Context context) { Location ret = null; this.bestProvider = getBestProvider(context); if(this.bestProvider != null) { ret = locationManager.getLastKnownLocation(this.bestProvider); } // 这里可能会返回 null, 表示按照当前的查询条件无法获取系统最后一次更新的地理位置信息return ret; }

在实际应用中,这里有两个问题需要特别注意:

一方面,当 Android 设备的地理位置信息服务处于未开启的状态时,通过LocationManager获取的LocationProvider将会返回null,在这里需要提示用户当前地理位置信息服务未开启,否则将会有"java.lang.IllegalArgumentException: provider==null"异常抛出(具体方式请参考附带源代码)

另一方面,由于 getLastKnownLocation方法是一个非阻塞调用方法,例如在设置为GPS方式获取地理位置信息时经常会返回null,通常处理在 getLastKnownLocation中返回值为null的方法有两种:

  1. 设置地理位置信息获取的精度为粗粒度位置信息获取,相对于GPS方式,通过网络信息等方式获取当前位置更容易进行定位。

    清单 10. 设置地理位置信息获取的精度

                  criteria.setAccuracy(Criteria. ACCURACY_COARSE)
    
  2. 通过使用 LocationListener 请求并监听用户地理位置信息的变化

    Step 1. 创建 Location Listener 对象,实现 LocationListener 接口

    Step 2. 使用在 4.1 中初始化的 locationManager 对象请求地理位置信息的更新,并绑定到自己定义的 locationListener 对象

    Step 3. 当 LocationManager获取到有效的地理位置信息时,在 LocationListener 接口定义的 onLocationChanged方法将会被回调,传入参数就是当前获取的位置。

最后需要注意的是,获取到地理位置信息后,以及当前 Activity 生命周期结束时,将 locationListener 在 LocationManager的绑定移除。

清单 11. 监听用户地理位置信息的变化

               private MyLocationListener myLocationListener = null; public class MyLocationListener implements LocationListener { @Override public void onLocationChanged(Location location) { if (location != null) { myLocation = location; mapController.setZoom(16); addMarker(); locationManager.removeUpdates(myLocationListener); } } @Override public void onProviderDisabled(String provider) {} @Override public void onProviderEnabled(String provider) {} @Override public void onStatusChanged(String provider, int status, Bundle extras) {} @Override protected void onPause() { super.onPause(); } @Override protected void onResume() { super.onResume(); myLocation = getLastKnowLocation(this); if(myLocation == null) { if(this.bestProvider != null){ locationManager.requestLocationUpdates(LocationManager. GPS_PROVIDER, 1000, 0, myLocationListener); } } else { addMarker(); } } @Override protected void onDestroy() { super.onDestroy(); locationManager.removeUpdates(myLocationListener); }

回页首

在地图上添加当前位置的图标

在地图上添加图标是地图应用时必不可少的功能,Google Map API 也为开发者提供了方便的接口在地图显示图标,本文还是以实例来说明如何将当前位置标示在地图上,效果如图 10 所示。

图 10. 当前位置图标

  1. 创建 MyOverlay 类,继承自 ItemizedOverlay 抽象类,在 MyOverlay 对象中包括所有要在地图上标注的对象列表 mItems。
  2. 重写 createItem 方法,将需要在地图上标注的点转化为 OverlayItem 对象,OverlayItem 对象对应于在地图上标注的每一个点,其包括经纬度信息、名称、标题、图标等属性,这些属性均可以通过其对象中提供的设置方法进行修改。
  3. 调用 addMarker()方法,将获取的当前位置信息以图标方式显示在地图上。
  4. 在 myMapOverlay类中重写 OnTap 方法,该方法会在图标点击事件触发时回调,传入参数为响应触击事件 overlayItem 对象在mItems中的位置。在我们的示例中,当图标点击事件触发时通过toast来显示当前位置信息。

清单 12. 在地图上添加图标

                private void addMarker() { if (myOverlay == null && myLocation != null) { GeoPoint myGeoPoint = location2GeoPoint(myLocation); if (myGeoPoint != null) { myOverlay = new MyMapOverlay(currLocMaker); myOverlay.setItem(myGeoPoint); mapView.getOverlays().add(myOverlay); mapController.animateTo(myGeoPoint); } } } public class MyMapOverlay extends ItemizedOverlay<OverlayItem> { private List<GeoPoint> mItems = new ArrayList<GeoPoint>(); public MyMapOverlay(Drawable marker) { // 初始化默认图标,并设置其为底部中心对应显示点super(boundCenterBottom(marker)); } public void setItems(ArrayList<GeoPoint> items) { mItems = items; populate(); } public void setItem(GeoPoint item) { mItems.add(item); populate(); } @Override protected OverlayItem createItem(int i) { // 此处没有进行图标的修改,默认为使用父类的默认图标return new OverlayItem(mItems.get(i), null, null); } @Override public int size() { return mItems.size(); } @Override protected boolean onTap(int i) { // 图标点击事件处理Toast.makeText(GoogleMapExampleActivity.this, "当前位置:\n "+ myLocation.getLatitude() + ", "+myLocation.getLongitude(), Toast.LENGTH_SHORT).show();   return true; } }

回页首

结束语

本文通过实例介绍如何在 Android 系统上开发以及 Google Map 的简单应用程序,相信读者通过源代码实例以及文字介绍有了大致的了解。接下来我们还会对开发基于 Map 应用过程中一些常用的方法进行汇总,比如,如何自定制图标并添加文字,响应长按事件,zoom 事件,点击图标弹出气球框等。

回页首

下载

描述 名字 大小 下载方法
样例代码 GoogleMapExample.zip 64KB HTTP

关于下载方法的信息

http://www.ibm.com/developerworks/cn/opensource/os-cn-android-gmap/

逐步进阶指南

开发基于 Google Map 的 Android 应用相关推荐

  1. google map for Android

    因为政策原因,google map在国内鲜有人使用,但是如果涉及到国外的项目,又不得不和google map接触,借着自己做的项目,在这里简单介绍一下google map for Android的使用 ...

  2. 用Python和Google AppEngine开发基于Google架构的应用软件

    用Python和Google AppEngine开发基于Google架构的应用软件 在研究了一段时间的Google AppEngine之后,我发现Google AppEngine是未来一个非常不错的开 ...

  3. Android特色开发(3):Google Map

    Google Map(Google地图) 参考书籍:<Android应用开发揭秘>第9章 Google Map概述 Google Map是 Google 公司提供的电子地图服务,包括局部详 ...

  4. android google map key,android google map api key取得?

    我有一个项目的谷歌地图apikey现在我想要另一个项目的apikey和这个项目的keystore是在一个不同的地方.我的第一个cmd:android google map api key取得? &qu ...

  5. android google map 标记,android google map添加标记和TipView

    1.new一个mapoverlay并添加到map上.    mapoverlay上要绘制数据点标记和TipView: protected void adjustCacheInMap(final Lis ...

  6. Python和Google AppEngine开发基于Google架构的应用软件

    在研究了一段时间的Google AppEngine之后,我发现Google AppEngine是未来一个非常不错的开发平台,希望可以尽快搞清楚GoogleAppEngine整个的平台架构,并且可以尽快 ...

  7. android google map 标记,android,在googlemap上从位图添加标记

    我正在使用googlemap-android-api v2,并希望在运行时从位图创建标记.所以,我做的:android,在googlemap上从位图添加标记 BitmapFactory.Options ...

  8. android+脚本录制开发,基于hook机制的android自动化脚本录制回放框架的设计与实现...

    Design and implementation of an automated script Recording Playback android hook mechanism based fra ...

  9. Google Map开发之实战

    视频课:[免费]跨平台APP JQuery Mobile开发-1-初探移动开发-张晨光的在线视频教程-CSDN程序员研修院 学习内容 Google Map服务简介 获取Google Map API K ...

最新文章

  1. 影像组学视频学习笔记(34)-使用3D Slicer软件提取影像组学特征、Li‘s have a solution and plan.
  2. 学习.Net的经典网站
  3. AWS load balancer
  4. inconsistent debug frame and source code -Eclipse调试器里看到的代码行数和实际源代码不一致该怎么办
  5. android各版本的sdk区别
  6. Vijos 1303
  7. latex附录中放python代码_LaTeX 里「添加程序代码」的完美解决方案
  8. 欲戴王冠,必承其重。
  9. VCSA6.7移除添加vSAN磁盘组
  10. 有没有游泳可以戴的耳机、防水耳机能戴着游泳
  11. 打包项目出错 Your build settings specify a provisioning profile with the UUI
  12. 计算机软件版权注册,计算机软件版权注册费是多少
  13. F-One融资B轮,企业绩效管理与分析服务再升级!
  14. 利用CSS制作通栏,css6——通栏平均分布
  15. 需求来源以及竞品分析
  16. 《黄花黄》安铁诗词作品摘录
  17. 区块链测试(二):区块链测试
  18. 基于Python 3.11.0版本模拟登录并爬取西安理工大学正方教务系统的学分绩点并计算
  19. 听到别人发论文的感想
  20. 李健熙去世,面临诸多阻碍的三星缺乏发展的方向

热门文章

  1. Servlet知识概括详解
  2. 大数据热的冷思考:无法取代传统的新闻传播科研方法
  3. 我实现的一些Abp模块
  4. Nginx+Tomcat负载均衡的部署
  5. O光 E光 双折射现象
  6. 测试人员如何管理项目与风险预警
  7. Matlab / ArcGIS 处理GPM全球月均降水数据
  8. 搞数仓也得懂几个常用机器学习算法
  9. 深度学习:蒸馏Distill
  10. oracle rac 关闭asm,11G rac的ASM无法关闭