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

来源:互联网 发布:淘宝退货了还能评价吗 编辑:程序博客网 时间:2024/05/29 08:30

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

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

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

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

程序流程图凸显

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

下面是完整代码

这里贴出的代码是基于各位亦有一定百度地图开发基础为参照,如果看不懂可留下邮箱我每晚发送源代码给各位,我是用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.目前点为下降的趋势:isDirectionUpfalse     * 2.之前的点为上升的趋势:lastStatustrue     * 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;    }}

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

3 0