百度地图绘制实时路线以及最短线路规划

如何使用百度地图绘制实时路线以及最短线路规划

最近在做百度地图的实时路线绘制,发现一些问题,比如由于定位漂移带来的路线绘制偏差,还有由于定位漂移,导致人未走动时,也会绘制路线等。百度鹰眼的线路纠偏个人感觉很一般啊。而且有限漂移了两百米的点他也没有纠正过来。所以最后还是决定自己写一个纠偏吧。而且百度地图官方的dome和示例代码真的很示例啊。然人摸不着头脑。ok进入正题,思路是这样的,因为实时绘制线路都是在室外,所以只采用gps定位,不采用无线网络定位。这样漂移一两百米的点基本不会出现。第二当人在等红绿灯时,人是静止的,但是定位有可能会漂移,所以这部分我们采用手机感应器进行判断是否移动。ok大体方向确定了,接下来就是进行功能划分然后开发了。功能模块主要涉及以下几点

需要项目源码的请移步到此下载
http://download.csdn.net/detail/zero172/9588471

  • 地图定位
  • 绘制当前位置
  • 获取位置进行纠偏
  • 判断是否移动
  • 绘制线路
  • 线路规划

程序流程图凸显

Created with Raphaël 2.2.0 开始 获取gps位置 不是第一个? 不是前10个? 手机是否处于运动? 两点间距离是否大于1米? 两点间距离是否小于90米? 保存位置 绘制线路 抛弃位置 保存位置 yes no yes no yes no yes no yes no

下面是完整代码

这里贴出的代码是基于各位亦有一定百度地图开发基础为参照,如果看不懂可留下邮箱我每晚发送源代码给各位,我是用jar包是3.7.3版的,各位如果使用其他版本的包,可能会出现百度地图初始化失败的现象。对我被坑过。

package com.example.baidutext;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.graphics.Color;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.view.Menu;
import android.view.MenuItem;
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.mapapi.SDKInitializer;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BaiduMap.OnMapLongClickListener;
import com.baidu.mapapi.map.BitmapDescriptor;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.MapStatus;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.MarkerOptions;
import com.baidu.mapapi.map.OverlayOptions;
import com.baidu.mapapi.map.PolylineOptions;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.search.route.BikingRouteResult;
import com.baidu.mapapi.search.route.DrivingRouteResult;
import com.baidu.mapapi.search.route.OnGetRoutePlanResultListener;
import com.baidu.mapapi.search.route.PlanNode;
import com.baidu.mapapi.search.route.RoutePlanSearch;
import com.baidu.mapapi.search.route.TransitRouteResult;
import com.baidu.mapapi.search.route.WalkingRoutePlanOption;
import com.baidu.mapapi.search.route.WalkingRouteResult;
import com.baidu.mapapi.utils.DistanceUtil;

