• 百度地图2(转)


     
    Android 百度地图开发(二)--- 定位功能之MyLocationOverlay,PopupOverlay的使用
    
    分类: Android百度地图开发2013-09-09 15:38 920人阅读 评论(8) 收藏 举报
    百度地图定位PopupOverlayMyLocationOverlay
    转载请注明出处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目录下
    
     
    
    二 . 布局文件,一个百度地图控件,加一个手动点击实现定位的按钮,放在一个相对布局里面,很简单的布局
    
     
    
    [html] view plaincopy
     
    <?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代码,先贴上,然后适当讲解相关代码,我注释也比较清楚
    
     
    
    [java] view plaincopy
     
    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("
    error code : ");  
                  sb.append(location.getLocType());  
                  sb.append("
    latitude : ");  
                  sb.append(location.getLatitude());  
                  sb.append("
    lontitude : ");  
                  sb.append(location.getLongitude());  
                  sb.append("
    radius : ");  
                  sb.append(location.getRadius());  
                  if (location.getLocType() == BDLocation.TypeGpsLocation){  
                       sb.append("
    speed : ");  
                       sb.append(location.getSpeed());  
                       sb.append("
    satellite : ");  
                       sb.append(location.getSatelliteNumber());  
                       } else if (location.getLocType() == BDLocation.TypeNetWorkLocation){  
                       sb.append("
    addr : ");  
                       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("[我的位置]
    " + 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一些情况
    61 : GPS定位结果
    62 : 扫描整合定位依据失败。此时定位结果无效。
    63 : 网络异常,没有成功向服务器发起请求。此时定位结果无效。
    65 : 定位缓存的结果。
    66 : 离线定位结果。通过requestOfflineLocaiton调用时对应的返回结果
    67 : 离线定位失败。通过requestOfflineLocaiton调用时对应的返回结果
    68 : 网络连接失败时,查找本地离线定位时对应的返回结果
    161: 表示网络定位结果
    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
    [html] view plaincopy
     
    <service  
                android:name="com.baidu.location.f"  
                android:enabled="true"  
                android:process=":remote" >  
            </service>  
    声明相关的使用权限
    [html] view plaincopy
     
    <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" />  
    五 . 运行结果
     
  • 相关阅读:
    几个比较好的IT站和开发库官网
    Win7下Qt5.2中使用OpenGL的glu函数库无法使用的解决方案
    QT5.2 Assistant-设置应用程序图标
    linux下文件编码格式转换方法(gb18030/utf-8)
    QT-进制转换计算器
    QT-图标设置
    QT-make: *** No rule to make target
    QT的exe文件打开显示,无法定位程序***输入点于动态链接库****
    QT工程文件上传Github仓库
    Eclipse中文乱码
  • 原文地址:https://www.cnblogs.com/li-print/p/3385323.html
Copyright © 2020-2023  润新知