首页 > 代码库 > Android应用中使用百度地图API定位自己的位置(二)

Android应用中使用百度地图API定位自己的位置(二)

官方文档:http://developer.baidu.com/map/sdkandev-6.htm#.E7.AE.80.E4.BB.8B3


百度地图SDK为开发人员们提供了例如以下类型的地图覆盖物:

  • 我的位置图层(MyLocationOverlay):用于显示用户当前位置的图层(支持自己定义位置图标);

  • Poi搜索结果图层(PoiOverlay):用于显示兴趣点搜索结果的图层;

  • 路线图层(RouteOverlay):公交、步行和驾车线路图层,将公交、步行和驾车出行方案的路线及关键点显示在地图上(起、终点图标用户可自己定义);

  • 公交换乘图层(TransitOverlay):公交换乘线路图层,将某一特定地区的公交出行方案的路线及换乘位置显示在地图上(起、终点图标用户可自己定义);

  • 自己定义图层(ItemizedOverlay):可将一个或多个兴趣点绘制到地图上,且支持自己定义图标(支持动态更新Item位置、图标);

  • 弹出窗图层(PopupOverlay):在地图上显示一个弹出窗体;

  • 几何图形绘制图层(GraphicsOverlay):用于绘制点、折线段、弧线、圆、矩形、多边形等几何图形的图层;

  • 文字绘制图层(TextOverlay):用于绘制文字的图层。

  • 图片图层(GroundOverlay):用于展示用户传入图片的图层。

  • 全景图图层(PanoramaOverlay):在全景图内标绘兴趣点,支持自己定义图标样式。

注:除弹出窗图层外,其它各个图层均已实现多实例。全景图图层是针对全景图所使用的特殊图层。

MapView使用一个List管理覆盖物,通过向MapView.getOverlays() add或remove上述类或其基类的实例就可以向地图加入或删除覆盖物。在更新地图覆盖物后,需调用MapView.refresh() 使更新生效。

定位原理

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


以下我们将利用  MyLocationOverlay和  PopupOverlay 这两个类

一 . 导入库文件

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

文件夹结构例如以下:

 库文件下载地址:http://pan.baidu.com/s/1ntNqKwp

二 . 布局文件,一个百度地图控件,加一个手动点击实现定位的button

<?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/mylocation"  
         />  
       
</RelativeLayout>

然后是主 Activity

package com.majianjie.baidumap;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.MeasureSpec;
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.MKMapViewListener;
import com.baidu.mapapi.map.MapController;
import com.baidu.mapapi.map.MapPoi;
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;
import com.example.baidumap.R;

public class MainActivity extends Activity {

	//声明控件
		private Button request;
	
		private Toast mToast=null;
		private BMapManager mBMapManager=null;
		private MapView mMapView = null;			//MapView 是地图主控件
		private MapController mMapController = null;//用MapController完毕地图控制
		
		private LocationClient mLocClient; 
		 public LocationData mLocData = http://www.mamicode.com/null;>

大家注意:这里我把上一次的加入marker的代码凝视了,原因是当我这两个同一时候弄的时候会无法给当前位置加入标记。。。这个问题稍后会得到解决。

以下的布局文件是弹出框的布局,一个 非常easy的文件:pop_layout.xml

<?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"
    >
	<TextView  
         android:id="@+id/location_tips"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/location_tips"
        android:maxWidth="200.0dip"
        android:minWidth="40.0dip"
        android:textColor="@android:color/white" />
         />  
       
</RelativeLayout>



  • 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 : 网络异常,没有成功向server发起请求。此时定位结果无效。
  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进行相关配置和权限的声明

<span style="color:#ff6666;"> </span><span style="color:#333333;">   <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" /></span>

还有非常重要的一点就是在AndroidManifest.xml中加入以下的内容


 <service  
            android:name="com.baidu.location.f"  
            android:enabled="true"  
            android:process=":remote" >  
        </service> 
        
        <meta-data
            android:name="com.baidu.lbsapi.API_KEY"
            android:value=http://www.mamicode.com/"6KOX4mXHeBRzgriV6OP1T2Hw"
            />
        <!-- 致命的一句 -->

当中的meta-data问题:网上这样说,大家记住就得了。。。。

由于单独的定位sdk须要一个key值,而定位sdk的值又不像mapManager中能够直接赋值
所以就须要在注冊表单中注冊

执行图示:

 apk地址:http://pan.baidu.com/s/1hqqWSuw

部分内容摘自百度官方文档。部分来自博客:http://blog.csdn.net/xiaanming/article/details/11380619

定位自己的位置基本就这些内容,出现的问题随后会补充上。。今天就这样吧。。吃饭去了。。