public class MainActivity extends Activity {
	/**
	 * 百度地图视图
	 */
	private MapView map_v=null;
	/**
	 * 百度地图管理器
	 */
	private BaiduMap BaiDuMap;
	//	/**
	//	 * 位置管理器
	//	 */
	//	private LocationManager locationManager;
	/**
	 * 位置客户端
	 */
	private LocationClient locationClient = null;
	/**
	 * 获取位置时间间隔单位()
	 */
	private final int  time= 1000*9;
	//	/**
	//	 * 定位数据  
	//	 */
	//	private MyLocationData locData;
	/**
	 * 构建Marker图标  
	 */
	private BitmapDescriptor bitmap,StartBitmap,EndBitmap;  
	/**
	 *判断是否第一次定位
	 */
	private boolean isFirstLoc=true;
	/**
	 * 是否处于路线规划
	 */
	private boolean isGetRoute=false;
	/**
	 * 是否获取新路线
	 */
	private boolean isGetNewRoute=true;
	/**
	 * 定位位置数据
	 * 多线程在修改本数据,需要增加一个锁;
	 */
	private List<LatLng> pointList = new ArrayList<LatLng>();
	/**
//	 * 判断是否处于暂停
//	 */
	//	private boolean isPause=false;
	/**
	 * 描述地图将要发生的变化
	 */
	protected MapStatusUpdate msUpdate = null;
	/**
	 *  覆盖物
	 */
	protected OverlayOptions overlay,StartOverlay,EndOverlay;
	/**
	 *  路线覆盖物
	 */
	private PolylineOptions polyline = null;
	/**
	 * 手机加速度感应器服务注册
	 */
	private SensorManager sm = null;
	private Acc acc=new Acc();
	/**
	 * 最大距离单位()
	 */
	private final Double MaxDistance=90.00;
	/**
	 * 最小距离单位()
	 */
	private final Double MinDistance=2.0;
	/**
	 * 电源锁
	 */
	public static WakeLock wakeLock=null;
	private PowerReceiver powerReceiver = new PowerReceiver();
	/**
	 *最近位置信息
	 */
	private LatLng latLng;
	/**
	 * 因距离太大丢失的点数
	 */
	private int LostLoc=0;
	/**
	 * 第一次定位丢失的点数
	 */
	private int FLostLoc=0;
	/**
	 * 程序名称
	 */
	private final String APP_FOLDER_NAME = "LocationDemo";
	/**
	 * 路线规划监听
	 */
	private RoutePlanSearch mSearch;
	/**
	 * 当前位置,终点位置
	 */
	private LatLng ll,EndLL;
	/**
	 * 路线规划等待进度框
	 */
	private ProgressDialog progressDialog;
	/**
	 * 获取位置距离常量
	 */
	private int constant=0;
	/* (non-Javadoc)
	 * @see android.app.Activity#onCreate(android.os.Bundle)
	 */
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		sm = (SensorManager) getSystemService(SENSOR_SERVICE);
		SDKInitializer.initialize(getApplicationContext());
		
//		activityList.add(this);
		
