Android — 之百度地图定位+添加Mark+InfoWindow

前言:

  新手上路,这几天在弄百度地图SDK的使用(吐槽 : 官网上的开发指南简直就是实力坑爹,可能是开发人员太忙,维护不及时吧),我对本次学习的要求也不高:能正常显示地图,能定位,能添加mark(覆盖物),点击mark时能提示当前位置信息就行,再深的东西,以后有时间再去研究吧,毕竟新手还是欠火候。
  
因为软件开发更新换代太快,各位看官看的时候可能本文内容就已经过时了,所以先交代一下开发环境:

应用开发开发工具:
  Android Studio 1.5.1

百度地图版本信息:
  Android 地图 SDK v3.7.1
  Android 定位 SDK v6.2.2

正文:

一、效果图

废话多说,先来一发截图,一眼就能看出来到底实现了哪些功能:
Android — 之百度地图定位+添加Mark+InfoWindow_第1张图片
          图1-1.实现定位
         
Android — 之百度地图定位+添加Mark+InfoWindow_第2张图片
        图1-2.拖拽到新的位置
 
如上面两幅图所示,图1-1显示的是当程序正常运行后,就会定位到当前位置,显示位置信息(’气泡’),图1-2显示的是当拖动mark到新的位置后,显示当前的位置信息,大家可能注意到图1-2右下角红色圆圈圈住的图标,是可以点击的,作用是实现重新定位。

二、开发过程

2.1导入库文件

去百度开发者中心下载最新的开发包,现在是支持按功能需求来下载开发包,我就贪婪的全都下载了(下载地址),最好的学习方式就是下载示例代码,模仿着写。解压下载好的库文件。
首先:在工程app/libs目录下放入BaiduLBS_Android.jar包,如图2-1所示。
然后:在src/main/目录下新建jniLibs目录,在jniLibs新建armeabi文件(这个文件要根据你的手机的cpu类型来创建,armeabi就是针对普通的或旧的arm cpu,armeabi-v7a是针对有浮点运算或高级扩展功能的arm cpu),然后把动态链接库.so文件拷贝到该目录下,如图2-2所示。
最后:对于每个jar文件,右键-选择Add As Library,导入到工程中。

        图2-1.导入jar包文件
        
Android — 之百度地图定位+添加Mark+InfoWindow_第3张图片
        图2-2.导入.so库文件

环境配置也可以参考官方指南.

2.2布局文件

修改activity_main.xml布局文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.yu.baidumapdemo.MainActivity">

    <TextView  android:id="@+id/title" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="百 度 地 图" />
    <com.baidu.mapapi.map.MapView  android:id="@+id/map_view" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/title" android:clickable="true"/>
    <Button  android:id="@+id/request_location" android:layout_width="45dp" android:layout_height="45dp" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:layout_marginBottom="5dp" android:layout_marginLeft="50dp" android:background="@drawable/custom_loc"/>
</RelativeLayout>

布局文件如上所述,很简单,一个TextView显示一个标题(之后我用它来显示当前位置),一个com.baidu.mapapi.map.MapView,这是最重要的用来,是显示地图的控件,最后放了一个Button,就是图1-2中红圈所示的按钮,用来重新获取定位。

2.3java类代码

2.3.1初始化SDK

新建类 BaiduMapDemoApplication继承自Application

package com.yu.baidumapdemo;

import android.app.Application;

import com.baidu.mapapi.SDKInitializer;

/** * Created by yu on 2016-03-09. */
public class BaiduMapDemoApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        // 在使用 SDK 各组间之前初始化 context 信息,传入 ApplicationContext
        //这样就不用每个Activity都初始化一遍了
        SDKInitializer.initialize(this);
    }
}

这个类的功能很简单,因为在使用百度地图的所有功能前都需要调用SDKInitializer.initialize(android.content.Context);来初始化组件,所以新建这个类继承自Application,并在AndroidManifest.xml文件进行配置(为application添加属性 android:name=“.BaiduMapDemoApplication”),保证最先得到初始化。

2.3.2实现地图定位等功能

MainActivity.java:

package com.yu.baidumapdemo;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.location.Poi;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BitmapDescriptor;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.InfoWindow;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.Marker;
import com.baidu.mapapi.map.MarkerOptions;
import com.baidu.mapapi.map.MyLocationData;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.search.core.PoiInfo;
import com.baidu.mapapi.search.geocode.GeoCodeResult;
import com.baidu.mapapi.search.geocode.GeoCoder;
import com.baidu.mapapi.search.geocode.OnGetGeoCoderResultListener;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeOption;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeResult;

