开始搞个android定位demo(2)高德

本文通过对比高德地图和Google Geocoder的位置解析精度,发现高德地图能更精确地定位到街道级别,而Google Geocoder在区域级别上出现偏差。文中详细介绍了使用高德地图API进行位置解析的具体实现。

话说这几天新闻挺多啊

先是baidu map在东莞大发神威

然后就是阿里巴巴把高德给收购了

搞定了location之后,开始研究geocoder


本来打算从baidu map开始的,可是baidu map实在没有高德map简单,申请key也繁琐

所以就先调试了下高德map


结果真是令本人惊讶

用的同样都是network,得到的是同一个精度和纬度,我不知道为什么geocoder的精度差这么多,geocoder按道理来说调用的是google map才对,结果连区都不对

而高德基本上可以精确到街道了,想想都有点恐怖。。。。。


下面代码是根据高德的sample精简过的activity,location用的是另一篇作者的例子,模拟器用的是手上的闲置里程碑,

权限什么的直接copy的高德的sample

package com.example.gaode;

import java.io.IOException;
import java.util.List;

import com.amap.api.maps.AMap;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.model.BitmapDescriptorFactory;
import com.amap.api.maps.model.MarkerOptions;
import com.amap.api.services.core.LatLonPoint;
import com.amap.api.services.geocoder.GeocodeResult;
import com.amap.api.services.geocoder.GeocodeSearch;
import com.amap.api.services.geocoder.GeocodeSearch.OnGeocodeSearchListener;
import com.amap.api.services.geocoder.RegeocodeQuery;
import com.amap.api.services.geocoder.RegeocodeResult;

import android.app.Activity;
import android.app.ProgressDialog;
import android.location.Address;
import android.location.Criteria;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends Activity implements OnGeocodeSearchListener {
	private AMap aMap;
	private GeocodeSearch geocoderSearch;
	private String addressName ;
	

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		init();

		// 获取到LocationManager对象
		LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
		// 创建一个Criteria对象
		Criteria criteria = new Criteria();
		// 设置粗略精确度
		criteria.setAccuracy(Criteria.ACCURACY_COARSE);
		// 设置是否需要返回海拔信息
		criteria.setAltitudeRequired(false);
		// 设置是否需要返回方位信息
		criteria.setBearingRequired(false);
		// 设置是否允许付费服务
		criteria.setCostAllowed(false);
		// 设置电量消耗等级
		criteria.setPowerRequirement(Criteria.POWER_MEDIUM);
		// 设置是否需要返回速度信息
		criteria.setSpeedRequired(false);

		// 根据设置的Criteria对象,获取最符合此标准的provider对象
		String currentProvider = locationManager
				.getBestProvider(criteria, true);
		
		Log.d("Location", "currentProvider: " + currentProvider);
		// 根据当前provider对象获取最后一次位置信息
		
		Location currentLocation = locationManager
				.getLastKnownLocation(currentProvider);
		// 如果位置信息为null,则请求更新位置信息
		if (currentLocation == null) {
			locationManager.requestLocationUpdates(currentProvider, 0, 0,
					locationListener);
		}
		// 直到获得最后一次位置信息为止,如果未获得最后一次位置信息,则显示默认经纬度
		// 每隔10秒获取一次位置信息
		while (true) {
			currentLocation = locationManager
					.getLastKnownLocation(currentProvider);
			if (currentLocation != null) {
				Log.d("Location", "Latitude: " + currentLocation.getLatitude());
				Log.d("Location", "location: " + currentLocation.getLongitude());
				break;
			} else {
				Log.d("Location", "Latitude: " + 0);
				Log.d("Location", "location: " + 0);
			}
			try {
				Thread.sleep(10000);
			} catch (InterruptedException e) {
				Log.e("Location", e.getMessage());
			}
		}

		// 解析地址并显示 原装geocoder
		Geocoder geoCoder = new Geocoder(this);
		try {
			int latitude = (int) currentLocation.getLatitude();
			int longitude = (int) currentLocation.getLongitude();
			List<Address> list = geoCoder.getFromLocation(latitude, longitude,
					2);
			for (int i = 0; i < list.size(); i++) {
				Address address = list.get(i);
				Toast.makeText(
						MainActivity.this,
						address.getCountryName() + address.getAdminArea()
								+ address.getFeatureName(), Toast.LENGTH_LONG)
						.show();
				Log.d("Location", address.getCountryName() + address.getAdminArea()	+ address.getFeatureName());
			}
		} catch (IOException e) {
			Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_LONG)
					.show();
		}

	
		// 解析地址并显示 高德geocoder
		LatLonPoint latLonPoint = new LatLonPoint(currentLocation.getLatitude(), currentLocation.getLongitude());
		RegeocodeQuery query = new RegeocodeQuery(latLonPoint, 200,
				GeocodeSearch.AMAP);// 第一个参数表示一个Latlng,第二参数表示范围多少米,第三个参数表示是火系坐标系还是GPS原生坐标系
		geocoderSearch.getFromLocationAsyn(query);
	}
		// 创建位置监听器
	private LocationListener locationListener = new LocationListener() {
		// 位置发生改变时调用
		@Override
		public void onLocationChanged(Location location) {
			Log.d("Location", "onLocationChanged");
			Log.d("Location",
					"onLocationChanged Latitude" + location.getLatitude());
			Log.d("Location",
					"onLocationChanged location" + location.getLongitude());
		}

		// provider失效时调用
		@Override
		public void onProviderDisabled(String provider) {
			Log.d("Location", "onProviderDisabled");
		}

		// provider启用时调用
		@Override
		public void onProviderEnabled(String provider) {
			Log.d("Location", "onProviderEnabled");
		}

		// 状态改变时调用
		@Override
		public void onStatusChanged(String provider, int status, Bundle extras) {
			Log.d("Location", "onStatusChanged");
		}
	};
	private void init() {
		
		geocoderSearch = new GeocodeSearch(this);
		geocoderSearch.setOnGeocodeSearchListener(this);
		
	}
	@Override
	public void onGeocodeSearched(GeocodeResult arg0, int arg1) {
		// TODO Auto-generated method stub
		
	}
	@Override
	public void onRegeocodeSearched(RegeocodeResult result, int rCode) {
		
		if (rCode == 0) {
			if (result != null && result.getRegeocodeAddress() != null
					&& result.getRegeocodeAddress().getFormatAddress() != null) {
				addressName = result.getRegeocodeAddress().getFormatAddress()
						+ "附近";
//				aMap.animateCamera(CameraUpdateFactory.newLatLngZoom(
//						AMapUtil.convertToLatLng(latLonPoint), 15));
//				regeoMarker.setPosition(AMapUtil.convertToLatLng(latLonPoint));
				Toast.makeText(	MainActivity.this,addressName, Toast.LENGTH_LONG).show();
				Log.d("Location", addressName);
				
//				ToastUtil.show(GeocoderActivity.this, addressName);
			} else {
				Log.d("Location", "gaode no_result ");
//				ToastUtil.show(GeocoderActivity.this, R.string.no_result);
			}
		} else if (rCode == 27) {
			Log.d("Location", "gaode error_network ");
//			ToastUtil.show(GeocoderActivity.this, R.string.error_network);
		} else if (rCode == 32) {
			Log.d("Location", "gaode error_key ");
//			ToastUtil.show(GeocoderActivity.this, R.string.error_key);
		} else {
			Log.d("Location", "gaode error_other ");
//			ToastUtil.show(GeocoderActivity.this, R.string.error_other);
		}
		
	}
}