		setContentView(R.layout.activity_main);
		init();
		//设置定位监听
		locationClient.registerLocationListener(new BDLocationListener(){

			@Override
			public void onReceiveLocation(BDLocation location) {
				// TODO Auto-generated method stub
				//				locData = new MyLocationData.Builder()  
				//				.accuracy(0)  
				//				// 此处设置开发者获取到的方向信息,顺时针0-360  
				//				.direction(0).latitude(location.getLatitude())  
				//				.longitude(location.getLongitude()).build();  
				//				// 设置定位数据  
				//				BaiDuMap.setMyLocationData(locData);  
				ll = new LatLng(location.getLatitude(),
						location.getLongitude());
				progressDialog.dismiss();
				if(isFirstLoc||isGetRoute){
					if(!isGetRoute){
						MapStatusUpdate u = MapStatusUpdateFactory.newLatLng(ll);
						BaiDuMap.animateMapStatus(u);
					}
					//				MyLocationConfiguration config = new MyLocationConfiguration(LocationMode.NORMAL, true, bitmap);//普通(LocationMode.NORMAL)、跟随(LocationMode.FOLLOWING)、罗盘(LocationMode.COMPASS)
					//				BaiDuMap.setMyLocationConfigeration(config);
					isFirstLoc=false;
					if(constant<pointList.size()){
						if(DistanceUtil.getDistance(pointList.get(constant),ll)>DistanceUtil.getDistance(pointList.get(constant+1),ll)){
							save("距离: "+DistanceUtil.getDistance(pointList.get(constant+1),ll)+" 时间: "+getStringDate()+" 点数: "+constant);
							if(DistanceUtil.getDistance(pointList.get(constant+1),ll)>100&&isGetNewRoute){
								IsGetNewRoute();
							}
							constant++;
						}else{
							save("距离: "+DistanceUtil.getDistance(pointList.get(constant),ll)+" 时间: "+getStringDate()+" 点数: "+constant);
							if(DistanceUtil.getDistance(pointList.get(constant),ll)>100&&isGetNewRoute){
								IsGetNewRoute();
							}
						}
					}
					
					drawRealtimePoint(ll);
				}else{
					showRealtimeTrack(location);
				}
				
			}
		});
		locationClient.start();
		//路线规划回调
		OnGetRoutePlanResultListener listener = new OnGetRoutePlanResultListener(){

			@Override
			public void onGetBikingRouteResult(BikingRouteResult arg0) {
				// TODO Auto-generated method stub
			}

			@Override
			public void onGetDrivingRouteResult(DrivingRouteResult arg0) {
				// TODO Auto-generated method stub
			}

			@Override
			public void onGetTransitRouteResult(TransitRouteResult arg0) {
				// TODO Auto-generated method stub
			}

			@Override
			public void onGetWalkingRouteResult(WalkingRouteResult WalkingRoute) {
				// TODO Auto-generated method stub
				if(WalkingRoute.getRouteLines()!=null){
					constant =0;
					isGetNewRoute=true;
					for(int i=0;i<WalkingRoute.getRouteLines().get(0).getAllStep().size();i++){
						pointList.addAll(WalkingRoute.getRouteLines().get(0).getAllStep().get(i).getWayPoints());
					}
					save("时间: "+getStringDate()+" 总点数: "+pointList.size());
				}
				else
//					Toast.makeText(MainActivity.this, "获取线路失败", 3000).show();
					System.out.println("ccccccccccccccccccc");
			}
			
		};
		mSearch.setOnGetRoutePlanResultListener(listener);
		//长按地图监听
		BaiDuMap.setOnMapLongClickListener(new OnMapLongClickListener() {
			
			@Override
			public void onMapLongClick(LatLng arg0) {
				// TODO Auto-generated method stub
				EndLL=arg0;
				StartRoutePlan();
			}
		});
//		mSearch.destroy();
		Toast.makeText(this, "正在定位....", 3000).show();
	}
	/**
	 * 初始化资源
	 */
	protected void init(){
		map_v=(MapView)findViewById(R.id.bmapView);
		bitmap = BitmapDescriptorFactory.fromResource(R.drawable.map_d);
		StartBitmap= BitmapDescriptorFactory.fromResource(R.drawable.start_bitmap);
		EndBitmap= BitmapDescriptorFactory.fromResource(R.drawable.end_bitmap);
		//		locationManager = (LocationManager) getSystemService(this.LOCATION_SERVICE);
		BaiDuMap=map_v.getMap();
		locationClient = new LocationClient(this);
		LocationClientOption option = new LocationClientOption();
		option.setOpenGps(true);        //是否打开GPS
		option.setCoorType("bd09ll");       //设置返回值的坐标类型。bd09ll百度加密经纬度坐标,bd09百度加密墨卡托坐标,gcj02国测局加密经纬度坐标
		option.setPriority(LocationClientOption.GpsOnly);  //设置定位优先级,只取gps定位;
		option.setProdName(APP_FOLDER_NAME); //设置产品线名称。
		option.setScanSpan(time);    //设置定时定位的时间间隔。单位毫秒
		locationClient.setLocOption(option);
		BaiDuMap.setMapType(BaiduMap.MAP_TYPE_NORMAL);//普通地图模式 ;MAP_TYPE_SATELLITE为卫星地图;MAP_TYPE_NONE空白地图;
		BaiDuMap.setTrafficEnabled(false);//不开启交通视图;
		map_v.showZoomControls(false);//不开启底部放大缩小 图标;
		BaiDuMap.animateMapStatus(MapStatusUpdateFactory.zoomTo(18));//设置地图缩放
		BaiDuMap.setMyLocationEnabled(true);//开启定位图层
		BaiDuMap.setMaxAndMinZoomLevel(18.0f,1.0f);
		mSearch = RoutePlanSearch.newInstance();
		progressDialog=new ProgressDialog(this);
	}

	@Override
	protected void onStart() {
		// TODO Auto-generated method stub
		super.onStart();
	}
	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		map_v.onDestroy();
		BaiDuMap.setMyLocationEnabled(false);
		locationClient.stop();
		map_v = null;
		releaseWakeLock();
		sm.unregisterListener(acc);
		mSearch.destroy();
		saveArray();
	}

	@Override
	protected void onPause() {
		// TODO Auto-generated method stub
		super.onPause();
		map_v.onPause();
	}
	@Override
	public boolean onMenuItemSelected(int featureId, MenuItem item) {
		// TODO Auto-generated method stub
		if(item.getItemId()==R.id.action_settings)
		{
			progressDialog.setTitle("路线规划");
			progressDialog.setMessage("正在清除路线请稍后。。");
			progressDialog.show();
			isGetRoute=false;
			if(pointList!=null||pointList.size()>0)
				pointList.clear();
			if(StartOverlay!=null)
				StartOverlay=null;
			if(EndOverlay!=null)
				EndOverlay=null;
		}
		return super.onMenuItemSelected(featureId, item);
		
	}
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// TODO Auto-generated method stub
		return super.onCreateOptionsMenu(menu);
	}
	/*
	 * 将数据临时保存到xml文件
	 */
	private boolean saveArray() {  
		deleteXML();
		SharedPreferences sp= getSharedPreferences("lat", Context.MODE_APPEND);  
		Editor mEdit1= sp.edit(); 
		mEdit1.remove("Status_size");
		mEdit1.putInt("Status_size",pointList.size());

		for(int i=0;i<pointList.size();i++) {  
			mEdit1.remove("lat_" + i);  
			mEdit1.putString("lat_" + i,pointList.get(i).latitude+"");
			mEdit1.remove("lon_" + i);  
			mEdit1.putString("lon_" + i,pointList.get(i).longitude+"");
		}  
		return mEdit1.commit();	   
	}
	@Override
	protected void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
		map_v.onResume();
		sm.registerListener(acc, 
				Sensor.TYPE_ACCELEROMETER ,
				SensorManager.SENSOR_DELAY_NORMAL);
		acquireWakeLock();
		//		if(latLng!=null)
		//			drawRealtimePoint(latLng);
	}
	//	/*
	//	 * 读取xml文件存储数据;
	//	 * @param mContext
	//	 */
	//	protected void loadArray(Context mContext) {	
	//		SharedPreferences mSharedPreference1=getSharedPreferences("lat", Context.MODE_PRIVATE);   
	//		//		  pointList.clear();  
	//		int size = mSharedPreference1.getInt("Status_size", 0);	
	//
	//		for(int i=0;i<size;i++) {
	//			Double lat1=Double.valueOf(mSharedPreference1.getString("lat_"+i, null));
	//			Double lon1=Double.valueOf(mSharedPreference1.getString("lat_"+i, null));
	//			pointList.add(new LatLng(lat1, lon1));	
	//		}
	//	}
	/*
	 * 删除xml文件
	 */
	private void deleteXML() {
		File file = new File("/data/data/" + getPackageName().toString()  
				+ "/shared_prefs", "lat.xml");  
		if (file.exists()) {  
			file.delete(); 
		}
	}
	/*
	 * 显示实时轨迹
	 * 
	 * @param realtimeTrack
	 */
	protected void showRealtimeTrack(BDLocation location) {
		double latitude = location.getLatitude();
		double longitude = location.getLongitude();
		if (Math.abs(latitude - 0.0) < 0.000001 && Math.abs(longitude - 0.0) < 0.000001) {
			Toast.makeText(this, "当前无轨迹点", 3000).show();
		} else {
			latLng = new LatLng(latitude, longitude);
			if (IsMove(latLng,location)) {
				// 绘制实时点
				drawRealtimePoint(latLng);
			}
		}

	}

	/*
	 * 绘制实时点
	 * 
	 * @param points
	 */
	private void drawRealtimePoint(LatLng point) {

		BaiDuMap.clear();
		polyline=null;
		MapStatus mMapStatus = new MapStatus.Builder().target(point).build();

		msUpdate = MapStatusUpdateFactory.newMapStatus(mMapStatus);


		overlay = new MarkerOptions().position(point)
				.icon(bitmap).zIndex(9).draggable(true);
		
		if (pointList.size() >=2 && pointList.size() <= 100000) {
			// 添加路线(轨迹)
			polyline = new PolylineOptions().width(10)
					.color(Color.RED).points(pointList);
		}

		addMarker();

	}
	/*
	 * 添加地图覆盖物
	 */
	protected  void addMarker() {

		if (null != msUpdate) {
			BaiDuMap.setMapStatus(msUpdate);
		}

		// 路线覆盖物
		if (null != polyline) {
			BaiDuMap.addOverlay(polyline);
		}

		// 实时点覆盖物
		if (null != overlay) {
			BaiDuMap.addOverlay(overlay);
		}

		//起点覆盖物
		if (null != StartOverlay) {
			BaiDuMap.addOverlay(StartOverlay);
		}
		// 终点覆盖物
		if (null != EndOverlay) {
			BaiDuMap.addOverlay(EndOverlay);
		}
	}

	/*
	 *@author chenzheng_Java  
	 *保存用户输入的内容到文件 
	 */  
	private void save(String content) {  

		try {  
			/* 根据用户提供的文件名,以及文件的应用模式,打开一个输出流.文件不存系统会为你创建一个的, 
			 * 至于为什么这个地方还有FileNotFoundException抛出,我也比较纳闷。在Context中是这样定义的 
			 *   public abstract FileOutputStream openFileOutput(String name, int mode) 
			 *   throws FileNotFoundException; 
			 * openFileOutput(String name, int mode); 
			 * 第一个参数,代表文件名称,注意这里的文件名称不能包括任何的/或者/这种分隔符,只能是文件名 
			 *          该文件会被保存在/data/data/应用名称/files/chenzheng_java.txt 
			 * 第二个参数,代表文件的操作模式 
			 *          MODE_PRIVATE 私有(只能创建它的应用访问) 重复写入时会文件覆盖 
			 *          MODE_APPEND  私有   重复写入时会在文件的末尾进行追加,而不是覆盖掉原来的文件 
			 *          MODE_WORLD_READABLE 公用  可读 
			 *          MODE_WORLD_WRITEABLE 公用 可读写 
			 *  */  
			content=content+"\n";
			FileOutputStream outputStream = openFileOutput("Log.log",Activity.MODE_APPEND);  
			outputStream.write(content.getBytes());  
			outputStream.flush();  
			outputStream.close();  
		} catch (FileNotFoundException e) {  
			e.printStackTrace();  
		} catch (IOException e) {  
			e.printStackTrace();  
		}  

	}  
	/*
	 * 获取系统时间
	 */
	private String getStringDate() {
		Date currentTime = new Date();
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String dateString = formatter.format(currentTime);
		return dateString;
	}

	/*
	 * 判断手机是否在运动
	 */
	private boolean IsMove(LatLng latLng,BDLocation location){
		
		if(pointList.size()>=1){
			Double dis=DistanceUtil.getDistance(pointList.get(pointList.size()-1),latLng);
			//判断手机是否静止,如果静止,判定采集点无效,直接抛弃
			if(!acc.is_Acc&&acc.IsRun){
				acc.IsRun=false;
				return false;
			}
			//判断是否是第一次定位置,如果是第一次定位并且因为第一次抛弃的位置数量小于10个则判断两点间距离大小
			if(FLostLoc<10){
				FLostLoc=FLostLoc+1;
				if(dis>10&&FLostLoc<6){//距离大于十米,而且被抛弃数量少于5个则说明有可能是获取位置失败
					pointList.clear();
					pointList.add(latLng);//更新位置
					return false;
				}
				if(dis>0&&dis<10&&FLostLoc>=6)//如果距离在10米内,则表示客户正在运动,直接跳出
					FLostLoc=11;
			}
			//根据两点间距离判断是否发生定位漂移,如果漂移距离小于MinDistance则抛弃,如果漂移距离大于MaxDistance则取两点的中间点.
				if(dis<=MinDistance){
					if((dis<=MinDistance||dis>=MaxDistance)){
					return false;
				}

				if(LostLoc>=4){
					Double newlatitude=(latLng.latitude+pointList.get(pointList.size()-1).latitude)/2;
					Double newlongitude=(latLng.longitude+pointList.get(pointList.size()-1).longitude)/2;
					latLng = new LatLng(newlatitude, newlongitude);
				}else{
					LostLoc=LostLoc+1;
					return false;
				}

			}
			LostLoc=0;//重置丢失点的个数
			//			pointList.add(latLng);
			acc.is_Acc=false;
		}
		pointList.add(latLng);
		return true;
	}
	/*
	 * 开始规划线路
	 */
	private void StartRoutePlan() {
		// TODO Auto-generated method stub
		progressDialog.setTitle("路线规划");
		progressDialog.setMessage("正在规划路线请稍后。。");
		progressDialog.show();
		if(pointList!=null||pointList.size()>0)
			pointList.clear();
		PlanNode stNode = PlanNode.withLocation(ll);  
		StartOverlay=new MarkerOptions().position(ll)
				.icon(StartBitmap).zIndex(9);
		
		PlanNode enNode = PlanNode.withLocation(EndLL);
		EndOverlay=new MarkerOptions().position(EndLL)
				.icon(EndBitmap).zIndex(9);
		mSearch.walkingSearch((new WalkingRoutePlanOption())  
					.from(stNode)  
					.to(enNode));
		isGetRoute=true;
	}
	/*
	 * 获取新路线
	 */
	private void IsGetNewRoute() {
		// TODO Auto-generated method stub
		AlertDialog.Builder builder = new Builder(this);
		builder.setMessage("您已偏移路线,是否重新规划路线?");
		builder.setTitle("路线偏移");
		builder.setPositiveButton("重新规划", new OnClickListener() {   
			@Override
			public void onClick(DialogInterface dialog, int which) {
				StartRoutePlan();
				dialog.dismiss();
			}
		});  
		builder.setNegativeButton("按原规划", new OnClickListener() {   
			@Override
			public void onClick(DialogInterface dialog, int which) {
			dialog.dismiss();
		}
		});
		builder.create().show();
		isGetNewRoute=false;
	}
	/*
	 * 申请电源锁 
	 */
	private void acquireWakeLock() {
		if (null == wakeLock) {

			PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);

			wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE,getClass().getName());

		}
		IntentFilter filter = new IntentFilter();
		filter.addAction(Intent.ACTION_SCREEN_ON);
		filter.addAction(Intent.ACTION_SCREEN_OFF);
		registerReceiver(powerReceiver, filter);
	}

	/*
	 * 释放电源锁
	 */
	private void releaseWakeLock() {
		unregisterReceiver(powerReceiver);
	}
}

