Android:用户定位User Localtion和利用HTTP解析地址--GeoCoding

来源:互联网 发布:it业务范围 编辑:程序博客网 时间:2024/05/18 01:27

地图的使用,一般包括两方面的基本知识:一是定位;二是显示地图和在地图上显示相应的图层,包括定位到的位置。

Mars老师在这两节中主要讲解了定位方面的;至于在地图上显示其它图层可参照转载的另一篇文章:

一步步教你用Android Google Map


Android 中的定位,主要涉及到两个重要的 API : Location Manager 和 Location Providers 。

Location Manager 是用于管理 Android 的用户定位服务 ;

Location Providers 则是提供了多种定位方式供开发者选择,主要包括 GPS 、 NETWORK 和PASSIVE 。

其中前两者是较为常用,最后一种我也不太清楚是什么方式。

如果要使用 GPS 定位,则需要声明 android.permission.ACCESS_FINE_LOCATION权限;

如果需要使用 NETWORK 定位,则需要声明android.permission.ACCESS_FINE_LOCATION 权限或android.permission.ACCESS_COARSE_LOCATION 权限。

需要进行定位,一般需要通过以下四个步骤:

1、   AndroidManifest.xml 当中声明相应的权限;

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATON"/> 

2、  获取 LocationManager 对象

//得到一个定位服务管理器          locationManager = (LocationManager)LifeMap.this.getSystemService(Context.LOCATION_SERVICE);

3、  选择 LocationProviders 

/选择LocationProviders并绑定监听器  

// locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 0, theLocationListener);

   locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 50000, theLocationListener);

4、  绑定 LocationListener 对象。

下面给个实例代码看看:

public class HelloGPSActivity extends Activity {/** Called when the activity is first created. */@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);//得到LocationManagerLocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);//得到locationListener  添加一个监听器LocationListener locationListener = new LocationListener() {public void onLocationChanged(Location location) {// Called when a new location is found by the network location// provider.System.out.println(location.getLongitude());//获取当前经度System.out.println(location.getLatitude());//获取当前纬度}public void onStatusChanged(String provider, int status,Bundle extras) {}public void onProviderEnabled(String provider) {}public void onProviderDisabled(String provider) {}};// Register the listener with the Location Manager to receive location updates,绑定监听器//requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener)locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);}}

运行之后,在DDMS视图,下


点击 “Send”按钮在控件台输出:


既然定位有不同的 Providers ,那什么样的 Providers 对于我们来说是最合适的呢,这个就见仁见智了,得根据你自己的要求,然后再找出一个最为符合你的要求的 Providers 。 Android 中在android.location包中提供了一个类 Criteria ,其中有很方法用于设置我们需要的条件

setAccuracy (int accuracy) :设置精度,参数为 ACCURACY_COARSE  ACCURACY_FINE

setAltitudeRequired (boolean altitudeRequired) :是否需要海拔信息,参数为: true  false 

setBearingAccuracy (int accuracy) :设置方向的精度,参数为: ACCURACY_HIGH ACCURACY_LOW 

setBearingRequired (boolean bearingRequired) :是否需要方向信息,参数为: true  false;、

setCostAllowed (boolean costAllowed) :是否产生费用,如流量费用等等,参数为: true false 

setHorizontalAccuracy (int accuracy) :设置水平方向的精度,参数为: ACCURACY_HIGH ACCURACY_LOW  ACCURACY_MEDIUM 

setPowerRequirement (int level) :设置电量的消耗,参数为 NO_REQUIREMENT, POWER_LOW, POWER_MEDIUM,  POWER_HIGH 

setSpeedAccuracy (int accuracy) :设置速度的精度,其参数: ACCURACY_LOW ,ACCURACY_HIGH ,  NO_REQUIREMENT 

setSpeedRequired (boolean speedRequired)  是否需要速度信息,参数为: true  false 

setVerticalAccuracy (int accuracy) :垂直方向的精度,参数为: ACCURACY_LOW ,ACCURACY_MEDIUM , ACCURACY_HIGH  NO_REQUIREMENT 

设置好这个 Criteria 对象后,就可以通过 LocationManager  getBestProvider (Criteriacriteria, boolean enabledOnly) 方向传入刚设置好的 Criteria 对象,以及一个布尔值,则可得到一个最合适的 Provider 

注: enabledOnly 如果为 false 时,则在所有 Provider 中查找最合适的 Provider ;

     enabledOnly 如果为 true 时,则只在当前打开可用的 Provider 中查找最合适的 Provider 。


有时候我们需要精确定位用户的位置与经纬度之间的解析,我们可以用GOOGLE地图 HTTP解析地址或者Android给我们提供的Geocoder 

但是在实际中我们又遇到了问题:

