[Android]百度地圖POI檢索

寫(xiě)在前面
本來(lái)想使用百度定位的SDK把定位功能實(shí)現(xiàn)了斩萌,可無(wú)奈遇上個(gè)坑到寫(xiě)這篇blog為止都還沒(méi)有解決畅形。故所以把使用百度地圖SDK實(shí)現(xiàn)簡(jiǎn)單的POI檢索功能和遇到的坑先做一個(gè)總結(jié)置吓。

下載.os和jar包

  1. 如果需要使用自定義的功能沦补,最好不要分別下載踢俄。
    例如之前我只是想先簡(jiǎn)單的實(shí)現(xiàn)POI檢索功能蚊逢,所以只下載了跟百度地圖相關(guān)的SDK,實(shí)現(xiàn)了之后覺(jué)得單調(diào)箫章,決定加入定位功能的時(shí)候再單獨(dú)去下載了定位相關(guān)的SDK烙荷,坑就出現(xiàn)了,引入.os和jar之后檬寂,
    出現(xiàn) java.lang.NoSuchMethodError: No direct method <init> 這樣的錯(cuò)誤终抽。只要我們下載的時(shí)候勾選要下載的SDK統(tǒng)一下載,就不會(huì)出現(xiàn)這樣的bug了桶至。
    這里寫(xiě)圖片描述

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

這在地圖的文檔沒(méi)有說(shuō)到镣屹,但在定位的文檔才可以找到圃郊。小小的吐槽一下百度文檔...

地圖初始化

  • 添加密匙 (申請(qǐng)百度賬號(hào),密匙在這里就不寫(xiě)了女蜈。很簡(jiǎn)單)
<application>  
    <meta-data  
        android:name="com.baidu.lbsapi.API_KEY"  
        android:value="開(kāi)發(fā)者 key" />  
</application>
  • 添加所需權(quán)限
<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" />
  • 在應(yīng)用程序創(chuàng)建時(shí)初始化 SDK
public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        /***
         * 初始化定位sdk持舆,建議在Application中創(chuàng)建
         */
        SDKInitializer.initialize(getApplicationContext());
    }
}
  • 管理地圖生命周期
 @Override  
    protected void onDestroy() {  
        super.onDestroy();  
        //在activity執(zhí)行onDestroy時(shí)執(zhí)行mMapView.onDestroy(),實(shí)現(xiàn)地圖生命周期管理  
        mMapView.onDestroy();  
    }  
    @Override  
    protected void onResume() {  
        super.onResume();  
        //在activity執(zhí)行onResume時(shí)執(zhí)行mMapView. onResume ()伪窖,實(shí)現(xiàn)地圖生命周期管理  
        mMapView.onResume();  
        }  
    @Override  
    protected void onPause() {  
        super.onPause();  
        //在activity執(zhí)行onPause時(shí)執(zhí)行mMapView. onPause ()逸寓,實(shí)現(xiàn)地圖生命周期管理  
        mMapView.onPause();  
        }  
    }

當(dāng)然,還要在你的AndroidManifest中把你的Application設(shè)置成我們自定義的MyApplication

完成以上步驟運(yùn)行,就能把地圖顯示出來(lái)覆山,在沒(méi)實(shí)現(xiàn)定位功能之前竹伸,初始化位置是在北京。

POI檢索

  • 初始化POI檢索對(duì)象
/**
 *實(shí)例化
 */
PoiSearch mPoiSearch = PoiSearch.newInstance();
/**
 *回調(diào)
 */
OnGetPoiSearchResultListener poiListener = new OnGetPoiSearchResultListener(){  
@Override
    public void onGetPoiResult(PoiResult result){  
    //獲取POI檢索結(jié)果  
    }  
    @Override
    public void onGetPoiDetailResult(PoiDetailResult result){  
    //獲取Place詳情頁(yè)檢索結(jié)果  
    }  
    @Override
    public void onGetPoiIndoorResult(PoiIndoorResult poiIndoorResult) {
    //獲取門(mén)址類列表
    }
};
/**
 *設(shè)置監(jiān)聽(tīng)
 */
mPoiSearch.setOnGetPoiSearchResultListener(poiListener);
  • 檢索
    城市檢索
 mPoiSearch.searchInCity((new PoiCitySearchOption())
                .city("深圳")//城市
                .keyword("美食")//檢索關(guān)鍵字
                .pageNum(0)//分頁(yè)編碼
                .pageCapacity(5));//每頁(yè)容量簇宽,默認(rèn)10條

周邊檢索

mPoiSearch.searchNearby(new PoiNearbySearchOption()
        //搜索結(jié)果排序規(guī)則勋篓,PoiSortType.comprehensive->距離排序
        .sortType(PoiSortType.comprehensive) ->綜合排序;
        .radius(1000)//檢索半徑范圍晦毙,單位:米
        .location(LatLng location)) //檢索位置

區(qū)域檢索

 mPoiSearch.searchInBound(new PoiBoundSearchOption()
        .bound(LatLngBounds bound)//檢索范圍
 );

構(gòu)建LatLngBounds對(duì)象

        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();// 得到一個(gè)地理范圍對(duì)象   

所有檢索的結(jié)果都在poiListener中回調(diào)
在每一個(gè)POI中都包含一個(gè)"Uid"的字段生巡,如果我們需要知道某個(gè)POI的詳情,我們可以

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

檢索的結(jié)果同樣是在poiListener中回調(diào)
詳細(xì)的文檔內(nèi)容在這里