##下面PowerReceiver文件的内容

这里贴出的代码主要是完成电源锁的开启和撤销

package com.example.baidutext;

import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class PowerReceiver extends BroadcastReceiver {

    @SuppressLint("Wakelock")
    @Override
    public void onReceive(final Context context, final Intent intent) {
        final String action = intent.getAction();

        //按下电源键,关闭屏幕
        if (Intent.ACTION_SCREEN_OFF.equals(action)) {
            System.out.println("screen off,acquire wake lock!");
            if (null != MainActivity.wakeLock && !(MainActivity.wakeLock.isHeld())) {
            	MainActivity.wakeLock.acquire();
            }
         //按下电源键,打开屏幕  
        } else if (Intent.ACTION_SCREEN_ON.equals(action)) {
            System.out.println("screen on,release wake lock!");
            if (null != MainActivity.wakeLock && MainActivity.wakeLock.isHeld()) {
            	MainActivity.wakeLock.release();
            }
        }
    }

}

##下面Acc文件的内容

这个文件主要是获取加速感应器的值,然后通过波峰和波谷的插值,以及两个波峰之间的时间差来判断手机是否处于移动。关于详细的大家可查找计步器原理。一下算法非本人原创,但是一直找不到原创作者,如作者本人看到,可与我联系

package com.example.baidutext;

