提供重要的地理位置信息服务
1 Location Manager 管理服务2 Location Provider 提供数据的content provider
方式一:GPS 特点:精度高,耗电量大,不耗费流量 权限<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
方式二:NETWORK 特点:精度低,省电,需要网络访问 权限<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
或者权限<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
方式三PASSIVE_PROVIDER 资料比较少,只用于特定的情景下,SDK的解释是,并不自己实例化去获取地理位置,而是通过getProvider获取其他的服务或者activity更新位置,被动的获取更新。
操作基本步骤:
1 在manifest.xml文件中设置权限
2 获取LocaionManager
3 选择provider
4 创建listener
/**********************************************************************************************************************/
第一部分 权限
android的安全服务机制,如果应用要访问本地的资源例如联系人列表、拨号、GPS或者其他应用程序的数据,需要许可。所以要使用地理位置信息的服务需要在<manifest>标签下添加android:name="android.permission.ACCESS_FINE_LOCATION"/>获得许可
也可通过单击manifest.xml文件的permission标签可视化的添加许可
/**********************************************************************************************************************/
第二部分 认识LocationManager
官方SDK解释“This class provides access to the system location services. These services allow applications to obtain periodic updates of the device's geographical location, or to fire an application-specified Intent when the device enters the proximity of a given geographical location.
You do not instantiate this class directly; instead, retrieve it through Context.getSystemService(Context.LOCATION_SERVICE). ”
翻译一下大概意思是“LocationManager这个类提供了对系统位置服务的访问,这些服务允许应用程序获取设备地理位置的定期的更新,也可以在设备接近一个指定的地理位置的时候发起一个指定activity的intent。你不需要创建LocationManager的实例,取而代之的是通过Context.getSystemService(Context.LOCATION_SERVICE)获取。”
重要的方法:来自官方SDK(附上我的翻译注释)
-----------------------------------------------------------------------------------------------------------------------------------------------
public Location getLastKnownLocation (String provider)
Since: API Level 1
Returns a Location indicating the data from the last known location fix obtained from the given provider. This can be done without starting the provider. Note that this location could be out-of-date, for example if the device was turned off and moved to another location.
/ /返回一个Location,这个location标明从给定provider获得最后已知的位置,也就是最近获取的位置。这个操作可以不必要启动provider,注意这个地址可能是已经过期的,例如使用的设备可能已经被关闭或者转向了另一个位置。
If the provider is currently disabled, null is returned.
//如果当前的provider被禁用,函数返回null
Parameters
provider the name of the provider
Returns
the last known location for the provider, or null
Throws
SecurityException if no suitable permission is present for the provider. //前面提到的权限的问题,没有允许会抛出安全性的异常,android系统的机制
IllegalArgumentException if provider is null or doesn't exist //非法参数异常,表示provider为null,或者不存在
------------------------------------------------------------------------------------------------------------------------------------------------
一些补充:
认识Location类
官方SDK解释 :“A class representing a geographic location sensed at a particular time (a "fix"). A location consists of a latitude and longitude, a UTC timestamp. and optionally information on altitude, speed, and bearing.
大致的意思是:“这个类用来表示在一个特定时间被感应的地理位置信息(我们叫一个fix//感觉有点聚焦的意思,呵呵),一个location包括一个经度,纬度,一个世界时间戳还有一些关于海拔,速度和方向的可选信息。 “
可以通过getLatitude() getLongitude() getProvider()等函数来获取封装信息中的经度纬度和提供信息的provider,这个比较简单。
-----------------------------------------------------------------------------------------------------------------------------------------------
public void requestLocationUpdates (String provider, long minTime, float minDistance, LocationListener listener)
Since: API Level 1
Registers the current activity to be notified periodically by the named provider. Periodically, the supplied LocationListener will be called with the current Location or with status updates.
//注册当前的activity定时的被provider的被通知。相当于注册事件。每隔一段时间,LocationListenner会被调用,同时当前的位置或者状态进行更新。
It may take a while to receive the most recent location. If an immediate location is required, applications may use the getLastKnownLocation(String) method.
//接受最新的位置信息可能会花费一会时间,如果需要立刻获得位置信息,程序可以使用上面讲的getLastKonwnLocation方法
In case the provider is disabled by the user, updates will stop, and the onProviderDisabled(String) method will be called. As soon as the provider is enabled again, the onProviderEnabled(String) method will be called and location updates will start again.
//假如provider被用户停止,(比如关闭GPS等),更新会停止。并且onProviderDisabled方法(监听器中一个需要复写的方法)会被调用,只要provider再次变为可用状态,onProviderEnable方法会被调用,并且更新操作立刻开始。
The frequency of notification may be controlled using the minTime and minDistance parameters. If minTime is greater than 0, the LocationManager could potentially rest for minTime milliseconds between location updates to conserve power. If minDistance is greater than 0, a location will only be broadcasted if the device moves by minDistance meters. To obtain notifications as frequently as possible, set both parameters to 0.
//通知(更新)的频率可以通过使用minTime(最小更新时间 单位:毫秒)和minDistance(单位:米)参数,如果minTime大于0,LocationManager能够在minTime时间内休息来保存电量,如果minDistance大于0,每变化这个距离就会进行一次更新,如果希望尽可能频繁的更新的数据,则把两个参数均设置为0.
Background services should be careful about setting a sufficiently high minTime so that the device doesn't consume too much power by keeping the GPS or wireless radios on all the time. In particular, values under 60000ms are not recommended.
//后台的服务应该注意,设置一个合理的minTime使得设备一直保持GPS或者WIFI的时候不耗费太多的电量。不推荐使用6000ms的minTime值
The calling thread must be a Looper thread such as the main thread of the calling Activity.
//使用该方法的线程必须时开启消息循环的线程,例如被调用activity的主线程(可以参考Android线程机制,默认新建的线程是没有开启消息循环的,主线程开启消息循环,可以参考SDK的Looper类)
Parameters
provider the name of the provider with which to register
minTime the minimum time interval for notifications, in milliseconds. This field is only used as a hint to conserve power, and actual time between location updates may be greater or lesser than this value.
minDistance the minimum distance interval for notifications, in meters
listener a {#link LocationListener} whose onLocationChanged(Location) method will be called for each location update //这是事件监听器
Throws
IllegalArgumentException if provider or listener is null
RuntimeException if the calling thread has no Looper //运行时异常,在未开启消息循环的线程中运行
SecurityException if no suitable permission is present for the provider.
-----------------------------------------------------------------------------------------------------------------------------------------------
在使用android lcoation的时候,可能不希望自己去硬性的选择是GPS服务还是NETWORK服务,可能是我们考虑的因素有很多,自己很难决定,Android SDK提供了一个类Criteria,直译为标准。
注意在locationManager中还有一个重要的方法就是getBestProvider()
------------------------------------------------------------------------------------------------------------------------------------------------
public String getBestProvider (Criteria criteria, boolean enabledOnly)
Since: API Level 1
Returns the name of the provider that best meets the given criteria. Only providers that are permitted to be accessed by the calling activity will be returned. If several providers meet the criteria, the one with the best accuracy is returned. If no provider meets the criteria, the criteria are loosened in the following sequence:
//翻译:返回满足给定的criteria(标准)的最佳provider,(前面一篇文章提到过两种重要provider的区别)。只有当provider权限允许的时候才会返回,如果几个provider均满足criteria设定的标准,最贴近标准的provider将会被返回。如果没有provider满足,标准将按照下面的序列放宽松。
power requirement
accuracy
bearing
speed
altitude
Note that the requirement on monetary cost is not removed in this process.
//在放宽标准的过程中,对于资费的要求不会被移除,我感觉也就是是否允许产生资费的标准不会改变
Parameters
criteria the criteria that need to be matched
enabledOnly if true then only a provider that is currently enabled is returned//这个参数为true的时候,只会返回当前可用的provider,例如GPS处于关闭状态时,就不会获得了
Returns
name of the provider that best matches the requirements
------------------------------------------------------------------------------------------------------------------------------------------------
下面详细的看一下Criteria类的解释
A class indicating the application criteria for selecting a location provider. Providers maybe ordered according to accuracy, power usage, ability to report altitude, speed, and bearing, and monetary cost.
翻译:“这个类表示了应用程序选择位置服务provider的一个标准,provider可能是根据精准度,电量使用,能否获得海拔,速度、方向和产生资费来选择的”也就是说,criteria给用户提供了多种因素的标准设置,locationManager可以根据这个设定好的标准,自动选择最慢组需求的provider。
------------------------------------------------------------------------------------------------------------------------------------------------
void setAccuracy(int accuracy)
Indicates the desired accuracy for latitude and longitude. //设置经纬度的精准度 可选参数有ACCURACY_FINE 准确 ACCURACY_COARSE 粗略
void setAltitudeRequired(boolean altitudeRequired)
Indicates whether the provider must provide altitude information.//设置是否需要获取海拔数据
void setBearingAccuracy(int accuracy)
Indicates the desired bearing accuracy. //设置方向的精确 可选参数有ACCURACY_LOW,低 ACCURACY_HIGH 高 NO_REQUIREMENT.没有要求
void setBearingRequired(boolean bearingRequired)
Indicates whether the provider must provide bearing information.//设置是否需要获得方向信息
void setCostAllowed(boolean costAllowed)
Indicates whether the provider is allowed to incur monetary cost. //设置是否允许定位过程中产生资费,比如流量等
void setHorizontalAccuracy(int accuracy)
Indicates the desired horizontal accuracy (latitude and longitude).//获取水平方向经纬度的精准度 可选参数ACCURACY_LOW, 低 ACCURACY_MEDIUM 中 ACCURACY_HIGH 高 NO_REQUIREMENT. 无要求
void setPowerRequirement(int level)
Indicates the desired maximum power level. //设置耗电量的级别
void setSpeedAccuracy(int accuracy)
Indicates the desired speed accuracy. //设置速度的精确度
void setSpeedRequired(boolean speedRequired)
Indicates whether the provider must provide speed information. //设置是否提供速度的要求
void setVerticalAccuracy(int accuracy)
Indicates the desired vertical accuracy (altitude).//设置垂直距离的海拔高度
演示代码:/* LocationActivity.java
* @author octobershiner
* 2011 7 24
* SE.HIT
* 利用Criteria选择最优的位置服务,演示定位用户的位置并且监听位置变化的代码
* */
package uni.location;
import android.app.Activity;
import android.content.Context;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Vibrator;
import android.util.Log;
import android.widget.TextView;
public class LocationActivity extends Activity {
/** Called when the activity is first created. */
//创建lcoationManager对象
private LocationManager manager;
private static final String TAG = "LOCATION DEMO";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//获取系统的服务,
manager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
//创建一个criteria对象
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_COARSE);
//设置不需要获取海拔方向数据
criteria.setAltitudeRequired(false);
criteria.setBearingRequired(false);
//设置允许产生资费
criteria.setCostAllowed(true);
//要求低耗电
criteria.setPowerRequirement(Criteria.POWER_LOW);
String provider = manager.getBestProvider(criteria, false);
Log.i(TAG, "we choose "+ provider);
Location location = manager.getLastKnownLocation(provider);
//第一次获得设备的位置
updateLocation(location);
//重要函数,监听数据测试
manager.requestLocationUpdates(provider, 6000, 10,
locationListener);
}
//创建一个事件监听器
private final LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
updateLocation(location);
}
public void onProviderDisabled(String provider){
updateLocation(null);
Log.i(TAG, "Provider now is disabled..");
}
public void onProviderEnabled(String provider){
Log.i(TAG, "Provider now is enabled..");
}
public void onStatusChanged(String provider, int status,Bundle extras){ }
};
//获取用户位置的函数,利用Log显示
private void updateLocation(Location location) {
String latLng;
if (location != null) {
double lat = location.getLatitude();
double lng = location.getLongitude();
latLng = "Latitude:" + lat + " Longitude:" + lng;
} else {
latLng = "Can't access your location";
}
Log.i(TAG, "The location has changed..");
Log.i(TAG, "Your Location:" +latLng);
}
}
同时修改manifest.xml文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="uni.location"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="8" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".LocationActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
</manifest>
演示结果:
可任看到 我们只要求低的精确度并且最低电量,从最后一行可以看到我的虚拟机网络服务并没有打开,但是选择最佳provider的时候,参数选择了false 所以同样可以选择。
转帖:http://blog.csdn.net/octobershiner/article/details/6629305