在android開發中地圖和定位是不少軟件不可或缺的內容,這些特點功能也給人們帶來了不少方便。定位通常分爲三種發方案:即GPS定位、Google網絡定位以及基站定位android
最簡單的手機定位方式固然是經過GPS模塊(如今大部分的智能機應該都有了)。GPS方式準確度是最高的,可是它的缺點也很是明顯:1,比較耗電;2,絕大部分用戶默認不開啓GPS模塊;3,從GPS模塊啓動到獲取第一次定位數據,可能須要比較長的時間;4,室內幾乎沒法使用。這其中,缺點2,3都是比較致命的。須要指出的是,GPS走的是衛星通訊的通道,在沒有網絡鏈接的狀況下也能用。
另一種常見的定位方式是基站定位。大體思路就是採集到手機上的基站ID號(cellid)和其它的一些信息(MNC,MCC,LAC等等),而後經過網絡訪問一些定位服務,獲取並返回對應的經緯度座標。基站定位的精確度不如GPS,但好處是可以在室內用,只要網絡通暢就行。
還有Wifi定位。和基站定位相似,這種方式是經過獲取當前所用的wifi的一些信息,而後訪問網絡上的定位服務以得到經緯度座標。由於它和基站定位其實都須要使用網絡,因此在Android也統稱爲Network方式。
最後須要解釋一點的是AGPS方式。不少人將它和基站定位混爲一談,但其實AGPS的本質仍然是GPS,只是它會使用基站信息對獲取GPS進行輔助,而後還能對獲取到的GPS結果進行修正,因此AGPS要比傳統的GPS更快,準確度略高。git
本文分別介紹GPS定位、以及基於Google的網絡Wifi定位,以及最後的使用百度LBS的定位(百度LBS的定位功能比較強大,集成了GPS,網絡wifi以及基站定位三種定位方法)。主要用例就是利用這三種方法獲取位置經緯度,以及利用經緯度來獲取所在的城市及區域json
而根據經緯度來獲取所在位置的城市及區域所有都是採用百度地圖的API:http://api.map.baidu.com/geocoder?output=json&location=39.983228,116.491146key=您的keyapi
,這個key須要你本身申請百度開發者帳號來獲得的。網絡
首先來看看定位實例效果圖以下:app
1.GPS定位ide
(1)打開GPS設置函數
private void openGPSSettings() { LocationManager alm = (LocationManager) this .getSystemService(Context.LOCATION_SERVICE); if (alm.isProviderEnabled(android.location.LocationManager.GPS_PROVIDER)) { Toast.makeText(this, "GPS模塊正常", Toast.LENGTH_SHORT).show(); doWork(); return; } else { Toast.makeText(this, "請開啓GPS!", Toast.LENGTH_SHORT).show(); Intent intent = new Intent(Settings.ACTION_SECURITY_SETTINGS); startActivityForResult(intent, 0); // 此爲設置完成後返回到獲取界面 } }
(2)經過GPS獲取經緯度信息ui
private void doWork() { String msg = ""; LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); Criteria criteria = new Criteria(); // 得到最好的定位效果 criteria.setAccuracy(Criteria.ACCURACY_FINE); criteria.setAltitudeRequired(false); criteria.setBearingRequired(false); criteria.setCostAllowed(false); // 使用省電模式 criteria.setPowerRequirement(Criteria.POWER_LOW); // 得到當前的位置提供者 String provider = locationManager.getBestProvider(criteria, true); // 得到當前的位置 Location location = locationManager.getLastKnownLocation(provider); double latitude = location.getLatitude(); double longitude = location.getLongitude(); locationString = "&location=" + latitude + "," + longitude; keyString = "&key=您的key"; questURL = questURL + locationString + keyString; new ReadJSONFeedTask().execute(questURL); }
(3)由經緯度獲取所在城市和區域的ReadJSONFeedTask類的實現:this
/** * 由經緯度獲取所在的城市及區域信息 * @author caizhiming * */ private class ReadJSONFeedTask extends AsyncTask<String, Void, String> { StringBuilder stringBuilder = new StringBuilder(); @Override protected String doInBackground(String... urls) { // TODO Auto-generated method stub return readJSONFeed(urls[0]); } @Override protected void onPostExecute(String result) { // TODO Auto-generated method stub String strItem; try { JSONObject jsonObject = new JSONObject(result); JSONObject resultObject = jsonObject.getJSONObject("result"); JSONObject addressComponentObject = resultObject .getJSONObject("addressComponent"); String city = addressComponentObject.getString("city"); String district = addressComponentObject.getString("district"); city = "城市:" + city; district = " 區:" + district; stringBuilder.append(city + district); textView.setText(stringBuilder.toString()); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } /** * 請求json數據 * @param url * @author caizhiming */ public String readJSONFeed(String url) { StringBuilder stringBuilder = new StringBuilder(); HttpClient client = new DefaultHttpClient(); HttpGet httpGet = new HttpGet(url); HttpResponse response; try { response = client.execute(httpGet); StatusLine statusLine = response.getStatusLine(); int statusCode = statusLine.getStatusCode(); if (statusCode == 200) { HttpEntity entity = response.getEntity(); InputStream content = entity.getContent(); BufferedReader reader = new BufferedReader( new InputStreamReader(content)); String line; while ((line = reader.readLine()) != null) { stringBuilder.append(line); } } else { Log.e("JSON", "Failed to download file"); } } catch (ClientProtocolException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return stringBuilder.toString(); }
2. 網絡WIFI定位
(1) 經過網絡WIFI來獲取經緯度信息:
/* ====================Google Location By NetWork=========================== */ private void getLocationByNetwork() { LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); LocationListener locationListener = new LocationListener() { // Provider的狀態在可用、暫時不可用和無服務三個狀態直接切換時觸發此函數 @Override public void onStatusChanged(String provider, int status, Bundle extras) { } // Provider被enable時觸發此函數,好比GPS被打開 @Override public void onProviderEnabled(String provider) { } // Provider被disable時觸發此函數,好比GPS被關閉 @Override public void onProviderDisabled(String provider) { } // 當座標改變時觸發此函數,若是Provider傳進相同的座標,它就不會被觸發 @Override public void onLocationChanged(Location location) { if (location != null) { Log.e("Map", "Location changed : Lat: " + location.getLatitude() + " Lng: " + location.getLongitude()); } } }; locationManager.requestLocationUpdates( LocationManager.NETWORK_PROVIDER, 1000, 0, locationListener); Location location = locationManager .getLastKnownLocation(LocationManager.NETWORK_PROVIDER); double latitude = 0; double longitude = 0; if (location != null) { latitude = location.getLatitude(); // 經度 longitude = location.getLongitude(); // 緯度 } locationString = "&location=" + latitude + "," + longitude; keyString = "&key=你的key"; questURL = questURL + locationString + keyString; Toast.makeText(this, locationString, Toast.LENGTH_LONG).show(); new ReadJSONFeedTask().execute(questURL); }
(2)由經緯度獲取所在城市和區域的ReadJSONFeedTask類的實現:
/**
* 由經緯度獲取所在的城市及區域信息
* @author caizhiming
*
*/
private class ReadJSONFeedTask extends AsyncTask<String, Void, String> {
StringBuilder stringBuilder = new StringBuilder(); @Override protected String doInBackground(String... urls) { // TODO Auto-generated method stub return readJSONFeed(urls[0]); } @Override protected void onPostExecute(String result) { // TODO Auto-generated method stub String strItem; try { JSONObject jsonObject = new JSONObject(result); JSONObject resultObject = jsonObject.getJSONObject("result"); JSONObject addressComponentObject = resultObject .getJSONObject("addressComponent"); String city = addressComponentObject.getString("city"); String district = addressComponentObject.getString("district"); city = "城市:" + city; district = " 區:" + district; stringBuilder.append(city + district); textView.setText(stringBuilder.toString()); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } /** * 請求json數據 * @param url * @author caizhiming */ public String readJSONFeed(String url) { StringBuilder stringBuilder = new StringBuilder(); HttpClient client = new DefaultHttpClient(); HttpGet httpGet = new HttpGet(url); HttpResponse response; try { response = client.execute(httpGet); StatusLine statusLine = response.getStatusLine(); int statusCode = statusLine.getStatusCode(); if (statusCode == 200) { HttpEntity entity = response.getEntity(); InputStream content = entity.getContent(); BufferedReader reader = new BufferedReader( new InputStreamReader(content)); String line; while ((line = reader.readLine()) != null) { stringBuilder.append(line); } } else { Log.e("JSON", "Failed to download file"); } } catch (ClientProtocolException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return stringBuilder.toString(); }
3.使用百度LBS的SDK定位
(1)導入百度的LBS的SDK開發Jar包,開發者能夠到百度開發者中心去下載便可。即BaiduLBS_Android.jar包,放在項目的libs目錄下便可。須要注意的是,同時須要在libs目錄下創建armeabi目錄,並在該目錄下放sdk中的liblocSDK4d.so文件,這樣才能使用sdk。
(2)初始化百度LBS定位信息,包括初始化定位客戶端,定位監聽器,定位模式等信息:
/** * baidu lbs location * * @author caizhiming */ private void InitLocation() { Log.v("LocationActivity", "InitLocation"); mLocationClient = new LocationClient(this.getApplicationContext()); // 聲明LocationClient類 myListener = new MyLocationListener(); mLocationClient.registerLocationListener(myListener); // 註冊監聽函數 LocationClientOption option = new LocationClientOption(); option.setLocationMode(tempMode);// 設置定位模式 option.setCoorType(tempcoor);// 返回的定位結果是百度經緯度,默認值gcj02 int span = 3000; option.setScanSpan(span);// 設置發起定位請求的間隔時間爲5000ms option.setIsNeedAddress(false); mLocationClient.setLocOption(option); }
另外,還須要在AndroidMenifest.xml中配置key信息以下:
<!-- meta-data須要寫在application中 --> <meta-data android:name="com.baidu.lbsapi.API_KEY" android:value="您的key" />
最後還須要AndroidMenifest.xml中配置相應須要的權限以下:
<!-- baidu lbs --> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" > </uses-permission> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" > </uses-permission> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" > </uses-permission> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" > </uses-permission> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" > </uses-permission> <uses-permission android:name="android.permission.READ_PHONE_STATE" > </uses-permission> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" > </uses-permission> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" > </uses-permission> <uses-permission android:name="android.permission.READ_LOGS" > </uses-permission> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WRITE_SETTINGS" />
(3)啓動百度LBS的定位服務並獲取經緯度等信息:
/** * baidu lbs location * * @author caizhiming */ private void getLocationByBaiduLBS() { Log.v("LocationActivity", "getLocationByBaiduLBS"); mLocationClient.start(); } /** * baidu lbs location * * @author caizhiming */ public class MyLocationListener implements BDLocationListener { @Override public void onReceiveLocation(BDLocation location) { Log.v("LocationActivity", "MyLocationListener-onReceiveLocation"); if (location == null) return; StringBuffer sb = new StringBuffer(256); sb.append("time : "); sb.append(location.getTime()); sb.append("\nerror code : "); sb.append(location.getLocType()); sb.append("\nlatitude : "); sb.append(location.getLatitude()); sb.append("\nlontitude : "); sb.append(location.getLongitude()); sb.append("\nradius : "); sb.append(location.getRadius()); if (location.getLocType() == BDLocation.TypeGpsLocation) { sb.append("\nspeed : "); sb.append(location.getSpeed()); sb.append("\nsatellite : "); sb.append(location.getSatelliteNumber()); } else if (location.getLocType() == BDLocation.TypeNetWorkLocation) { sb.append("\naddr : "); sb.append(location.getAddrStr()); } logMsg(sb.toString()); locationString = "&location=" + location.getLatitude() + "," + location.getLongitude(); keyString = "&key=你的key"; questURL = questURL + locationString + keyString; new ReadJSONFeedTask().execute(questURL); } }
(4)由經緯度獲取所在城市和區域的ReadJSONFeedTask類的實現:
/** * 由經緯度獲取所在的城市及區域信息 * @author caizhiming * */ private class ReadJSONFeedTask extends AsyncTask<String, Void, String> { StringBuilder stringBuilder = new StringBuilder(); @Override protected String doInBackground(String... urls) { // TODO Auto-generated method stub return readJSONFeed(urls[0]); } @Override protected void onPostExecute(String result) { // TODO Auto-generated method stub String strItem; try { JSONObject jsonObject = new JSONObject(result); JSONObject resultObject = jsonObject.getJSONObject("result"); JSONObject addressComponentObject = resultObject .getJSONObject("addressComponent"); String city = addressComponentObject.getString("city"); String district = addressComponentObject.getString("district"); city = "城市:" + city; district = " 區:" + district; stringBuilder.append(city + district); textView.setText(stringBuilder.toString()); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } /** * 請求json數據 * @param url * @author caizhiming */ public String readJSONFeed(String url) { StringBuilder stringBuilder = new StringBuilder(); HttpClient client = new DefaultHttpClient(); HttpGet httpGet = new HttpGet(url); HttpResponse response; try { response = client.execute(httpGet); StatusLine statusLine = response.getStatusLine(); int statusCode = statusLine.getStatusCode(); if (statusCode == 200) { HttpEntity entity = response.getEntity(); InputStream content = entity.getContent(); BufferedReader reader = new BufferedReader( new InputStreamReader(content)); String line; while ((line = reader.readLine()) != null) { stringBuilder.append(line); } } else { Log.e("JSON", "Failed to download file"); } } catch (ClientProtocolException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return stringBuilder.toString(); }