import android.hardware.Sensor;
import android.hardware.SensorListener;
/**
 *根据加速度判断手机是否处于静止
 * @author Administrator
 *
 */
public class Acc implements SensorListener {
	//	/**
	//	 * 手机加速度各方向状态
	//	 */
	//	private float F_Acc_x,F_Acc_y,F_Acc_z;
	//	/**
	//	 * 上次获取状态时间
	//	 */
	//	private long LastUpdateTime;   
	//	/**
	//	 * 两次获取状态时间间隔单位()
	//	 */
	//	private final int UPTATE_INTERVAL_TIME = 1000*10;   
	//	
	/**
	 * 当前传感器的值
	 */
	private float gravityNew = 0;
	/**
	 * 上次传感器的值
	 */
	private float gravityOld = 0;
	/**
	 * 此次波峰的时间
	 */
	private long timeOfThisPeak = 0;
	/**
	 * 上次波峰的时间
	 */
	private long timeOfLastPeak = 0;
	/**
	 * 当前的时间
	 */
	private long timeOfNow = 0;;
	/**
	 * 波峰值
	 */
	private float peakOfWave = 0;
	/**
	 * 波谷值
	 */
	private float valleyOfWave = 0;
	/**
	 * 初始阈值
	 */
	private float ThreadValue = (float) 2.0;
	/**
	 * 动态阈值需要动态的数据,这个值用于这些动态数据的阈值
	 */
	private final float initialValue = (float) 1.3;
	/**
	 * 上一点的状态,上升还是下降
	 */
	private boolean lastStatus = false;
	/**
	 * 是否上升的标志位
	 */
	private boolean isDirectionUp = false;
	/**
	 * 持续上升次数
	 */
	private int continueUpCount = 0;
	/**
	 * 上一点的持续上升的次数,为了记录波峰的上升次数
	 */
	private int continueUpFormerCount = 0;
	public boolean is_Acc=false;
	//	private int ACC=30;//手机感应器波动范围,30以内判定手机处于静止
	private int tempCount = 0;
	private final int valueNum = 4;
	/**
	 * 用于存放计算阈值的波峰波谷差值
	 */
	private float[] tempValue = new float[valueNum];
	/**
	 * 记录波峰数量
	 */
	private int CountValue = 0;
	/**
	 * 判断传感器是否在运行
	 */
	public boolean IsRun=false; 
	