在回調(diào)中得到的是一條條的信息见妒,純文本看著多沒(méi)意思孤荣,展示的地圖還沒(méi)用上。那我們就可以給每個(gè)檢索出來(lái)的POI在地圖上標(biāo)注起來(lái)须揣,瞬間好玩多了盐股!

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

在POI檢索回調(diào)接口中添加自定義的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();  
        //創(chuàng)建PoiOverlay  
        PoiOverlay overlay = new MyPoiOverlay(mBaiduMap);  
        //設(shè)置overlay可以處理標(biāo)注點(diǎn)擊事件  
        mBaiduMap.setOnMarkerClickListener(overlay);  
        //設(shè)置PoiOverlay數(shù)據(jù)  
        overlay.setData(result);  
        //添加PoiOverlay到地圖中  
        overlay.addToMap();  
        overlay.zoomToSpan();  
        return;  
    }  
}

這樣,檢索出來(lái)的POI在地圖上就完成標(biāo)注了


這里寫(xiě)圖片描述

寫(xiě)到這里耻卡,簡(jiǎn)單的地圖的POI功能就完成了疯汁。

寫(xiě)在最后
簡(jiǎn)簡(jiǎn)單單的POI檢索當(dāng)然不能滿足我們?nèi)找媾蛎浀男难剑∷袁F(xiàn)在努力實(shí)現(xiàn)定位的功能卵酪,到時(shí)候再更新blog幌蚊,分享給那些還沒(méi)了解定位但即將使用的筒靴一個(gè)開(kāi)篇指引和遇到的坑谤碳。加油!
note:
在覆蓋物中設(shè)計(jì)到兩個(gè)類:PoiOverlay 和OverlayManager在SDK中是沒(méi)有的溢豆,但在官方的Demo中給出蜒简。這里是給沒(méi)有下載Demo的筒靴的一個(gè)幫助,希望可以共同進(jìn)步!

12月6號(hào)更新:
今天什么也沒(méi)改跑了一遍Demo漩仙,原先實(shí)現(xiàn)的定位功能突然就好了... 船到橋頭自然直呀
貼一下定位的代碼搓茬,基本照搬官方文檔上的代碼,就不作過(guò)多的解釋了

    /**
     * 封裝定位結(jié)果和時(shí)間的實(shí)體類
     *
     * @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();
    }

    /***
     * 定位結(jié)果回調(diào)队他,在此方法中處理定位結(jié)果
     */
    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);
                }
            }
        }
    };

    /***
     * 平滑策略代碼實(shí)現(xiàn)方法卷仑,主要通過(guò)對(duì)新定位和歷史定位結(jié)果進(jìn)行速度評(píng)分,
     * 來(lái)判斷新定位結(jié)果的抖動(dòng)幅度麸折,如果超過(guò)經(jīng)驗(yàn)值锡凝,則判定為過(guò)大抖動(dòng),進(jìn)行平滑處理,若速度過(guò)快磕谅,
     * 則推測(cè)有可能是由于運(yùn)動(dòng)速度本身造成的私爷,則不進(jìn)行低速平滑處理 ╭(●`?′●)╯
     *
     * @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) { // 經(jīng)驗(yàn)值,開(kāi)發(fā)者可根據(jù)業(yè)務(wù)自行調(diào)整,也可以不使用這種算法
                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;

    /***
     * 接收定位結(jié)果消息膊夹,并顯示在地圖上
     */
    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());
                    // 構(gòu)建Marker圖標(biāo)
                    BitmapDescriptor bitmap = null;
                    if (iscal == 0) {
                        bitmap = BitmapDescriptorFactory.fromResource(R.drawable.huaji); // 非推算結(jié)果
                    } else {
                        bitmap = BitmapDescriptorFactory.fromResource(R.drawable.icon_openmap_focuse_mark); // 推算結(jié)果
                    }

                    // 構(gòu)建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了

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末尸饺,一起剝皮案震驚了整個(gè)濱河市进统,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌浪听,老刑警劉巖螟碎,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異迹栓,居然都是意外死亡掉分,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門(mén)克伊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)酥郭,“玉大人,你說(shuō)我怎么就攤上這事愿吹〔淮樱” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵犁跪,是天一觀的道長(zhǎng)椿息。 經(jīng)常有香客問(wèn)我歹袁,道長(zhǎng),這世上最難降的妖魔是什么寝优? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任条舔,我火速辦了婚禮,結(jié)果婚禮上倡勇,老公的妹妹穿的比我還像新娘逞刷。我一直安慰自己,他們只是感情好妻熊,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布夸浅。 她就那樣靜靜地躺著,像睡著了一般扔役。 火紅的嫁衣襯著肌膚如雪帆喇。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,166評(píng)論 1 284
  • 那天亿胸,我揣著相機(jī)與錄音坯钦,去河邊找鬼。 笑死侈玄,一個(gè)胖子當(dāng)著我的面吹牛婉刀,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播序仙,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼突颊,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了潘悼?” 一聲冷哼從身側(cè)響起律秃,我...
    開(kāi)封第一講書(shū)人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎治唤,沒(méi)想到半個(gè)月后棒动,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡宾添,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年船惨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片辞槐。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡掷漱,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出榄檬,到底是詐尸還是另有隱情卜范,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布鹿榜,位于F島的核電站海雪,受9級(jí)特大地震影響锦爵,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜奥裸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一险掀、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧湾宙,春花似錦樟氢、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至伟恶,卻和暖如春碴开,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背博秫。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工潦牛, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人挡育。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓巴碗,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親即寒。 傳聞我的和親對(duì)象是個(gè)殘疾皇子良价,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容