由于访问这些服务的移动设备的位置可能会发生改变,因此利用位置作为请求的一部分可能会很有趣。在一个地方搜索Flickr上的“waterfront”图像与随后从另一个地方进行搜索将产生不同的结果。
Android提供了LocationManager类,可以使用它来查找并跟踪应用程序的位置变化。
下面是一个简单的代码片段,它演示了如何利用LocationManager以及如何监听位置的更新。
1 package com.nthm.androidtestActivity; 2 3 import com.nthm.androidtest.R; 4 import android.app.Activity; 5 import android.content.Context; 6 import android.location.Location; 7 import android.location.LocationListener; 8 import android.location.LocationManager; 9 import android.location.LocationProvider; 10 import android.os.Bundle; 11 import android.widget.TextView;
为了从LocationManager接收位置更新,活动将实现LocationListener。
1 public class LocationTracking extends Activity implements LocationListener { 2 private LocationManager lm; 3 private TextView tv; 4 @Override 5 protected void onCreate(Bundle savedInstanceState) { 6 super.onCreate(savedInstanceState); 7 setContentView(R.layout.locationtracking); 8 tv=(TextView) findViewById(R.id.location);
可以采用Context中可用的getSystemService方法得到一个LocationManager示例由于活动时Context的一个子类,因此他对我们可用。
1 lm=(LocationManager) getSystemService(Context.LOCATION_SERVICE);
LocationManager允许指定是否希望LocationListener(在此事例中是当前的活动)获得位置相关变化的通知。通过将其做为最后一个参数传递给requestLocationUpdates方法,可以将活动注册为LocationListener。
方法的第一个参数是想要使用的位置提供器。两个可用的位置提供器定义为在LocationManager类中的常量。此处使用的是NETWORK_PROVIDER,其利用网络服务(如手机信号塔的位置和WiFi访问点的位置确定。另一个可用的位置提供器是GPS_PROVIDER,其利用GPS(Global Positioning Statellites,全球定位卫星)来提供位置信息。NETWORK_PROVIDE通常会更快,可能其位置查找不太精确。GPS可能需要大量的时间从卫星获得信号,而且不能再所有的室内或者天空不太清晰的地区工作(例如马哈顿中城)。
第二个参数是系统在“位置更改”通知之间等待的最少时间,通过一个表示毫秒数的长整数来指定该时间。在这里使用6000毫秒或1分钟。
第三个参数是在发出一个“位置更改”通知之前位置需要改变的距离量,可以通过一个表示米的浮点数来指定该距离量。在这里使用5米。
1 lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 6000, 5.0f, this); 2 }
当使用LocationManager时,尤其是当使用GPS作为位置提供器时,如果应用程序不再位于前台,那么可能需要谨慎的停止位置更新。因为这将节省电池的电量。为此,可以重写活动中的onPause或onStop方法,并调用LocationManager对象上的removeUpdates方法。
1 @Override 2 protected void onPause() { 3 super.onPause(); 4 lm.removeUpdates(this); 5 }
每当位置发生改变时,其更改大于在requestLocationUpdates方法中指定的距离和时间参数时,将会在注册的LocationListener上调用onLocationChanged方法,并传入一个Location对象。
传入的Location对象具有可用于获取纬度(getLatitude)、经度(getLongitude)、海拔以及更多信息的方法。
1 @Override 2 public void onLocationChanged(Location location) { 3 tv.setText(location.getLatitude()+" "+location.getLongitude()); 4 }
如果用户禁用了正被监听的提供器,那么调用注册的LocationListener上的onProviderDisabled方法。
1 @Override 2 public void onProviderDisabled(String provider) { 3 4 }
如果用户启用了正在被监听的提供器,那么调用注册的LocationListener上的onProviderEnabled方法。
1 @Override 2 public void onProviderEnabled(String provider) { 3 4 }
最后,如果位置提供器的状态发生了更改,那么调用注册的LocationListener上的onStatusChanged方法。在LocationProvider上可以使用3个常量来测试status变量,以明确发生了何种变化。他们是;AVAILABLE,如果提供器在经过一段时间不可用之后变得可用,那么将调用它;TEMPORARILY_UNAVAILABLE,正如其名所暗示的那样,提供器暂时不能用,因为它无法获取当前位置;最后是OUT_OF_SERVICE,这意味着提供器可能由于失去连接或信号而无法使用。
1 @Override 2 public void onStatusChanged(String provider, int status, Bundle extras) { 3 if(status==LocationProvider.AVAILABLE){ 4 5 }else if(status==LocationProvider.TEMPORARILY_UNAVAILABLE){ 6 7 }else if(status==LocationProvider.OUT_OF_SERVICE){ 8 9 } 10 } 11 }
下面是上述活动所需的布局XML。
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 android:layout_width="match_parent" 3 android:layout_height="match_parent" 4 android:orientation="vertical" 5 > 6 <TextView 7 android:id="@+id/location" 8 android:text="Status" 9 android:layout_width="fill_parent" 10 android:layout_height="wrap_content" 11 android:textSize="35dip"></TextView> 12 13 </LinearLayout>
访问位置必须有请求的权限,所以需要将以下uses-permission标记添加到AndroidManifest.xml文件。注意以下标记用于LocationManager.NETWORK_PROVIDER提供器,它将提供一个粗略的位置。
1 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
如果有兴趣以GPS使用更精确的位置,那么需要使用ACCESS_FINE_LOCATION权限。
1 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>