这几天了解了一下借助于百度地图API的地图开发,做一下笔记以方便以后深入学习。
一、开发准备
开发第一步,下载百度地图的android sdk:http://developer.baidu.com/map/index.php?title=androidsdk
此页面对key的申请,以及SDK的下载和使用都有详细介绍,此处不做赘述。
工程配置介绍:http://developer.baidu.com/map/index.php?title=androidsdk/guide/hellobaidumap
demo下载:
在此页面可以下载SDK,demo,类参考。由于SDK v2.1.3以后的版本跟之前的版本有一定的差距,所以最好根据demo来实现自己想要的功能,而不是直接在网上找源码。
二、功能示例
1、坐标转换:将经纬度转换为具体地址
使用LocationManager获取坐标再使用 GeoCoder进行转换
package com.dream.locationdemo;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.search.core.SearchResult;
import com.baidu.mapapi.search.geocode.GeoCodeResult;
import com.baidu.mapapi.search.geocode.GeoCoder;
import com.baidu.mapapi.search.geocode.OnGetGeoCoderResultListener;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeOption;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeResult;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeResult.AddressComponent;
import android.app.Activity;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
public class PlaceholderFragment extends Fragment{
public PlaceholderFragment() {
}
private static final String TAG=PlaceholderFragment.class.getSimpleName();
View rootView;
private TextView latitudeTv;
private TextView longitudeTv;
private TextView altitudeTv;
private TextView detailTv;
private Button enterMapBtn;
LocationManager manager;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_main, container,
false);
return rootView;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
setLocationListener();
initView();
}
private void initView() {
latitudeTv=(TextView)rootView.findViewById(R.id.tv_main_latitude);
longitudeTv=(TextView)rootView.findViewById(R.id.tv_main_longitude);
altitudeTv=(TextView)rootView.findViewById(R.id.tv_main_altitude);
detailTv=(TextView)rootView.findViewById(R.id.tv_main_detailaddress);
enterMapBtn=(Button)rootView.findViewById(R.id.btn_main_entermap);
enterMapBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
try {
Activity act=getActivity();
if(act instanceof MainActivity){
((MainActivity)getActivity()).enterMap();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
Location location=manager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
showLocation(location);
}
public void setLocationListener(){
manager=(LocationManager)getActivity().getSystemService(Context.LOCATION_SERVICE);
LocationListener listener=new LocationListener() {
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
@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) {
showLocation(location);
}
};
manager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, listener);
}
protected void showLocation(Location location) {
try {
double latitude=location.getLatitude();
double longitude=location.getLongitude();
double altitude=location.getAltitude();
latitudeTv.setText(latitude+"");
longitudeTv.setText(longitude+"");
altitudeTv.setText(altitude+"");
LatLng ll=new LatLng(latitude, longitude);
GeoCoder gc=GeoCoder.newInstance();
OnGetGeoCoderResultListener listener=new OnGetGeoCoderResultListener() {
@Override
public void onGetReverseGeoCodeResult(ReverseGeoCodeResult result) {
if(result==null || result.error !=SearchResult.ERRORNO.NO_ERROR){
return;
}
AddressComponent ac=result.getAddressDetail();
StringBuilder sb=new StringBuilder();
sb.append(ac.province).append(" ").
append(ac.city).append(" ").
append(ac.district).append(" ").
append(ac.street).append(" ").append(ac.streetNumber);
detailTv.setText(sb.toString());
}
@Override
public void onGetGeoCodeResult(GeoCodeResult arg0) {
// TODO Auto-generated method stub
}
};
gc.setOnGetGeoCodeResultListener(listener);
ReverseGeoCodeOption rhco=new ReverseGeoCodeOption();
rhco.location(ll);
gc.reverseGeoCode(rhco);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
2、定位
使用LocationClient和MyLocationListener ; 定位有一个单独的SDK:http://developer.baidu.com/map/index.php?title=android-locsdk/guide/v4-2
package com.dream.locationdemo;
import android.app.Activity;
import android.media.DeniedByServerException;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.location.LocationClientOption.LocationMode;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.MyLocationConfiguration;
import com.baidu.mapapi.map.MyLocationData;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.search.core.SearchResult;
import com.baidu.mapapi.search.geocode.GeoCodeResult;
import com.baidu.mapapi.search.geocode.GeoCoder;
import com.baidu.mapapi.search.geocode.OnGetGeoCoderResultListener;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeOption;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeResult;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeResult.AddressComponent;
public class MyMapActivity extends Activity {
public static final String TAG = MyMapActivity.class.getSimpleName();
MapView mapView;
BaiduMap map;
LocationClient client;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
mapView = (MapView) findViewById(R.id.mv_main_map);
map = mapView.getMap();
map.setMapType(BaiduMap.MAP_TYPE_NORMAL);
map.setMyLocationEnabled(true);
client = new LocationClient(this);
MyLocationListener listener = new MyLocationListener();
client.registerLocationListener(listener);
LocationClientOption locationClientOption = new LocationClientOption();
locationClientOption.setCoorType("bd09ll");
locationClientOption.setScanSpan(1000);
locationClientOption.setOpenGps(true);
client.setLocOption(locationClientOption);
// MyLocationConfiguration config = new MyLocationConfiguration(
// com.baidu.mapapi.map.MyLocationConfiguration.LocationMode.NORMAL,
// true, null);
// map.setMyLocationConfigeration(config);
client.start();
}
@Override
protected void onResume() {
// TODO Auto-generated method stub
mapView.onResume();
super.onResume();
}
@Override
protected void onPause() {
mapView.onPause();
super.onPause();
}
@Override
protected void onDestroy() {
// 退出时销毁定位
client.stop();
// 关闭定位图层
map.setMyLocationEnabled(false);
mapView.onDestroy();
mapView = null;
super.onDestroy();
}
private boolean isFirstLoc = true;
public class MyLocationListener implements BDLocationListener {
@Override
public void onReceiveLocation(BDLocation location) {
double latitude=location.getLatitude();
double longitude=location.getLongitude();
MyLocationData locData = new MyLocationData.Builder()
.accuracy(location.getRadius()).direction(100)
.latitude(latitude)
.longitude(longitude).build();
map.setMyLocationData(locData);
if (isFirstLoc) {
isFirstLoc = false;
LatLng ll = new LatLng(location.getLatitude(),
location.getLongitude());
MapStatusUpdate u = MapStatusUpdateFactory.newLatLng(ll);
map.animateMapStatus(u);
}
LatLng ll=new LatLng(latitude, longitude);
GeoCoder gc=GeoCoder.newInstance();
OnGetGeoCoderResultListener listener=new OnGetGeoCoderResultListener() {
@Override
public void onGetReverseGeoCodeResult(ReverseGeoCodeResult result) {
if(result==null || result.error !=SearchResult.ERRORNO.NO_ERROR){
return;
}
AddressComponent ac=result.getAddressDetail();
StringBuilder sb=new StringBuilder();
sb.append(ac.province).append(" ").
append(ac.city).append(" ").
append(ac.district).append(" ").
append(ac.street).append(" ").append(ac.streetNumber);
Toast.makeText(getApplicationContext(), sb.toString(), Toast.LENGTH_LONG).show();
}
@Override
public void onGetGeoCodeResult(GeoCodeResult arg0) {
// TODO Auto-generated method stub
}
};
gc.setOnGetGeoCodeResultListener(listener);
ReverseGeoCodeOption rhco=new ReverseGeoCodeOption();
rhco.location(ll);
gc.reverseGeoCode(rhco);
}
}
}
这两个例子,一个使用android api进行定位,一个使用 baidumap api 进行定位;在测试中发现,使用 baidumap api 定位更加精确,但是也存在不小的偏差。这是因为 由于我国政府的法律明确规定GPS数据需要偏转才能匹配到电子地图上,因此android等3G手机定位出的位置都是经过偏移的,和实际的地理位置确实存在一定的偏差。而百度地图在这个基础上又进行了二次纠偏。
手机定位方式有:基站定位,网络定位,GPS定位,AGPS定位这几种方式。其中,基站定位比较快,能够在室内使用,但是精确度比较低,但是随着基站的密集度越来越高,定位也会越来越准确。GPS定位会比较耗时,不能够在室内使用,耗电量大,但是精确度比较高,不过绝大部分用户默认都是不开起GPS服务的。还有就是网络定位,它是根据IP地址等信息来进行定位。AGPS定位,很多人将它和基站定位混为一谈,但其实AGPS的本质仍然是GPS,只是它会使用基站信息对获取GPS进行辅助,然后还能对获取到的GPS结果进行修正,所以AGPS要比传统的GPS更快,准确度略高。