import java.util.List;

//Ak(百度密钥): 8w4BMfqde5lkbGy3xz6h6Y7C
public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";   //日志的TAG
    private Button requestButton = null;    //重新定位按钮
    private TextView locationText = null;   //显示位置信息的TextView
    private MapView mapView = null;         //显示地图的控件
    private BaiduMap baiduMap = null;       //地图管理器
    private Marker marker = null ;          //覆盖物
    //初始化bitmap信息,不用的时候请及时回收recycle //覆盖物图标
    private BitmapDescriptor bd = BitmapDescriptorFactory.fromResource(R.drawable.location_arrows);
    //定位服务的客户端。宿主程序在客户端声明此类,并调用,目前只支持在主线程中启动
    private LocationClient locationClient = null;
    //是否是首次定位,实际上没有用到,因为我设置了不定时请求位置信息
    boolean isFirstLoc = true;

    //定位监听器(实现定位请求回调接口),当客户端请求定位或者开始定位的时候会触发
    public BDLocationListener myListener = new BDLocationListener() {
        @Override
        public void onReceiveLocation(BDLocation bdLocation) {
            Log.d(TAG, "BDLocationListener -> onReceiveLocation");
            String addr; //定位结果
            //mapView销毁后不在处理新接收的位置
            if(bdLocation == null || mapView == null) {
                Log.d(TAG, "BDLocation or mapView is null");
                locationText.setText("定位失败...");
                return;
            }
            if(!bdLocation.getLocationDescribe().isEmpty()) {
                addr = bdLocation.getLocationDescribe();
            }else if (bdLocation.hasAddr()) {
                addr = bdLocation.getAddrStr();
            }else {
                Log.d(TAG, "BDLocation has no addr info");
                addr = "定位失败...";
                return;
            }
            //以下打印日志,打印一些详细信息,供参考
            //------------------------------------位置信息日志--------------------------------------------------
            StringBuilder sBuilder = new StringBuilder();
            sBuilder.append("\nTime : " + bdLocation.getTime());            //服务器返回的当前定位时间
            sBuilder.append("\nError code : " + bdLocation.getLocType());   //定位结果码
            sBuilder.append("\nLatitude : " + bdLocation.getLatitude());    //获取纬度坐标
            sBuilder.append("\nLongtitude : " + bdLocation.getLongitude()); //获取经度坐标
            sBuilder.append("\nRadius : " + bdLocation.getRadius());        //位置圆心

           //根据定位结果码判断是何种定位以及定位请求是否成功
            if(bdLocation.getLocType() == BDLocation.TypeGpsLocation) {
                //GPS定位结果
                sBuilder.append("\nSpeed : " + bdLocation.getSpeed());//当前运动的速度
                sBuilder.append("\nSatellite number : " + bdLocation.getSatelliteNumber());//定位卫星数量
                sBuilder.append("\nHeight : " + bdLocation.getAltitude());  //位置高度
                sBuilder.append("\nDirection : " + bdLocation.getDirection());  //定位方向
                sBuilder.append("\nAddrStr : " + bdLocation.getAddrStr());  //位置详细信息
                sBuilder.append("\nStreet : " + bdLocation.getStreetNumber() + " " + bdLocation.getStreet());//街道号、路名
                sBuilder.append("\nDescribtion : GPS 定位成功");
            }else if (bdLocation.getLocType() == BDLocation.TypeNetWorkLocation) {
                //网络定位结果
                sBuilder.append("\nAddrStr : " + bdLocation.getAddrStr()); //位置详细信息
                sBuilder.append("\nStreet : " + bdLocation.getStreetNumber() + " " + bdLocation.getStreet());//街道号、路名
                sBuilder.append("\nOperators : " + bdLocation.getOperators());//运营商编号
                sBuilder.append("\nDescribtion : 网络定位成功");
            }else if(bdLocation.getLocType() == BDLocation.TypeOffLineLocation) {
                //离线定位结果
                sBuilder.append("\nAddrStr : " + bdLocation.getAddrStr()); //位置详细信息
                sBuilder.append("\nStreet : " + bdLocation.getStreetNumber() + " " + bdLocation.getStreet());//街道号、路名
                sBuilder.append("\nDescribtion : 离线定位成功");
            }else if(bdLocation.getLocType() == BDLocation.TypeServerError) {
                sBuilder.append("\nDescribtion : 服务端网络定位失败,可以反馈IMEI号和大体定位时间到[email protected],会有人追查原因");
            }else if(bdLocation.getLocType() == BDLocation.TypeNetWorkException) {
                sBuilder.append("\nDescribtion : 网络故障,请检查网络连接是否正常");
            }else if(bdLocation.getLocType() == BDLocation.TypeCriteriaException) {
                sBuilder.append("\nDescribtion : 无法定位结果,一般由于定位SDK内部检测到没有有效的定位依据," +
                        "比如在飞行模式下就会返回该定位类型, 一般关闭飞行模式或者打开wifi就可以再次定位成功");
            }

            //位置语义化描述
            sBuilder.append("\nLocation decribe : " + bdLocation.getLocationDescribe());
            //poi信息(就是附近的一些建筑信息),只有设置可获取poi才有值
            List<Poi> poiList = bdLocation.getPoiList();
            if(poiList != null) {
                sBuilder.append("\nPoilist size : " + poiList.size());
                for (Poi p : poiList) {
                    sBuilder.append("\nPoi : " + p.getId() + " " + p.getName() + " " + p.getRank());
                }
            }
            //打印以上信息
            Log.d(TAG, "定位结果详细信息 : " + sBuilder.toString());

            //----------------------------------------------定位----------------------------------------
            //构建生成定位数据对象 //定位数据构建器
            MyLocationData myLocationData = new MyLocationData.Builder()
                    .accuracy(bdLocation.getRadius())   //设置定位数据的精度信息,单位米
                    .direction(100)                     //设定定位数据的方向信息??啥意思??
                    .latitude(bdLocation.getLatitude()) //设定定位数据的纬度
                    .longitude(bdLocation.getLongitude())//设定定位数据的经度
                    .build();   //构建生生定位数据对象

            //设置定位数据, 只有先允许定位图层后设置数据才会生效,setMyLocationEnabled(boolean)
            baiduMap.setMyLocationData(myLocationData);

            if(isFirstLoc) {
                //Log.d(TAG,"首次定位开始");
                //isFirstLoc = false;
                //地理坐标基本数据结构:经度和纬度
                LatLng latLng = new LatLng(bdLocation.getLatitude(),bdLocation.getLongitude());
                //为当前定位到的位置设置覆盖物Marker
                resetOverlay(latLng);
                //描述地图状态将要发生的变化 //生成地图状态将要发生的变化,newLatLngZoom设置地图新中心点
                MapStatusUpdate mapStatusUpdate = MapStatusUpdateFactory.newLatLngZoom(latLng,18.0f);
                //MapStatusUpdate mapStatusUpdate = MapStatusUpdateFactory.newLatLngZoom(latLng);
                //以动画方式更新地图状态,动画耗时 300 ms (聚焦到当前位置)
                baiduMap.animateMapStatus(mapStatusUpdate);

            }
            locationText.setText(addr);
        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate");

        //在使用SDK各组件之前初始化context信息,传入ApplicationContext
        //注意该方法要再setContentView方法之前实现//最好使用全局的Context 即用getApplicationContext()
        //SDKInitializer.initialize(getApplicationContext());//由于已在BaiduMapDemoApplication中初始化过,就不再次初始化
        setContentView(R.layout.activity_main);//加载布局文件
        //获取地图控件的引用
        mapView = (MapView) findViewById(R.id.map_view);
        //重新定位按钮
        requestButton = (Button) findViewById(R.id.request_location);
        //定位结果显示
        locationText = (TextView) findViewById(R.id.title);
        locationText.setText("正在定位...");
        //获取地图控制器
        baiduMap = mapView.getMap();
        //允许定位图层,如果不设置这个参数,那么baiduMap.setMyLocationData(myLocationData);定位不起作用
        baiduMap.setMyLocationEnabled(true);
        //设置mark覆盖物拖拽监听器
        baiduMap.setOnMarkerDragListener(new MyMarkerDragListener());
        //设置mark覆盖物点击监听器
        baiduMap.setOnMarkerClickListener(new MyMarkerClickListener());
        //生成定位服务的客户端对象,此处需要注意:LocationClient类必须在主线程中声明
        locationClient = new LocationClient(getApplicationContext());
        //注册定位监听函数,当开始定位.start()或者请求定位.requestLocation()时会触发
        locationClient.registerLocationListener(myListener);
        //设定定位SDK的定位方式
        setLocationOption();
        //开始、请求定位
        //locationClient.start();
        requestLocation();

        //重新定位按钮设置监听器
        requestButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //开始定位,或者重新定位
                requestLocation();
            }
        });

    }

    //开始定位或者请求定位
    private void requestLocation() {
        //如果请求定位客户端已经开启,就直接请求定位,否则开始定位
        //很重要的一点,是要在AndroidManifest文件中注册定位服务,否则locationClient.isStarted一直会是false,
        // 而且可能出现一种情况是首次能定位,之后再定位无效
        if(locationClient != null && locationClient.isStarted()) {
            Log.d(TAG, "requestLocation.");
            locationText.setText("正在定位...");
            //请求定位,异步返回,结果在locationListener中获取.
            locationClient.requestLocation();
        }else if (locationClient != null && !locationClient.isStarted()) {
            Log.d(TAG, "locationClient is started : " + locationClient.isStarted());
            locationText.setText("正在定位...");
            //定位没有开启 则开启定位,结果在locationListener中获取.
            locationClient.start();
        }else {
            Log.e(TAG,"request location error!!!");
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy");
        //注销定位监听器
        locationClient.unRegisterLocationListener(myListener);
        //停止定位
        locationClient.stop();
        //不允许图层定位
        baiduMap.setMyLocationEnabled(false);
        //清除覆盖物
        clearOverlay();
        //回收Bitmap资源
        bd.recycle();
        //在activity执行onDestroy时执行MapView.onDestroy(),实现地图生命周期管理
        mapView.onDestroy();
        mapView = null;
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG, "onResume");
        //在activity执行onResume时执行MapView. onResume(),实现地图生命周期管理
        mapView.onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG, "onPause");
        //在activity执行onPause时执行MapView. onResume(),实现地图生命周期管理
        mapView.onPause();
    }

    //设定定位服务客户端locationClient的定位方式
    private void setLocationOption(){
        //获取配置参数对象,用于配置定位SDK各配置参数,比如定位模式、定位时间间隔、坐标系类型等
        LocationClientOption option = new LocationClientOption();
        //可选,默认false,设置是否使用gps
        option.setOpenGps(true);
        /* * 高精度定位模式:这种定位模式下,会同时使用网络定位和GPS定位,优先返回最高精度的定位结果; * 低功耗定位模式:这种定位模式下,不会使用GPS,只会使用网络定位(Wi-Fi和基站定位); * 仅用设备定位模式:这种定位模式下,不需要连接网络,只使用GPS进行定位,这种模式下不支持室内环境的定位。*/
        //可选,默认高精度,设置定位模式,高精度,低功耗,仅设备
        option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);
        //可选,默认gcj02,设置返回的定位结果坐标系
        option.setCoorType("bd09ll");
        //可选,默认0,即仅定位一次,设置定时发起定位请求的间隔需要大于等于1000ms才是有效的
        /* * 定位sdk提供2种定位模式,定时定位和app主动请求定位。 * setScanSpan < 1000 则为 app主动请求定位; * setScanSpan >=1000,则为定时定位模式(setScanSpan的值就是定时定位的时间间隔)) * 定时定位模式中,定位sdk会按照app设定的时间定位进行位置更新,定时回调定位结果。此种定位模式适用于希望获得连续定位结果的情况。 * 对于单次定位类应用,或者偶尔需要一下位置信息的app,可采用app主动请求定位这种模式。*/
        //option.setScanSpan(2000);
        //可选,设置是否需要地址信息,默认不需要
        option.setIsNeedAddress(true);
        //可选,默认false,设置是否需要位置语义化结果,可以在BDLocation.getLocationDescribe里得到,结果类似于“在北京天安门附近”
        option.setIsNeedLocationDescribe(true);
        //设置是否需要返回位置POI信息,可以在BDLocation.getPoiList()中得到数据
        option.setIsNeedLocationPoiList(true);
        //在网络定位时,是否需要设备方向 true:需要 ; false:不需要
        option.setNeedDeviceDirect(true);
        //可选,默认true,定位SDK内部是一个SERVICE,并放到了独立进程,设置是否在stop的时候杀死这个进程,默认不杀死
        option.setIgnoreKillProcess(false);
        //可选,默认false,设置是否收集CRASH信息,默认收集
        option.SetIgnoreCacheException(false);
        //可选,默认false,设置是否需要过滤gps仿真结果,默认需要
        option.setEnableSimulateGps(false);

        //设定定位SDK的定位方式
        locationClient.setLocOption(option);
    }

    //初始化添加覆盖物mark
    private void initOverlay(LatLng latLng) {
        Log.d(TAG, "Start initOverlay");

        //设置覆盖物添加的方式与效果
        MarkerOptions markerOptions = new MarkerOptions()
                .position(latLng)//mark出现的位置
                .icon(bd)       //mark图标
                .draggable(true)//mark可拖拽
                .animateType(MarkerOptions.MarkerAnimateType.drop)//从天而降的方式
                //.animateType(MarkerOptions.MarkerAnimateType.grow)//从地生长的方式
                ;
        //添加mark
        marker = (Marker) (baiduMap.addOverlay(markerOptions));//地图上添加mark

        //弹出View(气泡,意即在地图中显示一个信息窗口),显示当前mark位置信息
        setPopupTipsInfo(marker);

        Log.d(TAG,"End initOverlay");
    }

    //清除覆盖物
    private void clearOverlay(){
        baiduMap.clear();
        marker = null;
    }
    //重置覆盖物
    private void resetOverlay(LatLng latLng) {
        clearOverlay();
        initOverlay(latLng);
    }

    //覆盖物拖拽监听器
    public class MyMarkerDragListener implements BaiduMap.OnMarkerDragListener {

        @Override
        public void onMarkerDrag(Marker marker) {

        }

        //拖拽结束,调用方法,弹出View(气泡,意即在地图中显示一个信息窗口),显示当前mark位置信息
        @Override
        public void onMarkerDragEnd(Marker marker) {
            setPopupTipsInfo(marker);
        }

        @Override
        public void onMarkerDragStart(Marker marker) {

        }
    }

    //覆盖物点击监听器
    public class MyMarkerClickListener implements BaiduMap.OnMarkerClickListener {

        @Override
        public boolean onMarkerClick(Marker marker) {
           //调用方法,弹出View(气泡,意即在地图中显示一个信息窗口),显示当前mark位置信息
            setPopupTipsInfo(marker);
            return false;
        }
    }

    //想根据Mark中的经纬度信息,获取当前的位置语义化结果,需要使用地理编码查询和地理反编码请求
    //在地图中显示一个信息窗口
    private void setPopupTipsInfo(Marker marker){
        //获取当前经纬度信息
        final LatLng latLng = marker.getPosition();
        final String[] addr = new String[1];
        //实例化一个地理编码查询对象
        GeoCoder geoCoder = GeoCoder.newInstance();
        //设置反地理编码位置坐标
        ReverseGeoCodeOption option = new ReverseGeoCodeOption();
        option.location(latLng);
        //发起反地理编码请求
        geoCoder.reverseGeoCode(option);
        //为地理编码查询对象设置一个请求结果监听器
        geoCoder.setOnGetGeoCodeResultListener(new OnGetGeoCoderResultListener() {
            @Override
            public void onGetGeoCodeResult(GeoCodeResult geoCodeResult) {

                Log.d(TAG, "地理编码信息 ---> \nAddress : " + geoCodeResult.getAddress()
                        + "\ntoString : " + geoCodeResult.toString()
                        + "\ndescribeContents : " + geoCodeResult.describeContents());
            }

            //当获取到反编码信息结果的时候会调用
            @Override
            public void onGetReverseGeoCodeResult(ReverseGeoCodeResult reverseGeoCodeResult) {
                //获取地理反编码位置信息
                addr[0] = reverseGeoCodeResult.getAddress();
                //获取地址的详细内容对象,此类表示地址解析结果的层次化地址信息。
                ReverseGeoCodeResult.AddressComponent addressDetail = reverseGeoCodeResult.getAddressDetail();
                Log.d(TAG, "反地理编码信息 ---> \nAddress : " + addr[0]
                        + "\nBusinessCircle : " + reverseGeoCodeResult.getBusinessCircle()//位置所属商圈名称
                        + "\ncity : " + addressDetail.city  //所在城市名称
                        + "\ndistrict : " + addressDetail.district  //区县名称
                        + "\nprovince : " + addressDetail.province  //省份名称
                        + "\nstreet : " + addressDetail.street      //街道名
                        + "\nstreetNumber : " + addressDetail.streetNumber);//街道(门牌)号码

                StringBuilder poiInfoBuilder = new StringBuilder();
                //poiInfo信息
                List<PoiInfo> poiInfoList = reverseGeoCodeResult.getPoiList();
                if(poiInfoList != null) {
                    poiInfoBuilder.append("\nPoilist size : " + poiInfoList.size());
                    for (PoiInfo p : poiInfoList) {
                        poiInfoBuilder.append("\n\taddress: " + p.address);//地址信息
                        poiInfoBuilder.append(" name: " + p.name + " postCode: " + p.postCode);//名称、邮编
                        //还有其他的一些信息,我这里就不打印了,请参考API
                    }
                }
                Log.d(TAG,"poiInfo --> " + poiInfoBuilder.toString());

                //动态创建一个View用于显示位置信息
                Button button = new Button(getApplicationContext());
                //设置view是背景图片
                button.setBackgroundResource(R.drawable.location_tips);
                //设置view的内容(位置信息)
                button.setText(addr[0]);
                //在地图中显示一个信息窗口,可以设置一个View作为该窗口的内容,也可以设置一个 BitmapDescriptor 作为该窗口的内容
                InfoWindow infoWindow = new InfoWindow(BitmapDescriptorFactory.fromView(button), latLng, -47, new InfoWindow.OnInfoWindowClickListener() {
                    @Override
                    public void onInfoWindowClick() {
                        //当InfoWindow被点击后隐藏
                        baiduMap.hideInfoWindow();
                    }
                });
                //InfoWindow infoWindow = new InfoWindow(button, latLng, -47);
                //显示信息窗口
                baiduMap.showInfoWindow(infoWindow);
            }
        });
        /*不能放在下面 因为可能得到的数据还没来得及回调 Button button = new Button(getApplicationContext()); button.setBackgroundResource(R.drawable.location_tips); button.setText(addr[0]); //InfoWindow infoWindow = new InfoWindow(BitmapDescriptorFactory.fromView(button),latLng,-47,null); InfoWindow infoWindow = new InfoWindow(button,latLng,-47); baiduMap.showInfoWindow(infoWindow); */
        return ;
    }
}

