百度地图的基本应用和遇到的坑

百度地图的集成和使用

1. 第一步

既然是集成,自然需要先去看一下百度地图的相关网站,下面会陆续使用到这个网站。http://lbsyun.baidu.com/index.php?title=%E9%A6%96%E9%A1%B5

2. 申请sdk

注册完账号,之后就可以创建自己的应用啦,这个过程很简单,不需要人工通过。相关操作具体参考http://lbsyun.baidu.com/index.php?title=androidsdk/guide/key

3. 下载

首先要清楚自己需要的百度地图含有什么内容啦,在这里,我主要使用了基础地图,离线定位和计算工具的功能,下载开发包就行了,如果想要自行了解百度地图的,建议可以具体看看示例代码。相关地址http://lbsyun.baidu.com/sdk/download?selected=mapsdk_basicmap,mapsdk_searchfunction,mapsdk_lbscloudsearch,mapsdk_calculationtool,mapsdk_radar

4. 集成

使用很简单,主要是添加依赖和复制我们下载的包中的文件,详情见http://lbsyun.baidu.com/index.php?title=androidsdk/guide/buildproject

5. 使用

前五点内容在百度相关的网站说明中还是很详细的,具体的使用其实在demo中也是有的。

6. 权限

<uses-permission android:name="com.android.launcher.permission.READ_SETTINGS"/>
    <uses-permission android:name="android.permission.WAKE_LOCK"/>
    <uses-permission android:name="android.permission.GET_TASKS"/>
    <uses-permission android:name="android.permission.WRITE_SETTINGS"/>

    <!-- 这个权限用于进行网络定位 -->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <!-- 这个权限用于访问GPS定位 -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <!-- 用于访问wifi网络信息,wifi信息会用于进行网络定位 -->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>

    <!-- 获取运营商信息,用于支持提供运营商信息相关的接口 -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <!-- 这个权限用于获取wifi的获取权限,wifi信息会用来进行网络定位 -->
    <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"/>
    <!-- SD卡读取权限,用户写入离线定位数据 -->
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>

7. application添加

<meta-data
android:name="com.baidu.lbsapi.API_KEY" android:value="yBafP53oxkrDaE9mnuMxg07sstX4DBYt"/>

<service
    android:name="com.baidu.location.f"
    android:enabled="true"
    android:process=":remote">
</service>

8. 基础地图

以下的内容都是我集成了官方的百度地图Demo,写的内容,主要的区别就是官方是分开的,我是都集成在一起了,不过不影响使用,建议看官方Demo,后续我会接着说明一些Api的使用。
//1.基础地图,建议可修改默认城市
mMapView = (MapView) findViewById(R.id.bmapView);
mBaiduMap = mMapView.getMap();
//设定地图状态
LatLng center = new LatLng(39.915071, 116.403907); // 默认 天安门
MapStatus build = new MapStatus.Builder().target(center).zoom(18.0f).build();
MapStatusUpdate mapstatus = MapStatusUpdateFactory.newMapStatus(build);
mBaiduMap.animateMapStatus(mapstatus);

所需的座标,可通过百度提供的百度地图座标拾取系统获取。点击前往获取座标
当然最后写上生命周期是必要的。这个后面会有一起提到

9.基础定位

//获取传感器管理服务 用于箭头指示方向
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);

//2.定位
mBaiduMap.setMyLocationEnabled(true);
mBaiduMap.setOnMapLongClickListener(this);

mCurrentMode = MyLocationConfiguration.LocationMode.NORMAL;
mBaiduMap.setMyLocationConfigeration(new MyLocationConfiguration(mCurrentMode, true, null));
mLocationClient = new LocationClient(this);// 声明LocationClient类
mLocationClient.registerLocationListener(myListener); // 注册监听函数

//开启定位
option = new LocationClientOption();
option.setOpenGps(true);
option.setCoorType("bd09ll");
option.setProdName("shouxiu");
option.setScanSpan(1000);// 设置发起定位请求的间隔时间为10000ms
mLocationClient.setLocOption(option);
mLocationClient.start();

/**
 * 定位开启后位置监听
 */
@SuppressLint("ShowToast")
public class MyLocationListener implements BDLocationListener {

    @Override
    public void onReceiveLocation(BDLocation location) {
        if (location == null || mMapView == null) {
            return;
        }

        // 当位置改变时,获取当前经纬度
        mCurrentLat = location.getLatitude();
        mCurrentLon = location.getLongitude();
        mCurrentAccracy = location.getRadius();
        locData = new MyLocationData.Builder()
                .accuracy(location.getRadius())
                // 此处设置开发者获取到的方向信息,顺时针0-360
                .direction(mCurrentDirection).latitude(location.getLatitude())
                .longitude(location.getLongitude()).build();
        mBaiduMap.setMyLocationData(locData);

        //为了有效显示默认地址12,定位地址18
        if (isFirstLoc) {
            isFirstLoc = false;
            LatLng ll = new LatLng(location.getLatitude(),
                    location.getLongitude());
            MapStatus.Builder builder = new MapStatus.Builder();
            builder.target(ll).zoom(18.0f);
            mBaiduMap.animateMapStatus(MapStatusUpdateFactory.newMapStatus(builder.build()));

        }
    }

}

