接上篇。

改造一下MapsActivity:

public class MapsActivity extends Activity implements LocationListener, InfoWindowAdapter, OnMarkerClickListener, OnMarkerDragListener{
}

实现4个interface:

android.location.LocationListener

GoogleMap.InfoWindowAdapter

GoogleMap.OnMarkerClickListener

GoogleMap.OnMarkerDragListener

本篇要实现在地图上定位,主要用到LocationListener接口。

另外3个接口关系到 打标记(Marker),移动标记点,以及点击标记弹出info窗口。这些功能将在下一篇文中整理。

地图初始化

首先在onCreate中需要对地图对象做一些设置:

@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.map); ........ if(servicesConnected()){
initMapView();
}
}

servicesConnected 检查service是否可用

private boolean servicesConnected() {
// Check that Google Play services is available
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
// If Google Play services is available
if(ConnectionResult.SUCCESS == resultCode) {
log("Google Play services is available.");
isServiceOk = true;
} else {
// Get the error code
ConnectionResult connectionResult = new ConnectionResult(resultCode, null);
int errorCode = connectionResult.getErrorCode();
// Get the error dialog from Google Play services
Dialog errorDialog = GooglePlayServicesUtil.getErrorDialog(
errorCode,
this,
RESULT_CODE_SERVICE_FAILURE); // If Google Play services can provide an error dialog
if(errorDialog != null) {
errorDialog.show();
}
isServiceOk = false;
}
return isServiceOk;
}

上一篇说过,手机调试环境需要安装Google Play服务和play store。如果没有安装,这里就会返回错误码。

initMapView 初始化

 private void initMapView(){
mMapView = ((MapFragment)getFragmentManager().findFragmentById(R.id.map_view)).getMap();
mMapView.setMapType(GoogleMap.MAP_TYPE_NORMAL); UiSettings setting = mMapView.getUiSettings();
setting.setTiltGesturesEnabled(true);
//setting.setCompassEnabled(false);
}

2行,获得地图对象 GoogleMap mMapView;后面很多操作都要通过它。

3行,设在地图模式为normal

4行,UiSettings 设置人机交互相关的各种按钮手势等待,例如:

void setTiltGesturesEnabled(boolean)  是否允许手势改变视角;

void setCompassEnabled(boolean)  是否显示指南针;

详细的UiSettings用法可参考官文 https://developers.google.com/maps/documentation/android/reference/com/google/android/gms/maps/UiSettings

移动到经纬度地点

先阐明一个概念,Goolge Map假定地图本身是固定不动的,移动的是camera(public final class CameraUpdate)。

想象一下,在地球上空漂浮着一只佳能无敌兔,把镜头对准魔都,焦距拉近看到了一号线,再拉远,视角倾斜一下,看到了魔都全貌,还是带广角的。不错吧!

回到代码,这里需要用的GPS。通过LocationManager来获得位置服务

mLocManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
mGPSOk = mLocManager.isProviderEnabled(LocationManager.GPS_PROVIDER);

获得LocationManager,并检查GPS是否可用。

在onResume函数中注册监听

 @Override
protected void onResume(){
super.onResume();
if(isServiceOk == false)
return; String provider = getBestProvider();
if(provider != null){
mLocManager.requestLocationUpdates(provider, 5*1000, 1, this);
} updateCurrentLoction();
setLatLng();
}

7行,获得可用的Location Provider,开启GPS的情况下这里得到的是GPS provider

9行,注册位置变化监听。第二入参5*1000表示每隔5秒更新一次,第三入参表示移动超过1米更新一次。最后一个入参即LocationListener,由于activity implement了LocationListener,所以这里只需要给activity的this指针。

12行和13行的两个函数,用于主动获取最新位置,移动地图到该位置,稍后贴出。

先看一下位置变化的监听函数,activity在implement了LocationListener后 需要实现一下几个函数:

 /* LocationListener begin */
@Override
public void onLocationChanged(Location newLoction) {
if(mLocation != null){
mLocation.setLatitude(newLoction.getLatitude());
mLocation.setLongitude(newLoction.getLongitude());
animateLatLng();
}
} @Override
public void onProviderDisabled(String arg0) {
// TODO Auto-generated method stub
}
@Override
public void onProviderEnabled(String arg0) {
// TODO Auto-generated method stub
}
@Override
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
}
/* LocationListener end */

3~9行,我这里只处理了onLocationChanged,这个函数在location发生变化时会调用到。

