接上篇。

改造一下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. 【网络流24题】No.19 负载平衡问题 (费用流)

    [题意] G 公司有 n 个沿铁路运输线环形排列的仓库, 每个仓库存储的货物数量不等. 如何用最少搬运量可以使 n 个仓库的库存数量相同.搬运货物时,只能在相邻的仓库之间搬运. 输入文件示例input ...

  2. Android 窗口管理

    一.概述 在Android系统中,从设计的角度来看,窗口管理系统是基于C/S模式的.整个窗口系统分为服务端和客户端两大部分,客户端负责请求创建窗口和使用窗口,服务端完成窗口的维护,窗口显示等. 在Cl ...

  3. poj2104

    裸的主席树,没什么好说的 type node=record        l,r,s:longint;      end; ..] of node;     sa,rank,a,b,sum,head: ...

  4. sql server 2005+ 翻页

    select * from ( select row_number() over (order by dm) row,* from t_zycp where dm like '%4%' ) tmp

  5. HDU-1701 Binary Tree Traversals

    http://acm.hdu.edu.cn/showproblem.php?pid=1710 已知先序和中序遍历,求后序遍历二叉树. 思路:先递归建树的过程,后后序遍历. Binary Tree Tr ...

  6. LR测试工具性能指标详解

    这篇文章将对LoadRunner测试工具的性能指标从以下三点进行详解. 第一点.Web资源分析是从服务器入手对Web服务器的性能分析. 1.Hits per Second "每秒点击次数&q ...

  7. 作品第一课----获取批量checkbox选中的值

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. java基础(十八)IO流(一)

    这里有我之前上课总结的一些知识点以及代码大部分是老师讲的笔记 个人认为是非常好的,,也是比较经典的内容,真诚的希望这些对于那些想学习的人有所帮助! 由于代码是分模块的上传非常的不便.也比较多,讲的也是 ...

  9. JAVA vo pojo javabean dto的区别

    JavaBean 是一种JAVA语言写成的可重用组件.为写成JavaBean,类必须是具体的和公共的,并且具有无参数的构造器.JavaBean 通过提供符合一致性设计模式的公共方法将内部域暴露成员属性 ...

  10. CodeFirst-数据迁移-Migration

    http://www.cnblogs.com/haogj/archive/2012/02/17/2356537.html 1.安装最新NuGet 2.安装EntityFramework:在程序包管理器 ...