在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(); }