在android的API中提到:

 The Geocoder class requires a backend service that is not included in the core android framework. The Geocoder query methods will return an empty list if there no backend service in the platform. Use the isPresent() method to determine whether a Geocoder implementation exists. 
大意就是:

Geocoder类的使用描述在使用的前提是必须有 后台服务的支持,但是andorid sdk中不包含该服务的,模拟器可能模拟了该服务了。在真机上不一定存在。可以用isPresent() 检测一下,就知道有没有了。

这个错误经常使用:getFromLocation()与getFromLocationName()这两个函数会返回null值。

相关信息可以去code.google.com上查询:


我们可以直接利用http地址,实现地址查询:如:

根据地址查询经纬度:
http://maps.googleapis.com/maps/api/geocode/json?address=SFO&sensor=false


根据经纬度查询地址:
http://maps.googleapis.com/maps/api/geocode/json?latlng=40.714224,-73.961452&sensor=false


bounds的作用
http://maps.googleapis.com/maps/api/geocode/json?address=Winnetka&sensor=false
http://maps.googleapis.com/maps/api/geocode/json?address=Winnetka&bounds=34.172684,-118.604794|34.236144,-118.500938&sensor=false

region的作用
http://maps.googleapis.com/maps/api/geocode/json?address=Toledo&sensor=false
http://maps.googleapis.com/maps/api/geocode/json?address=Toledo&sensor=false&region=es


在上面这些方法,查询的都是显示json数据;senor表示,是否是来自传感器(比如手机上的传感器等)

bounds是在某个区域之间(定义一个矩形之内查询是不是有这个名字的地址)

region的作用是可选- 区域代码,指定为 ccTLD(“顶级域”)双字符值。(有关详细信息,请参见下文的区域偏向。)

详细信息也可以查看:http://code.google.com/intl/zh-CN/apis/maps/documentation/geocoding/


当地址解析器传回结果时,它会将其放在一个 (JSON) results 数组中。即使地址解析器未传回任何结果(例如地址不存在),它仍会传回一个空 results 数组。(XML 响应包含零或多个 <result> 元素。)

一个典型的结果由以下字段组成:

  • types[] 数组指示传回结果的类型。此数组包含一个或多个标签,这些标签标识结果中返回的特征的类型。例如,对“Chicago”的地址解析返回“locality”,表示“Chicago”是一个城市;同时返回“political”,表示它是一个政治实体。

  • formatted_address 是一个字符串,包含此位置的人类可读地址。通常该地址相当于“邮政地址”,有时会因不同国家/地区而存在差异。(请注意,部分国家/地区会有许可限制,禁止发布真实的邮政地址,如英国。)此地址通常由一个或多个地址部分组成。例如,地址“111 8th Avenue, New York, NY”包含四个地址组成部分,即“111”(街道门牌号)、“8th Avenue”(街道地址)、“New York”(城市)和“NY”(美国的一个州)。这些地址组成部分包含附加信息,如下面所述。

  • address_components[] 是一个包含多个地址组成部分(如上文所述)的数组。每个 address_component 通常包含以下几个组成部分:

    • types[] 是一个数组,表示地址组成部分的类型。
    • long_name 是地址解析器传回的完整文本说明或地址组成部分的名称。
    • short_name 是地址组成部分的缩写文本名称(如果有)。例如,阿拉斯加州的地址组成部分可能具有 long_name“Alaska”和 short_name“AK”(使用 2 个字母的邮政缩写)。

    请注意,address_components[] 包含的地址组成部分可能多于 formatted_address 中所注明的地址组成部分。

  • geometry 包含以下信息:

    • location 包含地址解析生成的纬度值和经度值。对于常规地址查询,此字段通常是最重要的。
    • location_type 存储有关指定位置的附加数据。当前支持以下值:

      • "ROOFTOP" 表示传回的结果是一个精确的地址解析值,我们可获得精确到街道地址的位置信息。
      • "RANGE_INTERPOLATED" 表示返回的结果是一个近似值(通常表示某条道路上的地址),该地址处于两个精确点(如十字路口)之间。当无法对街道地址进行精确的地址解析时,通常会返回近似结果。
      • "GEOMETRIC_CENTER" 表示返回的结果是折线(如街道)或多边形(区域)等内容的几何中心。
      • "APPROXIMATE" 表示返回的结果是一个近似值。
    • viewport 包含用于显示传回结果的建议可视区域,并被指定为两个纬度/经度值,分别定义可视区域边框的 southwest 和 northeast 角。通常,该可视区域用于在将结果显示给用户时作为结果的框架。
    • bounds(可选择传回)存储可完全包含传回结果的边框。请注意,这些边界可能与建议的可视区域不相符。(例如,旧金山包含费拉隆岛。该岛实际上是旧金山市的一部分,但不应该在可视区域内传回。)

更详细的信息看:http://code.google.com/intl/zh-CN/apis/maps/documentation/geocoding/#StatusCodes