/**
 * 手机自带的方向感应
 * @param sensorEvent
 */
@Override
public void onSensorChanged(SensorEvent sensorEvent) {
    double x = sensorEvent.values[SensorManager.DATA_X];
    if (Math.abs(x - lastX) > 1.0) {
        mCurrentDirection = (int) x;
        locData = new MyLocationData.Builder()
                .accuracy(mCurrentAccracy)
                // 此处设置开发者获取到的方向信息,顺时针0-360
                .direction(mCurrentDirection).latitude(mCurrentLat)
                .longitude(mCurrentLon).build();
        mBaiduMap.setMyLocationData(locData);
    }
    lastX = x;

}

生命周期

@Override
protected void onDestroy() {
    // 退出时销毁定位
    mLocationClient.stop();
    //销毁POI搜索
    mPoiSearch.destroy();
    mSuggestionSearch.destroy();
    // 关闭定位图层
    mBaiduMap.setMyLocationEnabled(false);
    mMapView.onDestroy();
    mMapView = null;
    //线路规划
    if (mRoutePlanSearch!= null) {
        mRoutePlanSearch.destroy();
    }
    super.onDestroy();
}

@Override
protected void onResume() {
    mMapView.onResume();
    super.onResume();
    //为系统的方向传感器注册监听器
    mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),
            SensorManager.SENSOR_DELAY_UI);
}

@Override
protected void onPause() {
    mMapView.onPause();
    super.onPause();
}

@Override
protected void onStop() {
    mSensorManager.unregisterListener(this);
    super.onStop();
}

10.POI搜索

// 初始化搜索模块,注册搜索事件监听
mPoiSearch = PoiSearch.newInstance();   mPoiSearch.setOnGetPoiSearchResultListener(poiListener);

// 初始化建议搜索模块,注册建议搜索事件监听
mSuggestionSearch = SuggestionSearch.newInstance();
mSuggestionSearch.setOnGetSuggestionResultListener(mSuggestionResultListener);

//填入搜索城市
editCity = (EditText) findViewById(R.id.city);
//填入搜索关键字
keyWorldsView = (AutoCompleteTextView) findViewById(R.id.searchkey);
//关键字输入后,提示下拉框显示适配器
sugAdapter = new ArrayAdapter<>(this,
        android.R.layout.simple_dropdown_item_1line);
keyWorldsView.setAdapter(sugAdapter);
keyWorldsView.setThreshold(1);

//当输入关键字变化时,动态更新建议列表
keyWorldsView.addTextChangedListener(new TextWatcher() {

    //省略代码

    @Override
    public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
        if (cs.length() <= 0) {
            return;
        }

   //使用建议搜索服务获取建议列表,结果在onSuggestionResult()中更新
    mSuggestionSearch
            .requestSuggestion((new SuggestionSearchOption())
                    .keyword(cs.toString()).city(editCity.getText().toString()));
}
});


//响应城市内搜索按钮点击事件
public void searchButtonProcess(View v) {
    searchType = 1;
    String citystr = editCity.getText().toString();
    String keystr = keyWorldsView.getText().toString();

    // 设置检索参数
    PoiCitySearchOption citySearchOption = new PoiCitySearchOption();
    citySearchOption.city(citystr);// 城市
    citySearchOption.keyword(keystr);// 关键字
    citySearchOption.pageCapacity(15);// 默认每页10条
    citySearchOption.pageNum(loadIndex);// 分页编号
    // 发起检索请求
    mPoiSearch.searchInCity(citySearchOption);
}

//响应周边搜索按钮点击事件
public void searchNearbyProcess(View v) {
    searchType = 2;
    mCenter = new LatLng(mCurrentLat, mCurrentLon);
    System.out.println(mCurrentLat);
    System.out.println(mCurrentLon);

    PoiNearbySearchOption nearbySearchOption = new PoiNearbySearchOption();
    nearbySearchOption.location(mCenter);
    nearbySearchOption.keyword(keyWorldsView.getText().toString());
    nearbySearchOption.radius(1000);// 检索半径,单位是米
    nearbySearchOption.pageNum(loadIndex);
    mPoiSearch.searchNearby(nearbySearchOption);// 发起附近检索请求
}

//检索结果标记类
private class MyPoiOverlay extends PoiOverlay {

    public MyPoiOverlay(BaiduMap baiduMap) {
        super(baiduMap);
    }

