类似现在很火的诸如跑步记录路程,可以跟踪用户的移动轨迹,并通过地图可视化
APK : http://fir.im/l2jq
思路:高精度定位 + 画线
使用的是高德地图:http://lbs.amap.com/
去官网下载SDK,以及demo,会看就行官网给的demo很强大
考虑到测试时没有网络,所以加了离线地图
首页是使用的PreferenceActivity,这样省的写button了,很简单,就一句话就好
import android.os.Bundle; import android.preference.PreferenceActivity; /** 定位 + 画线 */ public class MainActivity extends PreferenceActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.addPreferencesFromResource(R.xml.category); } }然后category.xml文件是这么写的
<?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" android:key="root_screen"> <Preference android:title="Version 1.1.6" /> <Preference android:title="离线地图下载" > <intent android:targetPackage="android.cl.com.forthtest03_map" android:targetClass="android.cl.com.forthtest03_map.offlinemap.OfflineMapActivity" > </intent> </Preference> <Preference android:title="地图追随" > <intent android:targetPackage="android.cl.com.forthtest03_map" android:targetClass="android.cl.com.forthtest03_map.mapfolllow.MapFollowActivity" > </intent> </Preference> </PreferenceScreen>离线地图是直接使用的官网给的参考,地图跟踪是定位+画线,demo里都给出了,我直接给出相关代码
import android.app.Activity; import android.cl.com.forthtest03_map.R; import android.graphics.Color; import android.os.Bundle; import android.util.Log; import android.widget.Toast; import com.amap.api.location.AMapLocation; import com.amap.api.location.AMapLocationClient; import com.amap.api.location.AMapLocationClientOption; import com.amap.api.location.AMapLocationListener; import com.amap.api.maps.AMap; import com.amap.api.maps.CameraUpdateFactory; import com.amap.api.maps.LocationSource; import com.amap.api.maps.MapView; import com.amap.api.maps.model.LatLng; import com.amap.api.maps.model.PolylineOptions; /** * Created by Administrator on 2016/1/23. * 在地图上显示走过的路径 */ public class MapFollowActivity extends Activity implements LocationSource,AMapLocationListener { private AMap aMap; private MapView mapView; //以前的定位点 private LatLng oldLatLng; //是否是第一次定位 private boolean isFirstLatLng; private OnLocationChangedListener mListener; private AMapLocationClient mlocationClient; private AMapLocationClientOption mLocationOption; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.map_follow); mapView = (MapView) findViewById(R.id.map); mapView.onCreate(savedInstanceState);// 此方法必须重写 isFirstLatLng = true; init(); } private void init(){ if (aMap == null) { aMap = mapView.getMap(); } //定位 aMap.setLocationSource(this);// 设置定位监听 aMap.getUiSettings().setMyLocationButtonEnabled(true);// 设置默认定位按钮是否显示 aMap.setMyLocationEnabled(true);// 设置为true表示显示定位层并可触发定位,false表示隐藏定位层并不可触发定位,默认是false // 设置定位的类型为定位模式 ,可以由定位 LOCATION_TYPE_LOCATE、跟随 LOCATION_TYPE_MAP_FOLLOW 或地图根据面向方向旋转 LOCATION_TYPE_MAP_ROTATE aMap.setMyLocationType(AMap.LOCATION_TYPE_MAP_ROTATE); //画线 // 缩放级别(zoom):地图缩放级别范围为【4-20级】,值越大地图越详细 aMap.moveCamera(CameraUpdateFactory.zoomTo(16)); //使用 aMap.setMapTextZIndex(2) 可以将地图底图文字设置在添加的覆盖物之上 aMap.setMapTextZIndex(2); // setUpMap(new LatLng(43.828, 87.621), new LatLng(43.800, 87.621)); } /**绘制两个坐标点之间的线段,从以前位置到现在位置*/ private void setUpMap(LatLng oldData,LatLng newData ) { // 绘制一个大地曲线 aMap.addPolyline((new PolylineOptions()) .add(oldData, newData) .geodesic(true).color(Color.GREEN)); } /** * 定位成功后回调函数 */ @Override public void onLocationChanged(AMapLocation amapLocation) { if (mListener != null && amapLocation != null) { if (amapLocation != null && amapLocation.getErrorCode() == 0) { mListener.onLocationChanged(amapLocation);// 显示系统小蓝点 // //定位成功 LatLng newLatLng = Utils.getLocationLatLng(amapLocation); // Log.e("Amap", amapLocation.getLatitude() + "," + amapLocation.getLongitude()); // Toast.makeText(this, amapLocation.getLatitude() + "," + amapLocation.getLongitude() , Toast.LENGTH_SHORT).show(); if(isFirstLatLng){ //记录第一次的定位信息 oldLatLng = newLatLng; isFirstLatLng = false; } //位置有变化 if(oldLatLng != newLatLng){ Log.e("Amap", amapLocation.getLatitude() + "," + amapLocation.getLongitude()); setUpMap( oldLatLng , newLatLng ); oldLatLng = newLatLng; } } else { String errText = "定位失败," + amapLocation.getErrorCode()+ ": " + amapLocation.getErrorInfo(); Log.e("AmapErr", errText); // Toast.makeText(this, errText, Toast.LENGTH_SHORT).show(); if(isFirstLatLng){ Toast.makeText(this, errText, Toast.LENGTH_SHORT).show(); } } } } /** * 激活定位 */ @Override public void activate(OnLocationChangedListener listener) { mListener = listener; if (mlocationClient == null) { mlocationClient = new AMapLocationClient(this); mLocationOption = new AMapLocationClientOption(); //设置定位监听 mlocationClient.setLocationListener(this); //设置为高精度定位模式 mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy); //设置定位参数 mlocationClient.setLocationOption(mLocationOption); mLocationOption.setOnceLocation(false); /** * 设置是否优先返回GPS定位结果,如果30秒内GPS没有返回定位结果则进行网络定位 * 注意:只有在高精度模式下的单次定位有效,其他方式无效 */ mLocationOption.setGpsFirst(true); // 设置发送定位请求的时间间隔,最小值为1000ms,1秒更新一次定位信息 mLocationOption.setInterval(1000); // 此方法为每隔固定时间会发起一次定位请求,为了减少电量消耗或网络流量消耗, // 注意设置合适的定位时间的间隔(最小间隔支持为2000ms),并且在合适时间调用stopLocation()方法来取消定位请求 // 在定位结束后,在合适的生命周期调用onDestroy()方法 // 在单次定位情况下,定位无论成功与否,都无需调用stopLocation()方法移除请求,定位sdk内部会移除 mlocationClient.startLocation(); } } /** * 停止定位 */ @Override public void deactivate() { mListener = null; if (mlocationClient != null) { mlocationClient.stopLocation(); mlocationClient.onDestroy(); } mlocationClient = null; } /** * 方法必须重写 */ @Override protected void onResume() { super.onResume(); mapView.onResume(); } /** * 方法必须重写 */ @Override protected void onPause() { super.onPause(); mapView.onPause(); deactivate(); } /** * 方法必须重写 */ @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); mapView.onSaveInstanceState(outState); } /** * 方法必须重写 */ @Override protected void onDestroy() { super.onDestroy(); mapView.onDestroy(); if(null != mlocationClient){ mlocationClient.onDestroy(); } } }然后布局文件就一个地图试图
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <com.amap.api.maps.MapView android:id="@+id/map" android:layout_width="match_parent" android:layout_height="match_parent" /> </RelativeLayout>代码上都写了注释,由于想定位时那个定位图标跟着手机头的方向旋转,发现只有一个模式( LOCATION_TYPE_MAP_ROTATE)可以使用,使用的是GPS(优先)+网络 循环 定位的方式,1S定位一次,可能会有些耗电,官方给提供了方法,默认不设置就是采用官方的默认方法,最快2S定一次位,有注释,会根据算法计算下一次定位时间,由于是自己测试,就1S定位一下
源码:http://download.csdn.net/detail/i_do_can/9415980