	public Acc(){
		//		LastUpdateTime=System.currentTimeMillis();
	}
	@Override
	public void onAccuracyChanged(int arg0, int arg1) {
		// TODO Auto-generated method stub

	}
	/**
	 * 感应器状态改变时自动调用此方法
	 */
	@Override
	public void onSensorChanged(int arg0, float[] arg1) {
		// TODO Auto-generated method stub
		IsRun=true;
		if(arg0==Sensor.TYPE_ACCELEROMETER){
			//			JIUjia(arg1);
			gravityNew = (float) Math.sqrt(arg1[0] * arg1[0]
					+ arg1[1] * arg1[1] + arg1[2] * arg1[2]);
			DetectorNewStep(gravityNew);
		}
	}

	//	 protected boolean JIUjia(float[] values) {
	//	    	if(F_Acc_x!=0){
	//	    		long currentUpdateTime = System.currentTimeMillis();   
	//	    		long timeInterval = currentUpdateTime - LastUpdateTime;    
	//	    		if(timeInterval < UPTATE_INTERVAL_TIME)
	//	    			return false;
	//	    		LastUpdateTime=currentUpdateTime;
	//	    		float tem0=values[0]-F_Acc_x;
	//	    		float tem1=values[1]-F_Acc_y;
	//	    		float tem2=values[2]-F_Acc_z;
	//	    		System.out.println(Math.abs(tem0)+","+Math.abs(tem1)+","+Math.abs(tem2));
	//	    		if(Math.abs(tem0)>ACC||Math.abs(tem1)>ACC||Math.abs(tem2)>ACC)
	//	    			is_Acc=true;
	//	    		
	//	    	}
	//	    	F_Acc_x=values[0];
	//	    	F_Acc_y=values[1];
	//	    	F_Acc_z=values[2];
	//	    	return is_Acc;
	//
	//	    }

