android 百度地圖SDK 獲取手機附近POI興趣點列表 (過時)
文章內容已經過時~大家去百度官方api學習。
http://developer.baidu.com/map/
http://lbsyun.baidu.com/sdk/download
功能描述:獲取手機自身附近的興趣點(Poi, 之後使用Poi表示興趣點)列表,顯示在listview中先上效果圖
顯而易見的是,圖中只有一個簡單的listview,然後每個item分別包含Poi的名字,地址和手機到poi所在的距離。由於我在學校裡,附近只有5個ATM。
好了如果你看到的這個效果是你所需要的功能,內心是不是有點小激動呢?
現在我們來分析這個實現的思路:
零,做好之前的準備工作
一,首先是要得到手機自身的位置
二,然後根據這個位置和你要找的POI的名字來得到附近的POI列表
實現的步驟:
向專案中加入百度地圖SDK。
登入後來訪問 下載地址http://developer.baidu.com/map/sdkandev-download.htm全部商情下載
下載後解壓成
在BaiduMap_AndroidSDK_v2.4.1_Sample - > BaiduMapsApiDemo - >庫以及庫 - > armeabi中
將 baidumapapi_v2_4_1.jar locSDK_3.1.jar libBaiduMapSDK_v2_4_1.so liblocSDK3.so以相同模式拷到我們當前新建的專案中
然後新增到構建路徑
然後記得申請的關鍵:http://developer.baidu.com/map/android-mobile-apply-key.htm跟著提示走,這裡就不敘述了。
東西準備好了,開始編寫程式碼
首先當然是MainActivity.java
public class MainActivity extends Activity { final static String TAG = "MainActivity"; private static final int MSG_SELFPOINT = 1; private static final int MSG_MPOIINFOLIST = 2; private static final String POI_NAME = "ATM"; // 搜尋指定興趣點名稱 private static final int SCAN_SPAN = 60 * 1000; // 重新整理時間 private static final int POI_DISTANCE = 1000; // 搜尋半徑 private LocationClient locationClient = null; private MKSearch mMKSearch = null; private GeoPoint selfPoint = null; // 自身經緯度 private ListView poiInfoList; private List<poiinfo> mPoiInfoList = null; @SuppressLint("HandlerLeak") private Handler handler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case MSG_SELFPOINT: // 獲得自身經緯度 default: Double[] locNum = (Double[]) msg.obj; // 用給定的經緯度構造一個GeoPoint(緯度,經度) selfPoint = new GeoPoint((int) (locNum[0] * 1E6), (int) (locNum[1] * 1E6)); // 執行搜尋周邊興趣點列表 mMKSearch.poiSearchNearBy(POI_NAME, selfPoint, POI_DISTANCE); break; case MSG_MPOIINFOLIST: // 獲得周邊興趣點列表 PoiAdapter adapter = new PoiAdapter(getApplicationContext(), mPoiInfoList); adapter.notifyDataSetChanged(); poiInfoList.setAdapter(adapter); break; } } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); initMapManagerAndMKSearch(); setContentView(R.layout.activity_main); initViews(); startLocationClient(); } @Override protected void onDestroy() { super.onDestroy(); if (locationClient != null && locationClient.isStarted()) { locationClient.stop(); locationClient = null; } } /** * 使用地圖sdk前需先初始化BMapManager. BMapManager是全域性的,可為多個MapView共用,它需要地圖模組建立前建立, * 並在地圖地圖模組銷燬後銷燬,只要還有地圖模組在使用,BMapManager就不應該銷燬 */ private void initMapManagerAndMKSearch() { MyApplication app = (MyApplication) this.getApplication(); if (app.mBMapManager == null) { app.mBMapManager = new BMapManager(getApplicationContext()); /** * 如果BMapManager沒有初始化則初始化BMapManager */ app.mBMapManager.init(new MyApplication.MyGeneralListener()); } mMKSearch = new MKSearch(); mMKSearch.init(app.mBMapManager, new MKSearchListener() { @Override public void onGetWalkingRouteResult(MKWalkingRouteResult result, int iError) { // 步行路線搜尋結果 } @Override public void onGetTransitRouteResult(MKTransitRouteResult result, int iError) { // 公交換乘路線搜尋結果 } @Override public void onGetSuggestionResult(MKSuggestionResult arg0, int arg1) { // TODO Auto-generated method stub } @Override public void onGetShareUrlResult(MKShareUrlResult arg0, int arg1, int arg2) { // TODO Auto-generated method stub } @Override public void onGetPoiResult(MKPoiResult result, int type, int iError) { // POI搜尋結果(範圍檢索、城市POI檢索、周邊檢索) if (result == null) { Log.i(TAG, "周圍一定範圍內沒有檢索出POI目標"); Toast.makeText(getApplicationContext(), "周圍一定範圍內沒有檢索出POI目標", Toast.LENGTH_SHORT).show(); return; } mPoiInfoList = new ArrayList<poiinfo>(); PoiInfo mPoiInfo = null; for (MKPoiInfo mMKPoiInfo : result.getAllPoi()) { // 計算自身與目的地之間的距離 int distanceM = (int) DistanceUtil.getDistance(selfPoint, mMKPoiInfo.pt); mPoiInfo = new PoiInfo(mMKPoiInfo.name, mMKPoiInfo.address, distanceM); mPoiInfoList.add(mPoiInfo); } Message.obtain(handler, MSG_MPOIINFOLIST).sendToTarget(); } @Override public void onGetPoiDetailSearchResult(int arg0, int arg1) { // TODO Auto-generated method stub } @Override public void onGetDrivingRouteResult(MKDrivingRouteResult result, int iError) { // 駕車路線搜尋結果 } @Override public void onGetBusDetailResult(MKBusLineResult arg0, int arg1) { // TODO Auto-generated method stub } @Override public void onGetAddrResult(MKAddrInfo result, int iError) { // 根據經緯度搜索地址資訊結果 } }); } private void startLocationClient() { locationClient = new LocationClient(getApplicationContext()); locationClient.setLocOption(setLocationOption()); // 註冊位置監聽器 locationClient.registerLocationListener(new BDLocationListener() { @Override public void onReceiveLocation(BDLocation location) { if (location == null) { return; } double latitude = location.getLatitude(); // 緯度 double longitude = location.getLongitude(); // 經度 Double[] locNum = { latitude, longitude }; Message.obtain(handler, MSG_SELFPOINT, locNum).sendToTarget(); locationClient.stop(); // 停止查詢自身經緯度 } @Override public void onReceivePoi(BDLocation location) { } }); locationClient.start(); // 開始查詢自身經緯度 locationClient.requestLocation(); } private LocationClientOption setLocationOption() { // 設定定位條件 LocationClientOption option = new LocationClientOption(); option.setServiceName("com.baidu.location.service_v2.9"); // 需要地址資訊,設定為其他任何值(string型別,且不能為null)時,都表示無地址資訊。 option.setAddrType("all"); // 設定是否返回POI的電話和地址等詳細資訊。預設值為false,即不返回POI的電話和地址資訊。 option.setPoiExtraInfo(false); // 設定產品線名稱。強烈建議您使用自定義的產品線名稱,方便我們以後為您提供更高效準確的定位服務。 option.setProdName("定位我當前的位置"); // 設定GPS,使用gps前提是使用者硬體開啟gps。預設是不開啟gps的。 option.setOpenGps(true); // 定位的時間間隔,單位:ms // 當所設的整數值大於等於1000(ms)時,定位SDK內部使用定時定位模式。 option.setScanSpan(SCAN_SPAN); // 查詢範圍,預設值為500,即以當前定位位置為中心的半徑大小。 option.setPoiDistance(POI_DISTANCE); // 禁用啟用快取定位資料 option.disableCache(true); // 座標系型別,百度手機地圖對外介面中的座標系預設是bd09ll option.setCoorType("bd09ll"); // 設定最多可返回的POI個數,預設值為3。由於POI查詢比較耗費流量,設定最多返回的POI個數,以便節省流量。 option.setPoiNumber(0); // 設定定位方式的優先順序。 // 當gps可用,而且獲取了定位結果時,不再發起網路請求,直接返回給使用者座標。這個選項適合希望得到準確座標位置的使用者。如果gps不可用,再發起網路請求,進行定位。 option.setPriority(LocationClientOption.NetWorkFirst); return option; } private void initViews() { poiInfoList = (ListView) findViewById(R.id.lv_poiInfoList); } } </poiinfo></poiinfo>
從onCreate走起,先初始化BMapManager,然後載入佈局,最後初始化LocationClient配置引數start()以及requestLocation()後
通過registerLocationListener中onReceiveLocation()可獲得自身經緯度,經緯度手柄一下呼叫MKSearch.poiSearchNearBy()搜尋周邊興趣點列表
通過MKSearchListener中onGetPoiResult()列表配置。再處理一下載入UI。
然後是MyApplication.java
public class MyApplication extends Application {
private static MyApplication mInstance = null;
public boolean m_bKeyRight = true;
BMapManager mBMapManager = null;
@Override
public void onCreate() {
super.onCreate();
mInstance = this;
initEngineManager(this);
}
public void initEngineManager(Context context) {
if (mBMapManager == null) {
mBMapManager = new BMapManager(context);
}
if (!mBMapManager.init(new MyGeneralListener())) {
Toast.makeText(MyApplication.getInstance().getApplicationContext(),
"BMapManager 初始化錯誤!", Toast.LENGTH_LONG).show();
}
}
public static MyApplication getInstance() {
return mInstance;
}
// 常用事件監聽,用來處理通常的網路錯誤,授權驗證錯誤等
static class MyGeneralListener implements MKGeneralListener {
@Override
public void onGetNetworkState(int iError) {
if (iError == MKEvent.ERROR_NETWORK_CONNECT) {
Toast.makeText(
MyApplication.getInstance().getApplicationContext(),
"您的網路出錯啦!", Toast.LENGTH_LONG).show();
} else if (iError == MKEvent.ERROR_NETWORK_DATA) {
Toast.makeText(
MyApplication.getInstance().getApplicationContext(),
"輸入正確的檢索條件!", Toast.LENGTH_LONG).show();
}
// ...
}
@Override
public void onGetPermissionState(int iError) {
// 非零值表示key驗證未通過
if (iError != 0) {
// 授權Key錯誤:
Toast.makeText(
MyApplication.getInstance().getApplicationContext(),
"請在 DemoApplication.java檔案輸入正確的授權Key,並檢查您的網路連線是否正常!error: "
+ iError, Toast.LENGTH_LONG).show();
MyApplication.getInstance().m_bKeyRight = false;
} else {
MyApplication.getInstance().m_bKeyRight = true;
Toast.makeText(
MyApplication.getInstance().getApplicationContext(),
"key認證成功", Toast.LENGTH_LONG).show();
}
}
}
}
然後清單檔案:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="7"
android:targetSdkVersion="10" />
<permission android:name="android.permission.BAIDU_LOCATION_SERVICE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.BAIDU_LOCATION_SERVICE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_LOGS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<application
android:name="MyApplication"
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<meta-data
android:name="com.baidu.lbsapi.API_KEY"
android:value="SebBBgHgrqTVjr8WXAYP9TCl" />
<activity android:name="com.example.android.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:permission="android.permission.BAIDU_LOCATION_SERVICE"
android:process=":remote" >
<intent-filter>
<action android:name="com.baidu.location.service_v2.4" />
</intent-filter>
</service>
</application>
</manifest>
這裡注意需要在中的android:值填寫關鍵值還有一個百度自己的位置服務的註冊。
最後佈局檔案:activity_main.xml和item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<com.baidu.mapapi.map.MapView
android:id="@+id/map_View"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true"
android:visibility="gone" />
<ListView
android:id="@+id/lv_poiInfoList"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#fff" />
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="@+id/tv_poiName"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_poiAddress"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_poiDistance"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
列表介面卡:
public class PoiAdapter extends BaseAdapter {
List<poiinfo> poiInfoList;
@SuppressWarnings("unused")
private Context context;
private LayoutInflater inflater;
public PoiAdapter(Context context, List<poiinfo> poiInfoList) {
this.poiInfoList = poiInfoList;
this.context = context;
inflater = LayoutInflater.from(context); // 建立檢視容器並設定上下文
}
@Override
public int getCount() {
return poiInfoList != null ? poiInfoList.size() : 0;
}
@Override
public Object getItem(int postion) {
return poiInfoList != null ? poiInfoList.get(postion) : null;
}
@Override
public long getItemId(int postion) {
return postion;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = null;
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = inflater.inflate(R.layout.item, null);
viewHolder.poiName = (TextView) convertView.findViewById(R.id.tv_poiName);
viewHolder.poiAddress = (TextView) convertView.findViewById(R.id.tv_poiAddress);
viewHolder.poiDistance = (TextView) convertView.findViewById(R.id.tv_poiDistance);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
PoiInfo mPoiInfo = poiInfoList.get(position);
viewHolder.poiName.setText(mPoiInfo.getName());
viewHolder.poiAddress.setText(mPoiInfo.getAddress());
viewHolder.poiDistance.setText(mPoiInfo.getDistance().toString());
return convertView;
}
final class ViewHolder {
TextView poiName;
TextView poiAddress;
TextView poiDistance;
}
}
</poiinfo></poiinfo>
列表實體:
package com.example.android;
public class PoiInfo {
private String name;
private String address;
private Integer distance;
public PoiInfo() {
super();
}
public PoiInfo(String name, String address, Integer distance) {
super();
this.name = name;
this.address = address;
this.distance = distance;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Integer getDistance() {
return distance;
}
public void setDistance(Integer distance) {
this.distance = distance;
}
@Override
public String toString() {
return "POIInfo [name=" + name + ", address=" + address + ", distance="
+ distance + "]";
}
}
到這裡就完成了。
然後宣告一下由於才剛學1個月的android開發,本人水平有限,對於這個功能,應該還有不足之處和一些BUG,
做出這個demo花了我6個小時時間編碼,查閱百度地圖api以及一些部落格。寫出這文章用了2個小時(第一次寫-_-||)。
雖然效率很慢,但是我能感覺到自己水平略有提升,在這裡希望和我一樣正在奮鬥的程式設計師繼續加油。