[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="開發(fā)者 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" />
  • 在應用程序創(chuàng)建時初始化 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時執(zhí)行mMapView.onDestroy(),實現地圖生命周期管理  
        mMapView.onDestroy();  
    }  
    @Override  
    protected void onResume() {  
        super.onResume();  
        //在activity執(zhí)行onResume時執(zhí)行mMapView. onResume (),實現地圖生命周期管理  
        mMapView.onResume();  
        }  
    @Override  
    protected void onPause() {  
        super.onPause();  
        //在activity執(zhí)行onPause時執(zhí)行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) {
    //獲取門址類列表
    }
};
/**
 *設置監(jiān)聽
 */
mPoiSearch.setOnGetPoiSearchResultListener(poiListener);
  • 檢索
    城市檢索
 mPoiSearch.searchInCity((new PoiCitySearchOption())
                .city("深圳")//城市
                .keyword("美食")//檢索關鍵字
                .pageNum(0)//分頁編碼
                .pageCapacity(5));//每頁容量,默認10條

周邊檢索

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

區(qū)域檢索

 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();  
        //創(chuàng)建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) { // 經驗值,開發(fā)者可根據業(yè)務自行調整,也可以不使用這種算法
                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閱讀 227,572評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 98,071評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 175,409評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,569評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,360評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,895評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,979評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,123評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 48,643評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,559評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,742評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,250評論 5 356
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 43,981評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,363評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,622評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,354評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,707評論 2 370

推薦閱讀更多精彩內容