	/*
	 * 检测步子
	 * 1.传入sersor中的数据
	 * 2.如果检测到了波峰,并且符合时间差以及阈值的条件,则判定为1* 3.符合时间差条件,波峰波谷差值大于initialValue,则将该差值纳入阈值的计算中
	 * */
	public void DetectorNewStep(float values) {
		if (gravityOld == 0) {
			gravityOld = values;
		} else {
			if (DetectorPeak(values, gravityOld)) {
				timeOfLastPeak = timeOfThisPeak;
				timeOfNow = System.currentTimeMillis();
				if ((timeOfNow - timeOfLastPeak) >= 250&& (peakOfWave - valleyOfWave >= ThreadValue)) {
					timeOfThisPeak = timeOfNow;
					//两步之间间隔大于4秒则不算
					if((timeOfNow-timeOfLastPeak)>40000)
						CountValue=0;
					else
						CountValue++;
					//只有手机连续摇晃4下或者以上才判定为走路
					if(CountValue>=4)
						is_Acc=true;
					//	                    mStepListeners.onStep();
				}
				if (timeOfNow - timeOfLastPeak >= 250&& (peakOfWave - valleyOfWave >= initialValue)) {
					timeOfThisPeak = timeOfNow;
					ThreadValue = Peak_Valley_Thread(peakOfWave - valleyOfWave);
				}
			}
		}
		gravityOld = values;
	}

