接上篇。

改造一下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. vlc

    源码下载地址:http://download.videolan.org/pub/videolan/vlc/ 编译依赖: sudo apt-get install liblua5.2-dev sudo ...

  2. ANDROID_MARS学习笔记_S03_008_GOOGLEMAP2

    一.简介 二.代码1.xml(1)main.xml <?xml version="1.0" encoding="utf-8"?> <Linea ...

  3. [OJ] Permutation Index

    LintCode 197. Permutation Index (Easy) LintCode 198. Permutation Index II (Medium) 感觉这两道题主要考察计算排列组合的 ...

  4. leetcode面试准备: CountPrimes

    1 题目 Description: Count the number of prime numbers less than a non-negative number, n. 接口:public in ...

  5. Deep Learning论文笔记之(八)Deep Learning最新综述

    Deep Learning论文笔记之(八)Deep Learning最新综述 zouxy09@qq.com http://blog.csdn.net/zouxy09 自己平时看了一些论文,但老感觉看完 ...

  6. insert into select * from 锁表

    mysql[192.168.11.187] processid[249] root@localhost in db[zjzc] hold transaction time 197 112069858, ...

  7. [主机/oracle/msyql] 监控脚本

    为了方便自己测试和监控,写了三个监控的脚本. 分别监控: 主机[cpu,mem,disk,fs,net] oracle mysql 脚本如下: hmon.py: monitor Linux os sy ...

  8. Android Volley - volley StringRequest編碼問題

    有些時候這個類並不能很好的解決中文編碼問題 如果出現亂碼,就 要重寫該類的parseNetworkResponse 方法了. 繼承StringRequest,然後重寫parseNetworkRespo ...

  9. [C# 网络编程系列]专题四:自定义Web浏览器

    转自:http://www.cnblogs.com/zhili/archive/2012/08/24/WebBrowser.html 前言: 前一个专题介绍了自定义的Web服务器,然而向Web服务器发 ...

  10. Oracle 12c最新特性

    9 Pluggable Databases This section provides details on the Pluggable Databases (PDB) metrics. 9.1 Da ...