CHAPTER 10
LBS 基于位置服务
LocationManager
getSystemService(Context.LOCATION_SERVICE);
由三种位置提供器来确定设备当前位置
分别是 GPS_PROVIDER , NETWORK_PROVIDER , PASSIVE_PROVIDER
尤其前两种方式使用较多
第一种GPS 定位比较精确但耗电较多
第二种网络定位相对耗电较少但不够精确
定位功能必须由用户主动启用才行
将选择好的位置提供器传入到getLastKnownLocation()方法中 ,就可以得到一个Location对象
String provider = LocationManager.NETWORK_PROVIDER;
Location location = locationManager.getLastKnownLocation(provider);
需要权限
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
此时该location中包含 经度(longitude) 、 纬度(latitude) 、 海拔(altitude) 等一系列的位置信息 。
如果有时候想让定位的精度更高一些,但又不确定 GPS 定位的功能是否启用 ,这个时候可以先判断有哪些位置提供器可用
List<String> providerList = locationManager.getProviders(true);
传入 true 就表示只有启用的位置提供器才会被返回。之后在 List 中进行判断是否包含 GPS 定位的功能即可
调用 getLastKnownLocation() 虽可以获取设备当前位置 ,但是用户完全有可能带着设备随时移动,如果在设备位置发生变化时获取到最新的位置信息呢?
LocationManager 提供了 requestLocationUpdate() 方法,只要传入一个 LocationListener 的实例,并简单配置几个参数即可实现
android.location.LocationManager.requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener)
Parameters:
provider the name of the provider with which to register
minTime minimum time interval between location updates, in milliseconds
minDistance minimum distance between location updates, in meters
listener a LocationListener whose LocationListener.onLocationChanged method will be called for each location update
移除监听
void android.location.LocationManager.removeUpdates(LocationListener listener)
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
List<String> providerList = locationManager.getProviders(true);
if (providerList.contains(LocationManager.GPS_PROVIDER)) {
provider = LocationManager.GPS_PROVIDER;
}else if (providerList.contains(LocationManager.NETWORK_PROVIDER)) {
provider = LocationManager.NETWORK_PROVIDER;
}else if (providerList.contains(LocationManager.PASSIVE_PROVIDER)) {
provider = LocationManager.PASSIVE_PROVIDER;
}else {
Toast.makeText(this, "No location provider to use", Toast.LENGTH_SHORT).show();
return ;
}
mLocation = locationManager.getLastKnownLocation(provider);
showLocationInfo(mLocation);
locationManager.requestLocationUpdates(provider, 5000, 1, listener);
private void showLocationInfo(Location location) {
double latitude =location.getLatitude();//纬度
double longitude = location.getLongitude();//经度
double altitude = location.getAltitude();//海拔
String locationInfo = "所在位置\n纬度 : "+latitude+"\n经度 : "+longitude+"\n海拔 : "+altitude;
tv.setText(locationInfo);
}
private LocationListener listener = new LocationListener() {
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
@Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
@Override
public void onLocationChanged(Location location) {
Toast.makeText(LocationActivity.this, "reLocating ---", Toast.LENGTH_SHORT).show();
mLocation = location;
showLocationInfo(location);
}
};
@Override
protected void onDestroy() {
super.onDestroy();
if (locationManager!=null) {
locationManager.removeUpdates(listener);
}
}
反向地理编码 将经纬度转化成看的懂的地理信息
google 提供给了相对稳定的Geocoding API
其中反向地理编码的接口如下
http://maps.googleapis.com/maps/api/geocode/json?latlng=xxx,xxx&sensor = false
固定不变的连接地址
http://maps.googleapis.com/api/geocode/
json 表示希望服务器返回的数据格式是 JSON格式 ,这里也可以用xml
latlng = xxx,xxx 纬度,经度
sensor 表示这条请求是否来自某个设备的位置传感器,通常置为false 即可
返回的数据 json格式的话 我们需要的信息 一个是 results 对应的 jsonarray
一个是 jsonarr中的 jsonobject 中 地理位置信息对应的key formatted_address
private void geocodeLocation(final Location location){
new Thread(new Runnable() {
@Override
public void run() {
StringBuilder url = new StringBuilder();
url.append("http://maps.googleapis.com/maps/api/geocode/json?latlng=");
url.append(location.getLatitude()+","+location.getLongitude())
.append("&sensor=false");
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(url.toString());
Log.i("haha", url.toString());
get.addHeader("Accept-Language", "zh-CN");
HttpResponse response;
try {
response = client.execute(get);
if (response.getStatusLine().getStatusCode()==200) {
Log.i("haha", "请求成功 状态码 200");
HttpEntity entity = response.getEntity();
String result = EntityUtils.toString(entity,"utf-8");
JSONObject jsonObject = new JSONObject(result);
JSONArray arr = jsonObject.getJSONArray("results");
if (arr.length()>0) {
Log.i("haha", "请求成功 有数据 arr.length : "+arr.length());
JSONObject object = arr.getJSONObject(0);
addressInfo= object.getString("formatted_address");
runOnUiThread(new Runnable() {
@Override
public void run() {
tv.setText(addressInfo);
}
});
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
以上代码都是学习内容 实际情况时 有时 Location 会为空 即使 GPS 和 网络都是打开的情况下
stackoverflow 上 有解决的方案 地址链接 Location null 如何解决 点击查看
private void getBestValidLocation(){
Location bestLocation = null;
List<String> providers = locationManager.getProviders(true);
for (String provide : providers) {
Location l = locationManager.getLastKnownLocation(provide);
if (l==null) {
continue;
}
if (bestLocation==null||bestLocation.getAccuracy()<l.getAccuracy()) {
bestLocation = l;
mProvider = provide;
}
}
mLocation = bestLocation;
}
百度地图的使用