	/*
	 * 检测波峰
	 * 以下四个条件判断为波峰:
	 * 1.目前点为下降的趋势:isDirectionUp为false
	 * 2.之前的点为上升的趋势:lastStatus为true
	 * 3.到波峰为止,持续上升大于等于4* 4.波峰值大于20
	 * 记录波谷值
	 * 1.观察波形图,可以发现在出现步子的地方,波谷的下一个就是波峰,有比较明显的特征以及差值
	 * 2.所以要记录每次的波谷值,为了和下次的波峰做对比
	 * */
	public boolean DetectorPeak(float newValue, float oldValue) {
		lastStatus = isDirectionUp;
		if (newValue >= oldValue) {
			isDirectionUp = true;
			continueUpCount++;
		} else {
			continueUpFormerCount = continueUpCount;
			continueUpCount = 0;
			isDirectionUp = false;
		}

		if (!isDirectionUp && lastStatus&& (continueUpFormerCount >= 4 || oldValue >= 20&&oldValue<=40)) {
			peakOfWave = oldValue;
			return true;
		} else if (!lastStatus && isDirectionUp) {
			valleyOfWave = oldValue;
			return false;
		} else {
			return false;
		}
	}

	/*
	 * 阈值的计算
	 * 1.通过波峰波谷的差值计算阈值
	 * 2.记录4个值,存入tempValue[]数组中
	 * 3.在将数组传入函数averageValue中计算阈值
	 * */
	public float Peak_Valley_Thread(float value) {
		float tempThread = ThreadValue;
		if (tempCount < valueNum) {
			tempValue[tempCount] = value;
			tempCount++;
		} else {
			tempThread = averageValue(tempValue, valueNum);
			for (int i = 1; i < valueNum; i++) {
				tempValue[i - 1] = tempValue[i];
			}
			tempValue[valueNum - 1] = value;
		}
		return tempThread;

	}

	/*
	 * 梯度化阈值
	 * 1.计算数组的均值
	 * 2.通过均值将阈值梯度化在一个范围里
	 * */
	public float averageValue(float value[], int n) {
		float ave = 0;
		for (int i = 0; i < n; i++) {
			ave += value[i];
		}
		ave = ave / valueNum;
		if (ave >= 8)
			ave = (float) 4.3;
		else if (ave >= 7 && ave < 8)
			ave = (float) 3.3;
		else if (ave >= 4 && ave < 7)
			ave = (float) 2.3;
		else if (ave >= 3 && ave < 4)
			ave = (float) 2.0;
		else {
			ave = (float) 1.3;
		}
		return ave;
	}
}

至此就全部结束了,各位如有其他问题可直接留言给我。

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页