`
810364804
  • 浏览: 779105 次
文章分类
社区版块
存档分类
最新评论

Android 百度地图开发(二)--- 定位功能之MyLocationOverlay,PopupOverlay的使用

 
阅读更多

转载请注明出处http://blog.csdn.net/xiaanming/article/details/11380619

这一篇文章主要讲解的是百度地图的定位功能,然后还有MyLocationOverlay和PopupOverlay两个地图覆盖物的使用,Overlay是“图层”或“覆盖物”的意思,MyLocationOverlay从名字上面理解就是我的位置图层,他能够实现在地图上显示当前位置的图标以及指南针,MyLocationOverlay只负责显示我的位置,位置数据请使用百度定位SDK获取,将获取的位置数据放在一个LocationData结构中并用该结构设置MyLcationOverlay的数据源,即可创建MyLocationOverlay,PopupOverlay就是弹出窗口图层了,跟PopupWindow类似的东西,下面会介绍他们的使用方法


定位我们使用的是百度Android 定位SDKv4.0,我们先了解下定位原理和定位精度


定位原理

使用百度Android定位SDK必须注册GPS和网络使用权限。定位SDK采用GPS、基站、Wi-Fi信号进行定位。当应用程序向定位SDK发起定位请求时,定位SDK会根据应用的定位因素(GPS、基站、Wi-Fi信号)的实际情况(如是否开启GPS、是否连接网络、是否有信号等)来生成相应定位依据进行定位。
用户可以设置满足自身需求的定位依据:
若用户设置GPS优先,则优先使用GPS进行定位,如果GPS定位未打开或者没有可用位置信息,且网络连接正常,定位SDK则会返回网络定位(即Wi-Fi与基站)的最优结果。为了使获得的网络定位结果更加精确,请打开手机的Wi-Fi开关。




定位精度



了解了百度定位的原理和定位精度之后,接下来我们就来使用百度定位SDKv4.0吧


一 . 导入库文件

在使用百度定位SDKv4.0之前,我们要下载最新的库文件,下载地址:点击下载相关库文件,将liblocSDK4.so文件拷贝到libs/armeabi目录下。将locSDK4.0.jar文件拷贝到工程的libs目录下


二 . 布局文件,一个百度地图控件,加一个手动点击实现定位的按钮,放在一个相对布局里面,很简单的布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <com.baidu.mapapi.map.MapView
        android:id="@+id/bmapView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:clickable="true" />
    
    
     <Button
         android:id="@+id/request"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_alignParentRight="true"
         android:layout_alignParentTop="true"
         android:layout_marginRight="10dp"
         android:layout_marginTop="10dip"
         android:background="@drawable/custom_loc"  />

</RelativeLayout>


三 . 界面MainActivity代码,先贴上,然后适当讲解相关代码,我注释也比较清楚

package com.example.baidumapdemo;

import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.MeasureSpec;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.mapapi.BMapManager;
import com.baidu.mapapi.MKGeneralListener;
import com.baidu.mapapi.map.LocationData;
import com.baidu.mapapi.map.MKEvent;
import com.baidu.mapapi.map.MapController;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.MyLocationOverlay;
import com.baidu.mapapi.map.PopupClickListener;
import com.baidu.mapapi.map.PopupOverlay;
import com.baidu.platform.comapi.basestruct.GeoPoint;

public class MainActivity extends Activity {
	private Toast mToast;
	private BMapManager mBMapManager;
	private MapView mMapView = null;
	private MapController mMapController = null;
	
	/**
	 * 定位SDK的核心类
	 */
	private LocationClient mLocClient;
	/**
	 * 用户位置信息 
	 */
	private LocationData mLocData;
	/**
	 * 我的位置图层
	 */
	private	LocationOverlay myLocationOverlay = null;
	/**
	 * 弹出窗口图层
	 */
	private PopupOverlay mPopupOverlay  = null;
	
	private boolean isRequest = false;//是否手动触发请求定位
	private boolean isFirstLoc = true;//是否首次定位
	
	/**
	 * 弹出窗口图层的View
	 */
	private View mPopupView;
	private BDLocation location;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		//使用地图sdk前需先初始化BMapManager,这个必须在setContentView()先初始化
		mBMapManager = new BMapManager(this);
		
		//第一个参数是API key,
		//第二个参数是常用事件监听,用来处理通常的网络错误,授权验证错误等,你也可以不添加这个回调接口
		mBMapManager.init("7ae13368159d6a513eaa7a17b9413b4b", new MKGeneralListenerImpl());
		setContentView(R.layout.activity_main);
		
		//点击按钮手动请求定位
		((Button) findViewById(R.id.request)).setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				requestLocation();
			}
		});
		
		mMapView = (MapView) findViewById(R.id.bmapView); //获取百度地图控件实例
        mMapController = mMapView.getController(); //获取地图控制器
        mMapController.enableClick(true);   //设置地图是否响应点击事件
        mMapController.setZoom(14);   //设置地图缩放级别
        mMapView.setBuiltInZoomControls(true);   //显示内置缩放控件
        
        mMapView.setTraffic(true);  //设置交通信息图
//        mMapView.setSatellite(true);  //设置卫星图
//        mMapController.setOverlooking(-45);  //设置地图俯视角度 ,范围:0~ -45
        
        
        mPopupView = LayoutInflater.from(this).inflate(R.layout.pop_layout, null);
        
        //实例化弹出窗口图层
        mPopupOverlay = new PopupOverlay(mMapView ,new PopupClickListener() {
			
        	/**
        	 * 点击弹出窗口图层回调的方法
        	 */
			@Override
			public void onClickedPopup(int arg0) {
				//隐藏弹出窗口图层
				mPopupOverlay.hidePop();
			}
		});
        
        
        //实例化定位服务,LocationClient类必须在主线程中声明
        mLocClient = new LocationClient(getApplicationContext());
		mLocClient.registerLocationListener(new BDLocationListenerImpl());//注册定位监听接口
		
		/**
		 * LocationClientOption 该类用来设置定位SDK的定位方式。
		 */
		LocationClientOption option = new LocationClientOption();
		option.setOpenGps(true); //打开GPRS
		option.setAddrType("all");//返回的定位结果包含地址信息
		option.setCoorType("bd09ll");//返回的定位结果是百度经纬度,默认值gcj02
		option.setPriority(LocationClientOption.GpsFirst); // 设置GPS优先
		option.setScanSpan(5000); //设置发起定位请求的间隔时间为5000ms
		option.disableCache(false);//禁止启用缓存定位
//		option.setPoiNumber(5);    //最多返回POI个数   
//		option.setPoiDistance(1000); //poi查询距离        
//		option.setPoiExtraInfo(true);  //是否需要POI的电话和地址等详细信息        
		mLocClient.setLocOption(option);  //设置定位参数
		
		
		mLocClient.start();  //	调用此方法开始定位
		
		//定位图层初始化
		myLocationOverlay = new LocationOverlay(mMapView);
		
		
		//实例化定位数据,并设置在我的位置图层
        mLocData = new LocationData();
	    myLocationOverlay.setData(mLocData);
	    
	    //添加定位图层
	    mMapView.getOverlays().add(myLocationOverlay);
	    
	    //修改定位数据后刷新图层生效
	    mMapView.refresh();
		
		
	}
	
	
	/**
	 * 定位接口,需要实现两个方法
	 * @author xiaanming
	 *
	 */
	public class BDLocationListenerImpl implements BDLocationListener {

		/**
		 * 接收异步返回的定位结果,参数是BDLocation类型参数
		 */
		@Override
		public void onReceiveLocation(BDLocation location) {
			if (location == null) {
				return;
			}
			
		    StringBuffer sb = new StringBuffer(256);
		      sb.append("time : ");
		      sb.append(location.getTime());
		      sb.append("\nerror code : ");
		      sb.append(location.getLocType());
		      sb.append("\nlatitude : ");
		      sb.append(location.getLatitude());
		      sb.append("\nlontitude : ");
		      sb.append(location.getLongitude());
		      sb.append("\nradius : ");
		      sb.append(location.getRadius());
		      if (location.getLocType() == BDLocation.TypeGpsLocation){
		           sb.append("\nspeed : ");
		           sb.append(location.getSpeed());
		           sb.append("\nsatellite : ");
		           sb.append(location.getSatelliteNumber());
		           } else if (location.getLocType() == BDLocation.TypeNetWorkLocation){
		           sb.append("\naddr : ");
		           sb.append(location.getAddrStr());
		        } 
		 
		      Log.e("log", sb.toString());
			
			
			MainActivity.this.location = location;
			
			mLocData.latitude = location.getLatitude();
			mLocData.longitude = location.getLongitude();
			//如果不显示定位精度圈,将accuracy赋值为0即可
			mLocData.accuracy = location.getRadius();
			mLocData.direction = location.getDerect();
			
			//将定位数据设置到定位图层里
            myLocationOverlay.setData(mLocData);
            //更新图层数据执行刷新后生效
            mMapView.refresh();
            
			
            if(isFirstLoc || isRequest){
            	//将给定的位置点以动画形式移动至地图中心
				mMapController.animateTo(new GeoPoint(
						(int) (location.getLatitude() * 1e6), (int) (location
								.getLongitude() * 1e6)));
				showPopupOverlay(location);
				isRequest = false;
            }
            isFirstLoc = false;
            
		}

		/**
		 * 接收异步返回的POI查询结果,参数是BDLocation类型参数
		 */
		@Override
		public void onReceivePoi(BDLocation poiLocation) {
			
		}

	}
	
	

	//继承MyLocationOverlay重写dispatchTap方法
	private class LocationOverlay extends MyLocationOverlay{

		public LocationOverlay(MapView arg0) {
			super(arg0);
		}

		
		/**
		 * 在“我的位置”坐标上处理点击事件。
		 */
		@Override
		protected boolean dispatchTap() {
			//点击我的位置显示PopupOverlay
			showPopupOverlay(location);
			return super.dispatchTap();
		}
		
	}
	
	
	/**
	 * 显示弹出窗口图层PopupOverlay
	 * @param location
	 */
	private void showPopupOverlay(BDLocation location){
		 TextView popText = ((TextView)mPopupView.findViewById(R.id.location_tips));
		 popText.setText("[我的位置]\n" + location.getAddrStr());
		 mPopupOverlay.showPopup(getBitmapFromView(popText),
					new GeoPoint((int)(location.getLatitude()*1e6), (int)(location.getLongitude()*1e6)),
					15);
		 
	}
	
	
	/**
	 * 手动请求定位的方法
	 */
	public void requestLocation() {
		isRequest = true;
		
		if(mLocClient != null && mLocClient.isStarted()){
			showToast("正在定位......");
			mLocClient.requestLocation();
		}else{
			Log.d("log", "locClient is null or not started");
		}
	}
	
	
	
	 /** 
     * 显示Toast消息 
     * @param msg 
     */  
    private void showToast(String msg){  
        if(mToast == null){  
            mToast = Toast.makeText(this, msg, Toast.LENGTH_SHORT);  
        }else{  
            mToast.setText(msg);  
            mToast.setDuration(Toast.LENGTH_SHORT);
        }  
        mToast.show();  
    } 
	
	/**
	 * 将View转换成Bitmap的方法
	 * @param view
	 * @return
	 */
	public static Bitmap getBitmapFromView(View view) {
		view.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
        view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
        view.buildDrawingCache();
        Bitmap bitmap = view.getDrawingCache();
        return bitmap;
	}
	
	
	
	
	
	/**
	 * 常用事件监听,用来处理通常的网络错误,授权验证错误等
	 * @author xiaanming
	 *
	 */
	public class MKGeneralListenerImpl implements MKGeneralListener{

		/**
		 * 一些网络状态的错误处理回调函数
		 */
		@Override
		public void onGetNetworkState(int iError) {
			if (iError == MKEvent.ERROR_NETWORK_CONNECT) {
				showToast("您的网络出错啦!");
            }
		}

		/**
		 * 授权错误的时候调用的回调函数
		 */
		@Override
		public void onGetPermissionState(int iError) {
			if (iError ==  MKEvent.ERROR_PERMISSION_DENIED) {
				showToast("API KEY错误, 请检查!");
            }
		}
		
	}
	
	@Override
	protected void onResume() {
    	//MapView的生命周期与Activity同步,当activity挂起时需调用MapView.onPause()
		mMapView.onResume();
		super.onResume();
	}



	@Override
	protected void onPause() {
		//MapView的生命周期与Activity同步,当activity挂起时需调用MapView.onPause()
		mMapView.onPause();
		super.onPause();
	}

	@Override
	protected void onDestroy() {
		//MapView的生命周期与Activity同步,当activity销毁时需调用MapView.destroy()
		mMapView.destroy();
		
		//退出应用调用BMapManager的destroy()方法
		if(mBMapManager != null){
			mBMapManager.destroy();
			mBMapManager = null;
		}
		
		//退出时销毁定位
        if (mLocClient != null){
            mLocClient.stop();
        }
		
		super.onDestroy();
	}

	
	
}

  • LocationClient定位SDK的核心类,LocationClient类必须在主线程中声明。需要Context类型的参数。Context需要时全进程有效的context,推荐用getApplicationConext获取全进程有效的context,我们调用registerLocationListener(BDLocationListener)方法来注册定位监听接口,BDLocationListener里面有两个方法,onReceiveLocation()(接收异步返回的定位结果),onReceivePoi()(接收异步返回的POI查询结果,POI是“Point of Interest”的缩写,可以翻译成“信息点”,每个POI包含四方面信息,名称、类别、经度、纬度、附近的酒店、饭店,商铺等信息。我们可以叫它为“导航地图信息”,导航地图数据是整个导航产业的基石),我们这里只需要重写onReceiveLocation就行了
  • BDLocation封装了定位SDK的定位结果,在BDLocationListener的onReceive方法中获取。通过该类用户可以获取error code,位置的坐标,精度半径,地址等信息,对于其getLocType ()方法获取的error code一些情况
  1. 61 : GPS定位结果
  2. 62 : 扫描整合定位依据失败。此时定位结果无效。
  3. 63 : 网络异常,没有成功向服务器发起请求。此时定位结果无效。
  4. 65 : 定位缓存的结果。
  5. 66 : 离线定位结果。通过requestOfflineLocaiton调用时对应的返回结果
  6. 67 : 离线定位失败。通过requestOfflineLocaiton调用时对应的返回结果
  7. 68 : 网络连接失败时,查找本地离线定位时对应的返回结果
  8. 161: 表示网络定位结果
  9. 162~167: 服务端定位失败
  • LocationClientOption 用来设置定位SDK的定位方式,比如设置打开GPS,设置是否需要地址信息,设置发起定位请求的间隔时间等等,参数设置完后调用LocationClient 的setLocOption方法
  • LocationOverlay MyLocationOverlay的子类,重写里面的dispatchTap()方法,显示弹出窗口图层PopupOverlay,调用mMapView.getOverlays().add(myLocationOverlay)就将我的位置图层添加到地图里面
  • PopupOverlay 弹出图层,这个类还是比较简单,里面只有三个方法,hidePop() (隐藏弹出图层)showPopup(Bitmap pop, GeoPoint point, int yOffset) (显示弹出图层)和showPopup显示多张图片的重载方法,由于showPopup方法只接受Bitmap对象,所以我们必须将我们的弹出图层View对象转换成Bitmap对象,我们调用getBitmapFromView方法就实现这一转换
  • BDLocationListener接口的onReceiveLocation(BDLocation location) 方法我还要重点讲解下,我们会发现onReceiveLocation方法会反复执行,他执行的间隔跟LocationClientOption类的setScanSpan()方法设定的值有关,我们设定的是5000毫秒,则onReceiveLocation方法每隔5秒执行一次,注意,当我们设定的值大于1000(ms),定位SDK内部使用定时定位模式。调用requestLocation( )后,每隔设定的时间,定位SDK就会进行一次定位。如果定位SDK根据定位依据发现位置没有发生变化,就不会发起网络请求,返回上一次定位的结果;如果发现位置改变,就进行网络请求进行定位,得到新的定位结果。如果你只需要定位一次的话,这个设置小于1000,或者不用设置就可以了,定时定位时,调用一次requestLocation,会定时监听到定位结果



四 . 在运行程序之前,我们还必须在AndroidManifest.xml进行相关配置和权限的声明
  • 在application标签中声明service组件,每个app拥有自己单独的定位service
<service
            android:name="com.baidu.location.f"
            android:enabled="true"
            android:process=":remote" >
        </service>
  • 声明相关的使用权限
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
    <uses-permission android:name="android.permission.READ_LOGS" />

五 . 运行结果


今天的讲解到此结束,有疑问的朋友请在下面留言。之后会持续介绍百度地图的使用,欢迎大家关注!


项目代码,点击下载




分享到:
评论

相关推荐

    Android 百度地图开发(二)--- 定位功能之MyLocationOverlay,PopupOverlay的使用 实例源码

    Android 百度地图开发(二)--- 定位功能之MyLocationOverlay,PopupOverlay的使用,项目详情http://blog.csdn.net/xiaanming/article/details/11380619

    Android高级编程--源代码

    作为使用androidsdk构建这些应用程序的实用指南书籍,《android高级编程》从始至终穿插了一系列示例项目,每个项目都引入android的新功能和新技术,以助您达到最圆满的学习效果。书中介绍android的所有基本功能,并...

    百度地图信息推送报告

    (四)地图定位和我的位置图层MyLocationOverlay 9 (五)自定义图层ItemizedOverlay和在地图上增加标注 10 (六)增加点击标注弹出气泡(显示标注信息)的功能 12 (七)增加POI搜索功能 15 三、百度地图的信息推送 ...

    Baidu_map(百度地图)Android平台开发指南

    Baidu_map(百度地图)Android平台开发指南 • 1 简介 • 2 基础知识 • 3 地图图层 o 3.1 底图 o 3.2 实时交通信息 o 3.3 卫星图 o 3.4 实景图 • 4 覆盖物 o 4.1 覆盖物的抽象基类:Overlay o 4.2 当前位置:...

    百度地图开发笔记

    详细介绍百度开发实例1.BMapManager 这个是地图引擎的管理类。要注意的地方:1、要在setContent()前使用;2、一个软件只需要一个BMapManager对象,我在主Activity把它定义为static类型的,然后在其他Activity共享...

    百度地图定位

    本地图完成了自我位置的定位和周边搜索 mBMapMan = new BMapManager(getApplication()); mBMapMan.init(mKey, null); mBMapMan.getLocationManager().setNotifyInternal(10, 3) ; // 如果使用地图SDK,请初始化...

    《Android高级编程》

    7.7.1 MapView和MapActivity简介 7.7.2 创建一个基于地图的活动 7.7.3 配置和使用MapView 7.7.4 使用MapController 7.7.5 对“Where Am I”示例使用地图 7.7.6 创建和使用覆盖(Overlay) 7.7.7 MyLocationOverlay简介...

    Android高级编程.pdf

    1.5 Android SDK功能 1.5.1 对包括摄像头、GPS和加速计在内的硬件的访问 1.5.2 自带的Google地图、地理编码和基于位置的服务 1.5.3 后台服务 1.5.4 SQLite数据存储和检索数据库 1.5.5 共享数据和应用程序间通信 ...

    beginning android

    * Work with TabActivity, MyLocationOverlay, DDMS, and more * Utilize the distinctive capabilities of the Android engine including maps, Internet access, integrated search, media playback, and more ...

    Google!Android手機應用程式設計入門

    跟隨擁有Android Market單一應用...第四十章 結合地圖與定位功能(MyLocationOverlay) 第四十一章 為地圖標上地標(ItemizedOverlay) 附錄A 後記 附錄B如何取得範例原始碼 这个是他BLOG的电子版,如喜欢请支持Z版。

    精通ANDROID 3(中文版)1/2

    1.5 使用Android SDK开发最终用户应用程序  1.5.1 Android模拟器  1.5.2 Android UI  1.5.3 Android基础组件  1.5.4 高级UI概念  1.5.5 Android Service组件  1.5.6 Android媒体和电话组件  1.5.7 ...

    精通Android 3 (中文版)2/2

    1.5 使用Android SDK开发最终用户应用程序  1.5.1 Android模拟器  1.5.2 Android UI  1.5.3 Android基础组件  1.5.4 高级UI概念  1.5.5 Android Service组件  1.5.6 Android媒体和电话组件  1.5.7 ...

    mapabc的文档

    对于初学者而言很实用,第一部分,如何获取MapABC API 密钥。 第二部分,什么时签名证书。 第三部分,如何获取一个 API 密钥。 第四部分,如何在 Mapview ...第十一部分,手势功能对 Android sdk 版本有哪些要求。

    一本android的好书beginning android 2 和 源码

    android好书系列,我目前找了两本,先贡献给大家。以后如果有好的资源,再上传和大家分享。 本资源是第一本。 这是一本学习android的好书,我浏览了,是老外著的,高清晰的pdf。为了方便大家学习android,我将本书所...

Global site tag (gtag.js) - Google Analytics