[Android]百度地图POI检索

写在前面
本来想使用百度定位的SDK把定位功能实现了,可无奈遇上个坑到写这篇blog为止都还没有解决。故所以把使用百度地图SDK实现简单的POI检索功能和遇到的坑先做一个总结。

下载.os和jar包

  1. 如果需要使用自定义的功能,最好不要分别下载。
    例如之前我只是想先简单的实现POI检索功能,所以只下载了跟百度地图相关的SDK,实现了之后觉得单调,决定加入定位功能的时候再单独去下载了定位相关的SDK,坑就出现了,引入.os和jar之后,
    出现 java.lang.NoSuchMethodError: No direct method <init> 这样的错误。只要我们下载的时候勾选要下载的SDK统一下载,就不会出现这样的bug了。
    这里写图片描述

    2.jar和.os引入之后,仍然无法使用(初始化SDK)。
    解决方案是在app的build.gradle加入
android{
    ...
    sourceSets {
           main() {
           jniLibs.srcDirs = ['libs']
           }
    }
}

这在地图的文档没有说到,但在定位的文档才可以找到。小小的吐槽一下百度文档...

地图初始化

  • 添加密匙 (申请百度账号,密匙在这里就不写了。很简单)
<application>  
    <meta-data  
        android:name="com.baidu.lbsapi.API_KEY"  
        android:value="开发者 key" />  
</application>
  • 添加所需权限
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
  • 在布局xml文件中添加地图控件
<com.baidu.mapapi.map.MapView  
    android:id="@+id/bmapView"  
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent"  
    android:clickable="true" />
  • 在应用程序创建时初始化 SDK
public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        /***
         * 初始化定位sdk,建议在Application中创建
         */
        SDKInitializer.initialize(getApplicationContext());
    }
}
  • 管理地图生命周期
 @Override  
    protected void onDestroy() {  
        super.onDestroy();  
        //在activity执行onDestroy时执行mMapView.onDestroy(),实现地图生命周期管理  
        mMapView.onDestroy();  
    }  
    @Override  
    protected void onResume() {  
        super.onResume();  
        //在activity执行onResume时执行mMapView. onResume (),实现地图生命周期管理  
        mMapView.onResume();  
        }  
    @Override  
    protected void onPause() {  
        super.onPause();  
        //在activity执行onPause时执行mMapView. onPause (),实现地图生命周期管理  
        mMapView.onPause();  
        }  
    }

当然,还要在你的AndroidManifest中把你的Application设置成我们自定义的MyApplication

完成以上步骤运行,就能把地图显示出来,在没实现定位功能之前,初始化位置是在北京。

POI检索

  • 初始化POI检索对象
/**
 *实例化
 */
PoiSearch mPoiSearch = PoiSearch.newInstance();
/**
 *回调
 */
OnGetPoiSearchResultListener poiListener = new OnGetPoiSearchResultListener(){  
@Override
    public void onGetPoiResult(PoiResult result){  
    //获取POI检索结果  
    }  
    @Override
    public void onGetPoiDetailResult(PoiDetailResult result){  
    //获取Place详情页检索结果  
    }  
    @Override
    public void onGetPoiIndoorResult(PoiIndoorResult poiIndoorResult) {
    //获取门址类列表
    }
};
/**
 *设置监听
 */
mPoiSearch.setOnGetPoiSearchResultListener(poiListener);
  • 检索
    城市检索
 mPoiSearch.searchInCity((new PoiCitySearchOption())
                .city("深圳")//城市
                .keyword("美食")//检索关键字
                .pageNum(0)//分页编码
                .pageCapacity(5));//每页容量,默认10条

周边检索

mPoiSearch.searchNearby(new PoiNearbySearchOption()
        //搜索结果排序规则,PoiSortType.comprehensive->距离排序
        .sortType(PoiSortType.comprehensive) ->综合排序;
        .radius(1000)//检索半径范围,单位:米
        .location(LatLng location)) //检索位置

区域检索

 mPoiSearch.searchInBound(new PoiBoundSearchOption()
        .bound(LatLngBounds bound)//检索范围
 );

