前不久写android应用需要用到轨迹记录,网上找了好多,结合自己看的文档,把这些写出来,给更多人看到,虽然很简单,但还是挺有用的。
主要思路
百度地图显示地图需要使用一个View来显示地图,地图上有一个图层用来显示轨迹,叫 com.baidu.mapapi.map.RouteOverlay,在RouteOverlay上添加路径信息,然后绘制在图层上,再显示出来就好鸟~
新建一个工程 就叫baduTraceDemo吧 工程配置
把下载的sdk文件里的jar和so库文件解压粗来,把百度定位需要的jar文件放在工程的libs文件夹下,然后在libs文件夹下新建一个文件夹叫 armeabi 把so文件放在这,就像这样
MainActivity里就放一个Button就好了,
MainActivity.java
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void OnClick(View v){
switch(v.getId()){
case R.id.startBtn :
Intent intent = new Intent(MainActivity.this,LocationOverlay.class);
startActivity(intent);
break;
default :
break;
}
}
}
把BaiduMapsApiDemo里面的DemoApplication直接复制过来,把里面的key 改成我们自己申请的
再定义地图显示图层,
public class LocationOverlay extends Activity {
/**
* 定位间隔 单位毫秒
*/
private int seconds = 1000 * 20;
/**
* 经纬度数组
*/
private geoPointArray gpArray ;
/**
* 定位开始点
*/
private GeoPoint start;
/**
* 定位结束点
*/
private GeoPoint end;
/**
* 定位点的集合 即路径
*/
private MKRoute mkRoute;
/**
* 定位图层
*/
private RouteOverlay routeOverlay;
// 定位相关
LocationClient mLocClient;
LocationData locData = null;
public MyLocationListenner myListener = new MyLocationListenner();
MapView mMapView = null; // 地图View
/**
* 地图控制器
*/
private MapController mMapController = null;
boolean isFirstLoc = true;//是否首次定位
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/**
* 使用地图sdk前需先初始化BMapManager.
* BMapManager是全局的,可为多个MapView共用,它需要地图模块创建前创建,
* 并在地图地图模块销毁后销毁,只要还有地图模块在使用,BMapManager就不应该销毁
*/
DemoApplication app = (DemoApplication)this.getApplication();
if (app.mBMapManager == null) {
app.mBMapManager = new BMapManager(getApplicationContext());
/**
* 如果BMapManager没有初始化则初始化BMapManager
*/
app.mBMapManager.init(DemoApplication.strKey,new DemoApplication.MyGeneralListener());
}
setContentView(R.layout.activity_locationoverlay);
CharSequence titleLable="记录轨迹";
setTitle(titleLable);
//地图初始化
mMapView = (MapView)findViewById(R.id.bmapView);
mMapController = mMapView.getController();
mMapView.getController().setZoom(14);
mMapView.getController().enableClick(true);
mMapView.setBuiltInZoomControls(true);
//定位初始化
mLocClient = new LocationClient( this );
locData = new LocationData();
mLocClient.registerLocationListener( myListener );
LocationClientOption option = new LocationClientOption();
option.setOpenGps(true);//打开gps
option.setCoorType("bd09ll"); //设置坐标类型
option.setScanSpan(seconds); // 定位间隔时间 单位毫秒
option.setIsNeedAddress(true); // 需要街道名称信息
option.setNeedDeviceDirect(false); // 不需要方向信息
mLocClient.setLocOption(option);
mLocClient.start();
mkRoute = new MKRoute();
routeOverlay = new RouteOverlay(LocationOverlay.this, mMapView);
routeOverlay.setData(mkRoute);
//添加定位图层
mMapView.getOverlays().add(routeOverlay);
//修改定位数据后刷新图层生效
mMapView.refresh();
}
/**
* 修改位置图标
* @param marker
*/
public void modifyLocationOverlayIcon(Drawable marker){
//当传入marker为null时,使用默认图标绘制
routeOverlay.setEnMarker(marker);
//修改图层,需要刷新MapView生效
mMapView.refresh();
}
/**
* 定位SDK监听函数
*/
public class MyLocationListenner implements BDLocationListener {
@Override
public void onReceiveLocation(BDLocation location) {
if (location == null)
return ;
locData.latitude = location.getLatitude();
locData.longitude = location.getLongitude();
//如果不显示定位精度圈,将accuracy赋值为0即可
locData.accuracy = 0;
// 此处可以设置 locData的方向信息, 如果定位 SDK 未返回方向信息,用户可以自己实现罗盘功能添加方向信息。
locData.direction = location.getDerect();
// 是手动触发请求或首次定位时
if (isFirstLoc){
gpArray = new geoPointArray();
start = new GeoPoint((int)(locData.latitude* 1e6), (int)(locData.longitude * 1e6));
end = new GeoPoint((int)(locData.latitude* 1e6), (int)(locData.longitude * 1e6));
// 把开始点放在路径中
gpArray.addGeoPoint(start);
// 构造路径
mkRoute.customizeRoute(start, end, gpArray.getGeoPointArray());
// 定位图层设置路径
routeOverlay.setData(mkRoute);
// 更新图层数据执行刷新后生效
mMapView.refresh();
// 移动地图到定位点
mMapController.animateTo(new GeoPoint((int)(locData.latitude* 1e6), (int)(locData.longitude * 1e6)));
isFirstLoc = false;
}else{
Log.i("test:LocationOverlay","loc:"+location.getLatitude()+","+location.getLongitude()+","+location.getAddrStr());
end = new GeoPoint((int)(locData.latitude* 1e6), (int)(locData.longitude * 1e6));
// 把当前点放在路径中
gpArray.addGeoPoint(end);
// 构造路径
mkRoute.customizeRoute(start, end, gpArray.getGeoPointArray());
// 定位图层设置路径
routeOverlay.setData(mkRoute);
// 移动地图到定位点
mMapController.animateTo(new GeoPoint((int)(locData.latitude* 1e6), (int)(locData.longitude * 1e6)));
// 刷新图层
mMapView.refresh();
}
}
@Override
public void onReceivePoi(BDLocation arg0) {
// TODO Auto-generated method stub
}
}
@Override
protected void onPause() {
mMapView.onPause();
super.onPause();
}
@Override
protected void onResume() {
mMapView.onResume();
super.onResume();
}
@Override
protected void onDestroy() {
//退出时销毁定位
if (mLocClient != null)
mLocClient.stop();
mMapView.destroy();
super.onDestroy();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mMapView.onSaveInstanceState(outState);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
mMapView.onRestoreInstanceState(savedInstanceState);
}
}
/**
* 经纬度数组类
*/
class geoPointArray{
private ArrayList <GeoPoint> mlist;
geoPointArray(){
mlist = new ArrayList<GeoPoint>();
}
public void addGeoPoint(GeoPoint point){
mlist.add(point);
}
/**
* @return 返回包含经纬度点的一纬数组
*/
public GeoPoint[] getGeoPointArray(){
GeoPoint []gp = new GeoPoint[mlist.size()];
for(int i=0; i<mlist.size(); i++){
gp[i] = mlist.get(i);
}
return gp;
}
}
地图图层的路径信息参数是 com.baidu.mapapi.search.MKRoute,而MKRoute里面还要构造一系列的点来组成路径customizeRoute(GeoPoint st, GeoPoint en, GeoPoint[] passby) 我们就自己写一个类来构造GeoPoint[] passby ,就是上面的geoPointArray,卧槽我研究这个研究了好久的说,当然还要重写监听器 MyLocationListenner,在这个监听器里面没定一次位就把得到的经纬度点添加我geoPointArray里面,
gpArray.addGeoPoint(currentPoint);
重新构造一次路径,再把路径添加到图层上
mkRoute.customizeRoute(start, end, gpArray.getGeoPointArray());
routeOverlay.setData(mkRoute);
最后是ManiFest.xml的填写,把百度需要的权限啊,服务啊,还有key添加上
添加百度的各种权限 ,百度真流氓,给的demo里面还要打电话的权限,这里用不到,就去掉了
<!--使用网络功能所需权限 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE">
</uses-permission>
<uses-permission android:name="android.permission.INTERNET">
</uses-permission>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE">
</uses-permission>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE">
</uses-permission>
<!-- SDK离线地图和cache功能需要读写外部存储器 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE">
</uses-permission>
<uses-permission android:name="android.permission.WRITE_SETTINGS">
</uses-permission>
<!-- 使用定位功能所需权限,demo已集成百度定位SDK,不使用定位功能可去掉以下6项 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION">
</uses-permission>
<permission android:name="android.permission.BAIDU_LOCATION_SERVICE">
</permission>
<uses-permission android:name="android.permission.BAIDU_LOCATION_SERVICE">
</uses-permission>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION">
</uses-permission>
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION">
</uses-permission>
在<application>里面添加这两行,服务权限,和key,自己用的话,记得把里面的key值换掉哦
<meta-data android:name="com.baidu.lbsapi.API_KEY" android:value="yRLtRhhaGdHuuLXeulWCtjSu"/>
<service android:name="com.baidu.location.f" android:enabled="true" android:process=":remote" />
3. 差不多完成了,可以编译试试了,
当然这里写的太简略了,一会把工程放下面,完成之后出去转一圈试试
4.终于写完鸟
卧槽,终于写完鸟,第一次写博客,感觉写博客好难,比写代码麻烦,不知道从哪里开始写,有东西讲不粗来的感觉,看来要好好练练了(OSC肿么没有预览),以后多写博客^_^
代码,还没用osc的git,就先用网盘吧 baiduTraceDemo.zip