我们用了一个私有数据:private Location mLocation = null;

在onLocationChanged函数中,把新的location保存到mLocation中,然后调用animateLatLng把地图移动到该位置。

=================================================================

mLocation用于记录每次更新的经纬度,建议在onPause的时候把这个数据保存到本地,我是保存在preference中的。在onResume时读出来。

这样可以避免gps不可用的时候,地图飞回非洲。

当然也可一增加一个对network provider的监听,通过网络获取不太准确的位置,这部份我没做完整。

因为火星坐标系的问题,我最后换了baidu map,google map的这个apk很多后续的优化就没做了,汗吧!

=================================================================

有时我们需要主动查询最新的Location

  private void updateCurrentLoction(){
String bestProvider = getBestProvider();
Location newLoction = null; if(bestProvider != null)
newLoction = mLocManager.getLastKnownLocation(bestProvider); if(mLocation == null){
mLocation = new Location("");
} if(newLoction != null){
mLocation.setLatitude(newLoction.getLatitude());
mLocation.setLongitude(newLoction.getLongitude());
}
}

3行,获取最优的provider

7行,获取最近一次的location

8~16行,同样的,新位置记录到mLocation中。

getBestProvider函数体如下:

private String getBestProvider(){      
    Criteria criteria = new Criteria();
    criteria.setPowerRequirement(Criteria.POWER_LOW);
    criteria.setAccuracy(Criteria.ACCURACY_FINE);
    String bestOne = mLocManager.getBestProvider(criteria, true);
    return bestOne;
}

上文用到的两个函数setLatLng()和animateLatLng()

 private void setLatLng(boolean marked){
if(mLocation == null){
Toast.makeText(this, R.string.gpserr, Toast.LENGTH_LONG).show();
return;
} double dLat = mLocation.getLatitude();
double dLong = mLocation.getLongitude();
log("setLatLng: (" + dLat + "," + dLong + ")"); //LatLng latlng = new LatLng(31.13893, 121.39668);
LatLng latlng = new LatLng(dLat, dLong);
if((latlng.latitude == 0) && (latlng.longitude == 0)){
//mMapView.moveCamera(CameraUpdateFactory.newLatLng(latlng));
}else{
mMapView.moveCamera(CameraUpdateFactory.newLatLngZoom(latlng, 15));
}
} private void animateLatLng(boolean guide){
if(mLocation == null){
Toast.makeText(this, R.string.gpserr, Toast.LENGTH_LONG).show();
return;
} double dLat = mLocation.getLatitude();
double dLong = mLocation.getLongitude();
log("animateLatLng: (" + dLat + "," + dLong + ")");
LatLng latlng = new LatLng(dLat, dLong); mMapView.animateCamera(CameraUpdateFactory.newLatLng(latlng));
}

先看第一个setLatLng():

7~8行,从mLocation中调用getLatitude()取得维度,getLongitude()取得经度。

12行,构造一个LatLng对象

16行, mMapView.moveCamera(CameraUpdateFactory.newLatLngZoom(latlng, 15));

CameraUpdateFactory.newLatLngZoom(latlng, 15) 返回一个CameraUpdate对象,入参是经纬度和zoom level;

GoogleMap的moveCamera方法把地图移动到该位置。

animateLatLng()函数

31行  基本相同,唯一的区别是最后调用的是animateCamera,我们会看到地图从原location移动到新location的过程。而moveCamera方法是瞬移过去的,不会看到移动过程。

CameraUpdate有很多中构造方法,可以单独或同时指定位置和放大倍数。指定边界等待,详见

https://developers.google.com/maps/documentation/android/reference/com/google/android/gms/maps/CameraUpdateFactory

最后,要在onPause函数中注销位置服务监听

mLocManager.removeUpdates(this);