    @Override
    public boolean onPoiClick(int index) {
        super.onPoiClick(index);
        PoiInfo poi = getPoiResult().getAllPoi().get(index);
        // if (poi.hasCaterDetails) {
        mPoiSearch.searchPoiDetail((new PoiDetailSearchOption())
                .poiUid(poi.uid));
        // }
        return true;
    }
}

//POI检索监听
OnGetPoiSearchResultListener poiListener = new OnGetPoiSearchResultListener() {

    public void onGetPoiResult(PoiResult result) {
        //获取POI检索结果
        if (result == null || result.error == SearchResult.ERRORNO.RESULT_NOT_FOUND) {
            Toast.makeText(MainActivity.this, "未找到结果", Toast.LENGTH_LONG)
                    .show();
            return;
        }
        if (result.error == SearchResult.ERRORNO.NO_ERROR) {
            mBaiduMap.clear();
            PoiOverlay overlay = new MyPoiOverlay(mBaiduMap);
            mBaiduMap.setOnMarkerClickListener(overlay);
            overlay.setData(result);
            overlay.addToMap();
            overlay.zoomToSpan();
            if (searchType == 2) {
                showNearbyArea(mCenter, radius);
            }

            return;
        }
        if (result.error == SearchResult.ERRORNO.AMBIGUOUS_KEYWORD) {

            // 当输入关键字在本市没有找到,但在其他城市找到时,返回包含该关键字信息的城市列表
            String strInfo = "在";
            for (CityInfo cityInfo : result.getSuggestCityList()) {
                strInfo += cityInfo.city;
                strInfo += ",";
            }
            strInfo += "找到结果";
            Toast.makeText(MainActivity.this, strInfo, Toast.LENGTH_LONG)
                    .show();
        }
    }

    public void onGetPoiDetailResult(PoiDetailResult result) {
        //获取Place详情页检索结果
        if (result.error != SearchResult.ERRORNO.NO_ERROR) {
            Toast.makeText(MainActivity.this, "抱歉,未找到结果", Toast.LENGTH_SHORT)
                    .show();
        } else {
            mEndLocation = result.getLocation();
            Toast.makeText(MainActivity.this, result.getName() + ": " + result.getAddress(), Toast.LENGTH_SHORT)
                    .show();
        }
    }

    @Override
    public void onGetPoiIndoorResult(PoiIndoorResult poiIndoorResult) {

    }
};

//输入关键字推荐结果
private ArrayList<String> suggest;
OnGetSuggestionResultListener mSuggestionResultListener = new OnGetSuggestionResultListener() {
    @Override
    public void onGetSuggestionResult(SuggestionResult res) {
        if (res == null || res.getAllSuggestions() == null) {
            return;
        }
        suggest = new ArrayList<>();
        for (SuggestionResult.SuggestionInfo info : res.getAllSuggestions()) {
            if (info.key != null) {
                suggest.add(info.key);
            }
        }
        sugAdapter = new ArrayAdapter<>(MainActivity.this, android.R.layout.simple_dropdown_item_1line, suggest);
        keyWorldsView.setAdapter(sugAdapter);
        sugAdapter.notifyDataSetChanged();
    }
};

11.路径规划

这一块的代码有点长,所以这里也就不做复述了,建议查看官方Demo,在这里提一些小的需求,长按标记前往地点,然后路径规划

//长按标记前往地址
@Override
public void onMapLongClick(LatLng latLng) {
    //全局终点座标
    mEndLocation = latLng;
    MarkerOptions ooA = new MarkerOptions().position(latLng).icon(bdA);
    mBaiduMap.clear();
    mBaiduMap.addOverlay(ooA);
}
然后在定位监听中获取当前座标,有了两个座标,就可以做路径规划了

12.遇到的坑

自定义地图的设定,官方必须要将mapview添加到FrameLayout,当时不清楚,就不断地试,走了不少弯路。其次就是关于公司的一个需求,去除地铁线路,这个我就笑了,线是去了,但是留下了文本框(地铁线上关于线路介绍的),这个框不管做什么设定,都存在。

13.综述

差不多了,这篇博客篇幅有些长了。关于Api的使用就放到下一篇中描述了。至于Demo,仔细看过官方Demo的哥们都应该看出来了,我的代码后面有时间上传吧。

14.后续遇到的坑

1.最近遇到一个项目中的Bug,百度地图不能拖动的问题,最后主要原因是当activityA有BaiduMap,并且正在定位,那么开启activityB,B中的BaiduMap就会出现过一段时间不能拖动的问题,具体解决就是在生命周期中暂停定位。业务上的需求进行转移。
2.最近接触了百度地图的动画,也就是官方介绍的生长动画,添加mark时会以变大的形式出现,这时经理拿着高德,给我看动画是从一个小图片直接生长成大图片,而百度地图却只是从中心变大。就坑了,只能多加点代码了。
3.最近接触了FragmentTabHost+Fragment+BaiduMap,切换遇到黑屏问题,后来找了解决方案使用了TextureMapView替换了MapView,就好用了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章