查了下关于geocoder的描述

上面代码里面的这块地方可疑性最大

List<Address> list = geoCoder.getFromLocation(latitude, longitude,  
                    2);  
            for (int i = 0; i < list.size(); i++) {  

google建议设置成1到5,max number of addresses to return. Smaller numbers (1 to 5) are recommended

莫非1是最精确的?我用了2的缘故?

将这个数字从1到5试了下

结果没有变化,也就是说,设为1,就是设为5时的第一个结果,这个数字与精度无关

看来了下,第一个和第二个结果

在getFeatureName时有区别,好吧,虽然连区居然都错了,但是为什么会有这个区别呢??????

暂时解决不了,这个参数很奇怪,而且找不到什么给说明下

好吧,暂时放弃下

getFeatureName()

Returns the feature name of the address, for example, "Golden Gate Bridge", or null if it is unknown

02-15 09:19:20.379: D/Location(3021): 0中国上海市null四联路四联路
02-15 09:19:20.395: D/Location(3021): 1中国上海市null青浦区null
02-15 09:19:20.411: D/Location(3021): 2中国上海市null上海市null
02-15 09:19:20.426: D/Location(3021): 3中国上海市null上海市null
02-15 09:19:20.442: D/Location(3021): 4中国nullnull中国null

	// 得到的地址数目设为5,然后用list循环,得到具体地址
			List<Address> list = geoCoder.getFromLocation(latitude, longitude,
					5);
			for (int i = 0; i < list.size(); i++) {
				Address address = list.get(i);
				Toast.makeText(
						MainActivity.this,
						address.getCountryName() + address.getAdminArea()
								+ address.getFeatureName()+address.getThoroughfare(), Toast.LENGTH_LONG)
						.show();
				Log.d("Location", i + address.getCountryName() + address.getAdminArea()	+ address.getSubLocality() +
						address.getFeatureName()+address.getThoroughfare());
			}

综上,在试用阶段,高德上手还是比较快的,起码pk google的geocoder不成问题,下一篇试一下baidu的


使用GPS 定位,首先,需要在清单文件(AndroidManifest.xml)中注册获取定位的权限: **1.获取位置管理器对象LocationManager** ``` import android.location.LocationManager; LocationManager lm; // lm =(LocationManager) this.getSystemService(Context`.LOCATION_SERVICE); // ``` **2.一般使用LocationManager的getLastKnownLocation(LocationManager.GPS_PROVIDER);方法获取Location对象** ``` String provider = LocationManager.GPS_PROVIDER;// 指定LocationManager的定位方法 Location location = locationManager.getLastKnownLocation(provider);// 调用getLastKnownLocation()方法获取当前的位置信息 ``` 不过不建议用这种方法,有几点原因: 一,在很多提供定位服务的应用程序中,不仅需要获取当前的位置信息,还需要监视位置的变化,在位置改变时调用特定的处理方法 ,其中LocationManager提供了一种便捷、高效的位置监视方法requestLocationUpdates(),可以根据位置的距离变化和时间间隔设定,产生位置改变事件的条件,这样可以避免因微小的距离变化而产生大量的位置改变事件 。 二,当你开启GPS,provider的值为GPS。这时的定位方式为GPS,由于GPS定位慢,所以它不可能立即返回你一个Location对象,所以就返回null了。 **3.推荐locationManager.requestLocationUpdates();方法** LocationManager中设定监听位置变化的代码如下: ``` lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000, 10,new MyLocationListener()); ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值