构建LatLngBounds对象

        LatLng southwest = new LatLng(latitude - 0.01, longitude - 0.012);// 西南  
        LatLng northeast = new LatLng(latitude + 0.01, longitude + 0.012);// 东北  
        LatLngBounds bounds = new LatLngBounds.Builder().include(southwest)  
                .include(northeast).build();// 得到一个地理范围对象   

所有检索的结果都在poiListener中回调
在每一个POI中都包含一个"Uid"的字段,如果我们需要知道某个POI的详情,我们可以

mPoiSearch.searchPoiDetail((new PoiDetailSearchOption()).poiUid(uid));

检索的结果同样是在poiListener中回调
详细的文档内容在这里

在回调中得到的是一条条的信息,纯文本看着多没意思,展示的地图还没用上。那我们就可以给每个检索出来的POI在地图上标注起来,瞬间好玩多了!

  • 覆盖物
    自定义 PoiOverlay 类
private class MyPoiOverlay extends PoiOverlay {  
    public MyPoiOverlay(BaiduMap baiduMap) {  
        super(baiduMap);  
    }  
    @Override  
    public boolean onPoiClick(int index) {  
        super.onPoiClick(index);  
        return true;  
    }  
}

在POI检索回调接口中添加自定义的PoiOverlay

public void onGetPoiResult(PoiResult result) {  
    if (result == null || result.error == SearchResult.ERRORNO.RESULT_NOT_FOUND) {  
        return;  
    }  
    if (result.error == SearchResult.ERRORNO.NO_ERROR) {  
        mBaiduMap.clear();  
        //创建PoiOverlay  
        PoiOverlay overlay = new MyPoiOverlay(mBaiduMap);  
        //设置overlay可以处理标注点击事件  
        mBaiduMap.setOnMarkerClickListener(overlay);  
        //设置PoiOverlay数据  
        overlay.setData(result);  
        //添加PoiOverlay到地图中  
        overlay.addToMap();  
        overlay.zoomToSpan();  
        return;  
    }  
}

这样,检索出来的POI在地图上就完成标注了


这里写图片描述

写到这里,简单的地图的POI功能就完成了。

写在最后
简简单单的POI检索当然不能满足我们日益膨胀的心呀!所以现在努力实现定位的功能,到时候再更新blog,分享给那些还没了解定位但即将使用的筒靴一个开篇指引和遇到的坑。加油!
note:
在覆盖物中设计到两个类:PoiOverlay 和OverlayManager在SDK中是没有的,但在官方的Demo中给出。这里是给没有下载Demo的筒靴的一个帮助,希望可以共同进步!

12月6号更新:
今天什么也没改跑了一遍Demo,原先实现的定位功能突然就好了... 船到桥头自然直呀
贴一下定位的代码,基本照搬官方文档上的代码,就不作过多的解释了

    /**
     * 封装定位结果和时间的实体类
     *
     * @author baidu
     */
    class LocationEntity {
        BDLocation location;
        long time;
    }

    private void initlocalMap() {
        mBaiduMap = mMapView.getMap();
        mBaiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL);
        mBaiduMap.setMapStatus(MapStatusUpdateFactory.zoomTo(15));
        mBaiduMap.setMyLocationEnabled(true);
        locService = ((MyApplication) getApplication()).locationService;
        LocationClientOption mOption = locService.getDefaultLocationClientOption();
        mOption.setOpenGps(true);
        mOption.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);
        mOption.setCoorType("bd09ll");

