1. 程式人生 > >android 百度地圖SDK 獲取手機附近POI興趣點列表 (過時)

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個小時(第一次寫-_-||)。

雖然效率很慢,但是我能感覺到自己水平略有提升,在這裡希望和我一樣正在奮鬥的程式設計師繼續加油。