应为上面的代码注释很详细,这里简单介绍一下流程:
首先:获取地图显示控件对象MapView -> mapView
然后:获取地图控制对象BaiduMap -> baiduMap,并允许显示图层定位
再后:为baiduMap设置监听器:覆盖物拖拽监听器,覆盖物点击监听器(二者的主要作用是在地图中显示一个信息窗口,来提示用户当前的位置信息)
接着:获取定位服务客户端对象 LocationClient -> locationClient,并注册定位监听函数(BDLocationListener)以及设置定位方式
最后:调用locationClient .start()开启定位或者如果定位服务已开启,则调用locationClient .requestLocation()再次请求定位,这两个方法成功调用后,会触发定位监听器(BDLocationListener),然后监听器中获取定位结果以及定位信息,并且添加覆盖物和显示信息窗口(气泡)。

2.4配置AndroidManifest.xml文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.yu.baidumapdemo">


    <!--读取系统设置的数据库(launcher.db)的权限-->
    <uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
    <!--屏幕保持唤醒 不锁屏-->
    <uses-permission android:name="android.permission.WAKE_LOCK"/>
    <!--允许应用程序更改主屏幕中的设置和快捷方式-->
    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
    <!-- 这个权限用于进行网络定位-->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
    <!-- 这个权限用于访问GPS定位-->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
    <!-- 用于访问wifi网络信息,wifi信息会用于进行网络定位-->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
    <!-- 获取运营商信息,用于支持提供运营商信息相关的接口-->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
    <!-- 这个权限用于获取wifi的获取权限,wifi信息会用来进行网络定位-->
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>
    <!-- 用于读取手机当前的状态-->
    <uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
    <!-- 写入扩展存储,向扩展卡写入数据,用于写入离线定位数据-->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
    <!-- 访问网络,网络定位需要上网-->
    <uses-permission android:name="android.permission.INTERNET" />
    <!-- SD卡读取权限,用户写入离线定位数据-->
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"></uses-permission>

    <application  android:name=".BaiduMapDemoApplication" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <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="8w4BMfqde5lkbGy3xz6h6Y7C"/>
    </application>

</manifest>

增加以下四个配置(很重要)
  1). 增加权限的申请
  2). 注册application初始化SDK,即:
    为application添加属性 android:name=“.BaiduMapDemoApplication”
  3). 注册定位服务(com.baidu.location.f),这个服务如果不注册,会导致无法进行定位
  4). 配置密钥(AK)

你可能感兴趣的:(android,百度地图)