Google Map API v2 步步为营 (二)----- Location的更多相关文章

  1. Google Map API v2 步步为营(一) ----- 初见地图

    官方文档:https://developers.google.com/maps/documentation/android/start?hl=zh-CN 先谷歌后百度.使用google的api基本上按 ...

  2. Android中Google地图路径导航,使用mapfragment地图上画出线路(google map api v2)详解

    在这篇里我们只聊怎么在android中google map api v2地图上画出路径导航,用mapfragment而不是mapview,至于怎么去申请key,manifest.xml中加入的权限,系 ...

  3. google map api v2的使用详细过程,图文并茂(原创)

    上一篇中说到怎么获取key,下面来介绍怎么使用key来显示google地图 步骤1:eclipse上打开android SDK Manager,安装google play services. 步骤2: ...

  4. Google Map API v2 (三)----- 地图上添加标记(Marker),标记info窗口,即指定经纬度获取地址字符串

    接上篇 http://www.cnblogs.com/inkheart0124/p/3536322.html 1,在地图上打个标记 private MarkerOptions mMarkOption; ...

  5. Google Map API V2密钥申请

    之前用的都是v1,用的是MapView,好吧,仅仅能认命了.废话不再多说,開始android 的Google Maps Android API v2吧 之前參考了http://www.cnblogs. ...

  6. Google Map API v2 (四)----- 导航路径

    仍然是建议个异步小任务 private GetPathTask mGetPathTask = null; private void getGuidePath(LatLng origin){ if(mG ...

  7. Google Map API v2 番外篇 关于gps位置偏差及修正方法探讨

    我的手机是M35C,在我自己的map activity中,通过gps获取到的经纬度比实际地址总是有500米左右的偏差. 在网上搜索了很多,都说这个是测绘局为了保密故意弄成这样的.gps全球定位系统获得 ...

  8. Google Map API V3开发(1)

    Google Map API V3开发(1) Google Map API V3开发(2) Google Map API V3开发(3) Google Map API V3开发(4) Google M ...

  9. Google Map API V3开发(4)

    Google Map API V3开发(1) Google Map API V3开发(2) Google Map API V3开发(3) Google Map API V3开发(4) Google M ...

随机推荐

  1. Class类文件结构、类加载机制以及字节码执行

    一.Class类文件结构 Class类文件严格按照顺序紧凑的排列,由无符号数和表构成,表是由多个无符号数或其他数据项构成的符合数据结构. Class类文件格式按如下顺序排列:   类型 名称 数量 u ...

  2. ANDROID_MARS学习笔记_S04_003_用HttpClent发http请求

    一.代码 1.xml(1)activity_main.xml <TextView android:layout_width="wrap_content" android:la ...

  3. Mozilla研究—深入理解mozilla所需的背景知识

    mozilla是一个以浏览器为中心的软件平台,它在我们平台中占有重要地位.我们用它来实现WEB浏览器.WAP浏览器.邮件系统.电子书和帮助阅读器等应用程序.为此,我最近花了不少时间去阅读mozilla ...

  4. VS2008编译器编译出来的文件比mingw编译的要几乎小一半

    为什么要在VS2008中使用QT静态编译呢?很简单,因为VS2008编译器编译出来的文件比mingw编译的要几乎小一半. 好了现在我们来做些准备工作,VS2008自然要安装的,然后打上SP1的补丁.然 ...

  5. 【Xamarin开发 Android 系列 7】 Android 结构基础(下)

    原文:[Xamarin开发 Android 系列 7] Android 结构基础(下) *******前期我们不打算进行太深入的东西,省的吓跑刚进门的,感觉门槛高,so,我们一开始就是跑马灯一样,向前 ...

  6. queue与topic的技术特点对比

    1    queue与topic的技术特点对比 Topic Queue 概要 Publish Subscribe messaging 发布订阅消息 Point-to-Point 点对点 有无状态 to ...

  7. bzoj1034

    贪心 尽可能让最强的赢,最弱的赢,都不行则最弱打最强 感性的想,我肯定要尽可能的赢,而且赢的要对等 实在不能赢就拿最小的拼,所谓的田忌赛马策略 由于总分一定,己方最差即己方最好时对方的分数 ..] o ...

  8. ASP.NET中定制自己的委托和事件参数类

    本文笔记选自<庖丁解牛:纵向切入ASP.NET 3.5控件和组件开发技术>一书 一般在实际开发中,对于事件不需要传递数据信息时,像上面的KingTextBox控件的事件,在引发事件时传递的 ...

  9. calabash-android Win10 入门笔记

    参考官方文档:https://developer.xamarin.com/guides/testcloud/calabash/   概述     Calabash是一个BDD的UI自动化验收测试框架, ...

  10. ambari的重新安装

    ambari是什么呢? 这里我简单说一下ambari的目的,他的目的就是简化hadoop集群的安装和管理.对于安装简化到什么地步呢?只需要几个命令,在页面上配置几个参数,几百几千个节点的集群就能安装成 ...