//        locService.setLocationOption(mOption);
//        locService.registerListener(listener);
//        locService.start();

        mClient = new LocationClient(this);
        mClient.setLocOption(mOption);
        mClient.registerLocationListener(listener);
        mClient.start();
    }

    /***
     * 定位结果回调,在此方法中处理定位结果
     */
    BDLocationListener listener = new BDLocationListener() {
        @Override
        public void onReceiveLocation(BDLocation location) {
            if (location != null && (location.getLocType() == 161 || location.getLocType() == 66)) {
                Message locMsg = locHander.obtainMessage();
                Bundle locData;
                locData = Algorithm(location);
                if (locData != null) {
                    locData.putParcelable("loc", location);
                    locMsg.setData(locData);
                    locHander.sendMessage(locMsg);
                }
            }
        }
    };

    /***
     * 平滑策略代码实现方法,主要通过对新定位和历史定位结果进行速度评分,
     * 来判断新定位结果的抖动幅度,如果超过经验值,则判定为过大抖动,进行平滑处理,若速度过快,
     * 则推测有可能是由于运动速度本身造成的,则不进行低速平滑处理 ╭(●`?′●)╯
     *
     * @param location
     * @return Bundle
     */
    private Bundle Algorithm(BDLocation location) {
        Bundle locData = new Bundle();
        double curSpeed = 0;
        if (locationList.isEmpty() || locationList.size() < 2) {
            LocationEntity temp = new LocationEntity();
            temp.location = location;
            temp.time = System.currentTimeMillis();
            locData.putInt("iscalculate", 0);
            locationList.add(temp);
        } else {
            if (locationList.size() > 5)
                locationList.removeFirst();
            double score = 0;
            for (int i = 0; i < locationList.size(); ++i) {
                LatLng lastPoint = new LatLng(locationList.get(i).location.getLatitude(),
                        locationList.get(i).location.getLongitude());
                LatLng curPoint = new LatLng(location.getLatitude(), location.getLongitude());
                double distance = DistanceUtil.getDistance(lastPoint, curPoint);
                curSpeed = distance / (System.currentTimeMillis() - locationList.get(i).time) / 1000;
                score += curSpeed * EARTH_WEIGHT[i];
            }
            if (score > 0.00000999 && score < 0.00005) { // 经验值,开发者可根据业务自行调整,也可以不使用这种算法
                location.setLongitude(
                        (locationList.get(locationList.size() - 1).location.getLongitude() + location.getLongitude())
                                / 2);
                location.setLatitude(
                        (locationList.get(locationList.size() - 1).location.getLatitude() + location.getLatitude())
                                / 2);
                locData.putInt("iscalculate", 1);
            } else {
                locData.putInt("iscalculate", 0);
            }
            LocationEntity newLocation = new LocationEntity();
            newLocation.location = location;
            newLocation.time = System.currentTimeMillis();
            locationList.add(newLocation);

        }
        return locData;
    }

    LatLng point;

    /***
     * 接收定位结果消息,并显示在地图上
     */
    private Handler locHander = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            // TODO Auto-generated method stub
            super.handleMessage(msg);
            try {
                BDLocation location = msg.getData().getParcelable("loc");
                int iscal = msg.getData().getInt("iscalculate");
                if (location != null) {
                    point = new LatLng(location.getLatitude(), location.getLongitude());
                    // 构建Marker图标
                    BitmapDescriptor bitmap = null;
                    if (iscal == 0) {
                        bitmap = BitmapDescriptorFactory.fromResource(R.drawable.huaji); // 非推算结果
                    } else {
                        bitmap = BitmapDescriptorFactory.fromResource(R.drawable.icon_openmap_focuse_mark); // 推算结果
                    }

                    // 构建MarkerOption,用于在地图上添加Marker
                    OverlayOptions option = new MarkerOptions().position(point).icon(bitmap);
                    // 在地图上添加Marker,并显示
                    mBaiduMap.addOverlay(option);
                    mBaiduMap.setMapStatus(MapStatusUpdateFactory.newLatLng(point));
                }
            } catch (Exception e) {
                // TODO: handle exception
            }
        }
    };

这里我们拿到定位返回的LatLng,然后我们检索定位周边的POI
修改原先的search方法

private void search(String searchPoi) {
        mPoiSearch = PoiSearch.newInstance();
        /*mPoiSearch.searchInCity((new PoiCitySearchOption())
                .city("深圳")
                .keyword(searchPoi)
                .pageNum(1)
                .pageCapacity(5));*/
        mPoiSearch.searchNearby(new PoiNearbySearchOption()
                .keyword(searchPoi)
                .location(point)
                .radius(2000)
                .pageNum(0)
                .pageCapacity(5)
                .sortType(PoiSortType.distance_from_near_to_far));
        mPoiSearch.setOnGetPoiSearchResultListener(poiListener);
    }

这样,就只能直接检索你所在位置的POI了

最后编辑于
?著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,992评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,212评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事?!?“怎么了?”我有些...
    开封第一讲书人阅读 159,535评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,197评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,310评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,383评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,409评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,191评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,621评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,910评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,084评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,763评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,403评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,083评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,318评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,946评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,967评论 2 351

推荐阅读更多精彩内容