Android百度地图的轨迹回放

 Android百度地图轨迹播放暂停速度调控,进度调控

摘要:之前看到了百度地图的api以为Android的实现方式也是很简单的,结果百度地图的demo并没有Android的轨迹播放的demo,有的也是简单的轨迹播放并没有进度和速度的控制,最后只能是自己做的。

   可以是实现小汽车轨迹的平滑移动,并且并且弹框的内容可以跟着小汽车的变化而变化。汽车轨迹播放的暂停与播放进度的控制速度的控制,并且如果车辆是移动到外面的还可以自动移动到屏幕中间

一:结果展示(因为gif的大小只能是5M所以录制的比较少 )


二:代码展示
activity的代码展示
这里请求的是本地的json格式的数据,但是里面也注释了HTTP的请求方式有需要的可以参考。

package com.boxin.truck.activity.manager;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.graphics.Point;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;

import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BitmapDescriptor;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.InfoWindow;
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.Marker;
import com.baidu.mapapi.map.MarkerOptions;
import com.baidu.mapapi.map.OverlayOptions;
import com.baidu.mapapi.map.Polyline;
import com.baidu.mapapi.map.PolylineOptions;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.model.LatLngBounds;
import com.boxin.truck.R;
import com.boxin.truck.map.MapActivity;
import com.boxin.truck.model.BaiduTrack;
import com.boxin.truck.util.JsonUtils;
import com.boxin.truck.util.LogUtils;
import com.boxin.truck.util.TimeUtils;
import com.boxin.truck.util.ToastUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

/**
 * Created by lsx on 2020/03/17.
 * 轨迹播放
 */
public class BaiduTrackActivity extends MapActivity implements View.OnClickListener {
    @BindView(R.id.title_tv)
    public TextView mTitleTV;
    @BindView(R.id.back_container)
    public RelativeLayout mBackContainer;
    @BindView(R.id.linearLayout)
    public LinearLayout linearLayout;
    @BindView(R.id.bmapView)
    protected MapView bmapView;
    @BindView(R.id.map)
    protected com.google.android.gms.maps.MapView googleView;
    @BindView(R.id.data_container)
    public LinearLayout mDataContainer;
    @BindView(R.id.top_truck_container)
    public RelativeLayout mTopTruckContainer;
    @BindView(R.id.top_truck_tv)
    public TextView mTopTruckTV;
    @BindView(R.id.loading_container)
    public RelativeLayout loadingContainer;
    @BindView(R.id.txt_bmap_top_name)
    public TextView txtName;
    @BindView(R.id.txt_bmap_top_speed)
    public TextView txtSpeed;
    @BindView(R.id.txt_bmap_top_time)
    public TextView txtTime;
    @BindView(R.id.play_btn)
    public ImageView mPlayBtn;
    @BindView(R.id.progress_bar)
    public SeekBar mProgressBar;
    @BindView(R.id.speed_bar)
    public SeekBar mSpeedBar;


    private static final String TAG = "GoogleTraceActivity";
    public static final String BUNDLE_PLATENUMBER = "mPlateNumber";
    public static final String BUNDLE_DATA_MILEAGE_DAILY = "mileageDaily";
    protected BaiduMap mMap;

    private BitmapDescriptor startBmp, endBmp, currentBmp;
    private BitmapDescriptor mGreenTexture = BitmapDescriptorFactory.fromAsset("Icon_road_green_arrow.png");


    private Polyline mPolyline;
    private Marker mMoveMarker;
    private Handler mHandler;
    private List<LatLng> polyLineList;
    public ArrayList<BaiduTrack> routePoints = new ArrayList<>();

    volatile boolean isMoving = true; //是否开始运动
    volatile boolean AnimationEnd = false; //动画是否播放结束
    private LatLng mLastLatLng = null; //保存移动到具体的某个点
    private double slope; //调整的坡
    private boolean isYReverse; //调整后的Y轴
    private boolean isXReverse;//调整后的X轴
    private double intercept;// 根据点和斜率算取截距
    private double xMoveDistance; //X轴移动的距离
    private double yMoveDistance; //Y轴移动的距离
    private LatLng lastStartPoint;//保存上一个起点
    private LinearLayout mInfoWindowLayout;//提示框
    private TextView mSpeed,mSpeedTV, mTimeTv; //文字信息
    private boolean isFirstStartThread = true;
    // 通过设置间隔时间和距离可以控制速度和图标移动的距离
    private int mNotChangeTime = 100;//默认1000毫秒
    volatile int mSleepTime = 100;
    volatile double mDistance = 0.00002;
    boolean state = true;//点击播放为true,点击暂停为false
    private LayoutInflater factory;//引入新的弹框样式
    private View layout;//初始化弹框样式


    @SuppressLint("baiDuHandler")
    private Handler myHandler = new Handler() {
        public void handleMessage(Message msg) {
            Bundle bundle = msg.getData();
            //类型为1的是实时监控marker的数据改变,类型为2是车辆运动到最后弹出警示和设置暂停按钮
            if (bundle.getString("type").equals("1")) {
                mSpeedTV.setText(bundle.getString("speed"));
                mTimeTv.setText(bundle.getString("time"));
                mMoveMarker.getInfoWindow().setBitmapDescriptor(BitmapDescriptorFactory.fromView(layout));
            } else if (bundle.getString("type").equals("2")) {
                showLimitTips();
                mPlayBtn.setBackground(getResources().getDrawable(R.drawable.map_icon_stop));
            }
            super.handleMessage(msg);
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_map_track);
        ButterKnife.bind(this);
        ButterKnife.bind(this);
        getPermission();
        initView();
        loadData();
    }

    /**
     * 方法必须重写
     */
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        bmapView.onSaveInstanceState(outState);
    }

    public void initView() {
        //mileageDailySubclass= (MileageDailySubclass) getIntent().getExtras().getSerializable(BUNDLE_DATA_MILEAGE_DAILY);
        // mTitleTV.setText(mileageDailySubclass.getPlateNumber());
        mTitleTV.setText("轨迹回放");
        mBackContainer.setVisibility(View.VISIBLE);
        polyLineList = new ArrayList<>();
        mTopTruckContainer.setVisibility(View.VISIBLE);
        googleView.setVisibility(View.GONE);
        bmapView.setVisibility(View.VISIBLE);
        mDataContainer.setVisibility(View.VISIBLE);
        loadingContainer.setVisibility(View.VISIBLE);
        mMap = bmapView.getMap();
        mMap.getUiSettings().setRotateGesturesEnabled(false);//不允许旋转地图
        mMap.getUiSettings().setZoomGesturesEnabled(true);
        mMap.getUiSettings().setCompassEnabled(true);
        mMap.setTrafficEnabled(false);
        mMap.setBuildingsEnabled(false);
        mMap.setIndoorEnable(false);
        mMap.getUiSettings().setAllGesturesEnabled(true);


        startBmp = BitmapDescriptorFactory.fromResource(R.drawable.icon_map_start_point);
        endBmp = BitmapDescriptorFactory.fromResource(R.drawable.destination);
        currentBmp = BitmapDescriptorFactory.fromResource(R.drawable.ic_truck);

        //初始化弹框样式
        factory=  LayoutInflater.from(BaiduTrackActivity.this) ;
        layout=factory.inflate(R.layout.map_bullet_box, null);
        mSpeedTV = (TextView) layout.findViewById(R.id.speed_tv);
        mTimeTv = (TextView) layout.findViewById(R.id.time_tv);

        //顶部样式隐藏与显示
        mTopTruckContainer.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mDataContainer.getVisibility() == View.GONE) {
                    mDataContainer.setVisibility(View.VISIBLE);
                    mTopTruckTV.setText("隐藏");
                } else {
                    mDataContainer.setVisibility(View.GONE);
                    mTopTruckTV.setText("显示");
                }

            }
        });
        //进度监听
        mProgressBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean b) {
                //Log.e("size",progress+"--");
                if (routePoints == null || routePoints.size() == 0) {
                    return;
                }
                if (progress == routePoints.size() - 1) {
                    //设置按钮
                    mPlayBtn.setBackgroundResource(R.drawable.map_icon_stop);
                    isMoving = false;
                    //设置终点marker
                    if (mMoveMarker != null) {
                        mMoveMarker.setIcon(BitmapDescriptorFactory.fromResource(R.drawable.ic_truck));
                    }
                }
                if (progress < routePoints.size() - 1)
                    ai.set(progress);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                LogUtils.i(TAG, "点击了进度条");
                isMoving = false;
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                LogUtils.i(TAG, "停止点击进度条");
                if (!state)
                    isMoving = true;
            }
        });

        //速度监听
        mSpeedBar.setMax(mNotChangeTime);
        mSpeedBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
                if (routePoints == null || routePoints.size() == 0) {
                    return;
                }
                if (mSleepTime > 0) {
                    mSleepTime = mNotChangeTime - i;
                    mDistance = i * 0.000005 + 0.00002;

                }
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                LogUtils.i(TAG, "点击了速度进度条");
                isMoving = false;
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                LogUtils.i(TAG, "停止点击速度进度条");
                if (!state)
                    isMoving = true;
            }
        });
        mHandler = new Handler(Looper.getMainLooper());

    }

   

    public void loadData() {
        /* HashMap<String, String> params = new HashMap<>();
       params.put("boxId", mileageDailySubclass.getBoxId());
        params.put("beginDate",TimeUtils.f_long_2_str(mileageDailySubclass.getStartTime().getTime()));
        params.put("endDate",TimeUtils.f_long_2_str(mileageDailySubclass.getEndTime().getTime()));
        params.put("mapType","1");
        LogUtils.i(TAG, "queryTrajectoryUrl=" + UrlConfig.getTrajectory() + " ,params=" + params);
          HttpProxy.getInstance().post(this, UrlConfig.getTrajectory(), params, new ICallback() {
            @Override
            public void onFailure(String e) {
                LogUtils.i(TAG,"MileageDailyDetail-err"+e);
            }

            @Override
            public void onResponse(String result) {
                LogUtils.i(TAG, "MileageDailyDetail-result=" + result);
                ArrayList<BaiduTrack> tracks = (ArrayList<BaiduTrack>) JsonUtils.MultipleJson(result, BaiduTrack.class);

                for(int j=0;j<tracks.size();j++){
                    polyLineList.add(new LatLng(tracks.get(j).getLatitude(),tracks.get(j).getLongitude()));
                }
                routePoints=tracks;

                drawPolyLine();
                TrackThread trackThread = new TrackThread(routePoints,mMoveMarker,mMap,mHandler,mPolyline);
                trackThread.start();
                loadingContainer.setVisibility(View.GONE);
            }
        });*/
        String result = getData();
        if (result != null) {
            routePoints = (ArrayList<BaiduTrack>) JsonUtils.MultipleJson(result, BaiduTrack.class);

            for (int j = 0; j < routePoints.size(); j++) {
                polyLineList.add(new LatLng(routePoints.get(j).getLatitude(), routePoints.get(j).getLongitude()));
            }
            drawPolyLine();
            loadingContainer.setVisibility(View.GONE);
        }

    }


    @OnClick({R.id.back_container, R.id.play_btn})
    @Override
    public void onClick(View v) {
        int id = v.getId();
        switch (id) {
            case R.id.back_container:
                finish();
                isMoving = false;
                break;
            case R.id.play_btn:
                if (ai.get() != routePoints.size() - 1) {
                    if (state) {
                        isMoving = true;
                        state = false;
                        mPlayBtn.setBackground(getResources().getDrawable(R.drawable.map_icon_broadcast));
                        if (isFirstStartThread) {
                            moveLooper();
                            isFirstStartThread = false;
                            if (null != polyLineList) {
                                MapStatus mapStatus = new MapStatus.Builder().target(polyLineList.get(0)).zoom(18).build();
                                mMap.animateMapStatus(MapStatusUpdateFactory.newMapStatus(mapStatus));
                            }
                        }
                    } else {
                        isMoving = false;
                        state = true;
                        mPlayBtn.setBackground(getResources().getDrawable(R.drawable.map_icon_stop));
                    }
                } else {
                    showLimitTips();
                }


        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        bmapView.onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        bmapView.onPause();
    }

    @Override  //再次进入该activity重新创建activity,从而到达数据刷新的效果
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);

    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mMap.clear();
        bmapView.onDestroy();

    }

    @Override
    protected void onStop() {
        super.onStop();
    }
    /**
     * 绘画轨迹线
     */
    private void drawPolyLine() {

        // 绘制纹理PolyLine
        PolylineOptions polylineOptions = new PolylineOptions().points(polyLineList).width(10).customTexture(mGreenTexture)
                .dottedLine(true);
        mPolyline = (Polyline) mMap.addOverlay(polylineOptions);


        final int count = polyLineList.size() - 1;
        // progressBar.setMax(count);
        mProgressBar.setMax(count);
        //第一次进入地图,将整条的路线在可见的屏幕上。
        LatLngBounds.Builder builder = new LatLngBounds.Builder();
        for (LatLng p : polyLineList) {
            builder.include(p);
        }
        MapStatusUpdate msUpdate = MapStatusUpdateFactory.newLatLngBounds(builder.build());
        mMap.animateMapStatus(msUpdate);

        // 添加小车marker
        OverlayOptions markerOptions = new MarkerOptions().flat(true).anchor(0.5f, 0.5f).icon(currentBmp).
                position(polyLineList.get(0)).rotate((float) getAngle(0));
        mMoveMarker = (Marker) mMap.addOverlay(markerOptions);

        //添加起点的定位icon
        OverlayOptions startOptions = new MarkerOptions().icon(startBmp).position(polyLineList.get(0));
        mMap.addOverlay(startOptions);
        //添加终点的定位icon
        OverlayOptions endOptions = new MarkerOptions().icon(endBmp).position(polyLineList.get(polyLineList.size() - 1));
        mMap.addOverlay(endOptions);

        InfoWindow.OnInfoWindowClickListener infoWindowClickListener = new InfoWindow.OnInfoWindowClickListener() {
            @Override
            public void onInfoWindowClick() {
                //  Toast.makeText(BaiduTrackActivity.this, "点击了InfoWindow", Toast.LENGTH_SHORT).show();
            }
        };
        mSpeedTV.setText(String.format("%.2f", routePoints.get(0).getSpeed()) + "km/h");
        mTimeTv.setText(TimeUtils.f_long_2_str(routePoints.get(0).getLoc_time() * 1000));

        // 添加 Marker 关联的InfoWindow,两者的更新是相互独立的。
        mMoveMarker.showInfoWindow(new InfoWindow(BitmapDescriptorFactory.fromView(layout), polyLineList.get(0), -47,
                infoWindowClickListener));

    }
    /**
     * 循环进行移动逻辑
     */

    AtomicInteger ai = new AtomicInteger(0);

    public void moveLooper() {
        new Thread() {
            public void run() {
                while (true) {
                    for (int i = 0; i < routePoints.size() - 2; ) {
                        if (isMoving) {
                            i = ai.get();
                            //获取两个点,判断车辆移动的方向
                            LatLng startPoint = new LatLng(routePoints.get(i).getLatitude(), routePoints.get(i).getLongitude());
                            LatLng endPoint = new LatLng(routePoints.get(i + 1).getLatitude(), routePoints.get(i + 1).getLongitude());

                            if (null != mLastLatLng && null != lastStartPoint) {
                                //判断一个点的起始点是否和上一个点的起始点是一样的。如果是一样的话就不进行角度的偏移。
                                if (startPoint.latitude == lastStartPoint.latitude && startPoint.longitude == lastStartPoint.longitude) {
                                    moveMarker(mLastLatLng, endPoint, false, routePoints.get(i));

                                } else {
                                    moveMarker(startPoint, endPoint, true, routePoints.get(i));
                                }

                            } else
                                moveMarker(startPoint, endPoint, true, routePoints.get(i));
                            //保存上运动点的起始经纬度
                            lastStartPoint = new LatLng(startPoint.latitude, startPoint.longitude);
                            ai.addAndGet(1);
                            if (i == routePoints.size() - 2) {
                                isMoving = false;
                                state = true;
                                Message message = new Message();
                                Bundle bundle = new Bundle();
                                bundle.putString("type", "2");
                                message.setData(bundle);
                                myHandler.sendMessage(message);
                                AnimationEnd = true;
                            }

                        }
                    }
                }
            }
        }.start();
    }

    /**
     * 小车的移动
     */
    public void moveMarker(LatLng startPoint, LatLng endPoint, boolean right, BaiduTrack baiduTracks) {

        if (isMoving) {
            if (right) {
                mMoveMarker.setPosition(startPoint);
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        // refresh marker's rotate
                        if (mMap == null) {
                            return;
                        }
                        //marker根据角度旋转车的角度
                        mMoveMarker.setRotate((float) getAngle(startPoint, endPoint));
                    }
                });
                slope = getSlope(startPoint, endPoint);

                // 是不是正向的标示
                isYReverse = (startPoint.latitude > endPoint.latitude);
                isXReverse = (startPoint.longitude > endPoint.longitude);
                intercept = getInterception(slope, startPoint);
                xMoveDistance = isXReverse ? getXMoveDistance(slope) : -1 * getXMoveDistance(slope);
                yMoveDistance = isYReverse ? getYMoveDistance(slope) : -1 * getYMoveDistance(slope);


                Message message = new Message();
                Bundle bundle = new Bundle();
                bundle.putString("type", "1");
                bundle.putString("speed", String.format("%.2f", baiduTracks.getSpeed()) + "km/h");
                bundle.putString("time", TimeUtils.f_long_2_str(baiduTracks.getLoc_time() * 1000));
                message.setData(bundle);
                myHandler.sendMessage(message);
                //设置进度条的位置
                mProgressBar.setProgress(ai.get());

            }

            //无限分割上传的两个点并且循环移动这两个点之间的所有点。
            for (double j = startPoint.latitude, k = startPoint.longitude;
                 !((j > endPoint.latitude) ^ isYReverse) && !((k > endPoint.longitude) ^ isXReverse); ) {

                if (!isMoving) {
                    //如果是没有移动状态的话,那么这两个点的起始点需要回滚到前一个点中,并且跳出该两点的循环。
                    ai.addAndGet(-1);
                    break;
                }

                LatLng latLng = null;
                if (slope == Double.MAX_VALUE) {
                    latLng = new LatLng(j, k);
                    j = j - yMoveDistance;
                } else if (slope == 0.0) {
                    latLng = new LatLng(j, k - xMoveDistance);
                    k = k - xMoveDistance;
                } else {
                    latLng = new LatLng(j, (j - intercept) / slope);
                    j = j - yMoveDistance;
                }

                final LatLng finalLatLng = latLng;
                mLastLatLng = latLng;
                if (finalLatLng.latitude == 0 && finalLatLng.longitude == 0) {
                    continue;
                }
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {

                        if (mMap == null) {
                            return;
                        }
                        mMoveMarker.setPosition(finalLatLng);

                        // 设置 Marker 覆盖物的位置坐标,并同步更新与Marker关联的InfoWindow的位置坐标.
                        mMoveMarker.setPositionWithInfoWindow(finalLatLng);

                        //设置marker的位置不移动出屏幕
                        if (finalLatLng != null) {
                            Point pt = mMap.getMapStatus().targetScreen;
                            Point point = mMap.getProjection().toScreenLocation(finalLatLng);
                            if (point.x < 0 || point.x > pt.x * 2 || point.y < 0 || point.y > pt.y * 2) {
                                mMap.animateMapStatus(MapStatusUpdateFactory.newLatLng(finalLatLng));
                            }
                        }


                    }
                });
                try {
                    Thread.sleep(mSleepTime);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 根据数字返回方向
     *
     * @param d
     * @return
     */
    private String directionType(int d) {
        if ((d >= 337 && d <= 360) || (d >= 0 && d <= 23)) {
            return "北向";
        } else if (d >= 23 && d <= 68) {
            return "东北向";
        } else if (d >= 68 && d <= 113) {
            return "东向";
        } else if (d >= 113 && d <= 158) {
            return "东南向";
        } else if (d >= 158 && d <= 203) {
            return "南向";
        } else if (d >= 203 && d <= 248) {
            return "西南向";
        } else if (d >= 248 && d <= 293) {
            return "西向";
        } else //if (d >= 293 && d <= 338) {
            return "西北向";
    }

    /**
     * 计算x方向每次移动的距离
     */
    private double getXMoveDistance(double slope) {
        if (slope == Double.MAX_VALUE || slope == 0.0) {
            return mDistance;
        }
        return Math.abs((mDistance * 1 / slope) / Math.sqrt(1 + 1 / (slope * slope)));
    }

    /**
     * 计算y方向每次移动的距离
     */
    private double getYMoveDistance(double slope) {
        if (slope == Double.MAX_VALUE || slope == 0.0) {
            return mDistance;
        }
        return Math.abs((mDistance * slope) / Math.sqrt(1 + slope * slope));
    }

    /**
     * 算斜率
     */
    private double getSlope(LatLng fromPoint, LatLng toPoint) {
        if (toPoint.longitude == fromPoint.longitude) {
            return Double.MAX_VALUE;
        }
        double slope = ((toPoint.latitude - fromPoint.latitude) / (toPoint.longitude - fromPoint.longitude));
        return slope;
    }

    /**
     * 根据点和斜率算取截距
     */
    private double getInterception(double slope, LatLng point) {
        double interception = point.latitude - slope * point.longitude;
        return interception;
    }

    /**
     * 根据点获取图标转的角度
     */
    private double getAngle(int startIndex) {
        if ((startIndex + 1) >= mPolyline.getPoints().size()) {
            throw new RuntimeException("index out of bonds");
        }
        LatLng startPoint = mPolyline.getPoints().get(startIndex);
        LatLng endPoint = mPolyline.getPoints().get(startIndex + 1);
        return getAngle(startPoint, endPoint);
    }

    /**
     * 根据两点算取图标转的角度
     */
    private double getAngle(LatLng fromPoint, LatLng toPoint) {
        double slope = getSlope(fromPoint, toPoint);
        if (slope == Double.MAX_VALUE) {
            if (toPoint.latitude > fromPoint.latitude) {
                return 0;
            } else {
                return 180;
            }
        } else if (slope == 0.0) {
            if (toPoint.longitude > fromPoint.longitude) {
                return -90;
            } else {
                return 90;
            }
        }
        float deltAngle = 0;
        if ((toPoint.latitude - fromPoint.latitude) * slope < 0) {
            deltAngle = 180;
        }
        double radio = Math.atan(slope);
        double angle = 180 * (radio / Math.PI) + deltAngle - 90;
        return angle;
    }

    private void showLimitTips() {
        ToastUtils.getInstance().shortShow(this, getString(R.string.track_playback_end));
    }
    private String getData() {
        StringBuilder newstringBuilder = new StringBuilder();
        InputStream inputStream = null;
        try {
            inputStream = getResources().getAssets().open("baiduTrack.json");
            InputStreamReader isr = new InputStreamReader(inputStream);
            BufferedReader reader = new BufferedReader(isr);
            String jsonLine;
            while ((jsonLine = reader.readLine()) != null) {
                newstringBuilder.append(jsonLine);
            }
            reader.close();
            isr.close();
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        String result = newstringBuilder.toString();
        Log.d("json", result);
        return result;
    }
}

xml文件 activity_map_track.xml文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/linearLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <!--标题-->
        <include
            android:id="@+id/title_container"
            layout="@layout/top_titile_view" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:layout_below="@+id/data_container"
            android:background="#80000000"
            android:visibility="gone">
            <TextView
                android:id="@+id/txt_bmap_top_name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textColor="@android:color/white"/>
            <TextView
                android:id="@+id/txt_bmap_top_speed"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textColor="@android:color/white"/>
            <TextView
                android:id="@+id/txt_bmap_top_time"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textColor="@android:color/white"/>
        </LinearLayout>

        <!--百度地图-->
        <com.baidu.mapapi.map.MapView
            android:id="@+id/bmapView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_above="@+id/bottom_layout"
            android:layout_below="@+id/data_container"
            android:visibility="gone"
            />

        <!--谷歌地图-->
        <!--底部按钮控制开始动画-->
        <com.google.android.gms.maps.MapView
            android:id="@+id/map"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_above="@+id/bottom_layout"
            android:layout_below="@+id/data_container" />



        <!--进度控制-->
        <RelativeLayout
            android:id="@+id/bottom_layout"
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:layout_alignParentBottom="true"
            android:background="@color/white"
            >

            <ImageView
                android:id="@+id/play_btn"
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:layout_centerVertical="true"
                android:layout_marginLeft="15dp"
                android:background="@drawable/map_icon_stop"
                android:scaleType="fitXY" />

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_centerVertical="true"
                android:layout_marginLeft="15dp"
                android:layout_marginRight="15dp"
                android:layout_toRightOf="@+id/play_btn"
                android:gravity="center_vertical"
                android:orientation="vertical">

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="horizontal">

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="进度"
                        android:textColor="#333333"
                        android:textSize="14sp" />

                    <SeekBar
                        android:id="@+id/progress_bar"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:maxHeight="3dp"
                        android:minHeight="3dp"
                        android:paddingLeft="10dp"
                        android:paddingRight="10dp"
                        android:progressDrawable="@drawable/map_bg_adjust_seek_bar"
                        android:thumb="@drawable/map_icon_destination" />
                </LinearLayout>

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="15dp"
                    android:orientation="horizontal">

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="速度"
                        android:textColor="#333333"
                        android:textSize="14sp" />

                    <SeekBar
                        android:id="@+id/speed_bar"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:maxHeight="3dp"
                        android:minHeight="3dp"
                        android:paddingLeft="10dp"
                        android:paddingRight="10dp"
                        android:progressDrawable="@drawable/map_bg_adjust_seek_bar"
                        android:thumb="@drawable/map_icon_destination" />
                </LinearLayout>

            </LinearLayout>

        </RelativeLayout>

        <!--加载动画-->
        <RelativeLayout
            android:id="@+id/loading_container"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@+id/data_container"
            android:visibility="gone"
            >
            <FrameLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:alpha="0.8"
                android:background="@color/white">

            </FrameLayout>
            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/loading_icon"
                android:layout_centerVertical="true"
                android:layout_centerHorizontal="true"
                />
            <ProgressBar
                android:id="@+id/progress_bar_tv"
                android:layout_width="65dp"
                android:layout_height="65dp"
                android:layout_centerVertical="true"
                android:indeterminateBehavior="repeat"
                android:indeterminateDrawable="@drawable/loading_circle"
                android:indeterminateOnly="true"
                android:visibility="visible"
                android:layout_centerHorizontal="true"
                />

            <!--<TextView
                android:id="@+id/text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="8dp"
                android:layout_centerInParent="true"
                android:layout_below="@+id/progress_bar_tv"
                android:text="@string/breaking_and_wait"
                android:textColor="@color/loading_color"
                android:textSize="@dimen/font_size_15" />-->
        </RelativeLayout>
    </RelativeLayout>

    <LinearLayout
        android:layout_width="120dp"
        android:layout_height="match_parent"
        android:layout_gravity="end"
        android:layout_marginTop="60dp"
        android:background="@color/white"
        android:orientation="vertical">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="48dp"
            android:gravity="center"
            android:text="@string/choose_vehicle"
            android:textColor="@color/black"
            android:textSize="@dimen/font_size_15" />

        <View
            android:layout_width="match_parent"
            android:layout_height="10px"
            android:background="@color/list_view_divider" />

        <ListView
            android:id="@+id/listview"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:cacheColorHint="#00000000"
            android:divider="@color/list_view_divider"
            android:dividerHeight="5dp"
            android:fadingEdge="vertical"
            android:fastScrollEnabled="false"
            android:footerDividersEnabled="false"
            android:headerDividersEnabled="false"
            android:smoothScrollbar="true" />
    </LinearLayout>



</LinearLayout>


json格式的文件(就是activity中提到的baiduTrack.json文件)

{"code":"","msg":"","data":["{\"status\":0,\"message\":\"成功\",\"total\":183,\"distance\":41420.454952368,\"toll_distance\":21768.874985325,\"low_speed_distance\":0,\"points\":[{\"loc_time\":1583399038,\"latitude\":23.162981209863,\"longitude\":113.5183105882,\"speed\":1.9704359414511,\"direction\":145.03425049045},{\"loc_time\":1583399135,\"latitude\":23.162324822703,\"longitude\":113.51879195379,\"speed\":17.965209268279,\"direction\":185.4958739896},{\"loc_time\":1583399135,\"latitude\":23.162170679943,\"longitude\":113.51877582246,\"speed\":17.965209268279,\"direction\":222.37891592352},{\"loc_time\":1583399169,\"latitude\":23.1617163099,\"longitude\":113.51791965633,\"speed\":2.7302969550567,\"direction\":295.10304896885},{\"loc_time\":1583399304,\"latitude\":23.162867515118,\"longitude\":113.51704924914,\"speed\":34.332919517071,\"direction\":356.81922729711},{\"loc_time\":1583399304,\"latitude\":23.163032010594,\"longitude\":113.51710432024,\"speed\":34.332919517071,\"direction\":54.249047444041},{\"loc_time\":1583399304,\"latitude\":23.16340163623,\"longitude\":113.51766276092,\"speed\":34.332919517071,\"direction\":322.15069841506},{\"loc_time\":1583399304,\"latitude\":23.1636926859,\"longitude\":113.51741246778,\"speed\":34.332919517071,\"direction\":54.776286069662},{\"loc_time\":1583399304,\"latitude\":23.166000658471,\"longitude\":113.52097400499,\"speed\":34.332919517071,\"direction\":68.039713189313},{\"loc_time\":1583399304,\"latitude\":23.166661052635,\"longitude\":113.52267619335,\"speed\":34.332919517071,\"direction\":91.207580714705},{\"loc_time\":1583399304,\"latitude\":23.166655039988,\"longitude\":113.52297098462,\"speed\":34.332919517071,\"direction\":74.889498426869},{\"loc_time\":1583399397,\"latitude\":23.167113616486,\"longitude\":113.52489553571,\"speed\":32.097889575864,\"direction\":71.829125023764},{\"loc_time\":1583399420,\"latitude\":23.167661822772,\"longitude\":113.52660487272,\"speed\":21.344933773378,\"direction\":135.0589707347},{\"loc_time\":1583399449,\"latitude\":23.16548946239,\"longitude\":113.52893624947,\"speed\":37.847819822382,\"direction\":124.87140712623},{\"loc_time\":1583399449,\"latitude\":23.165153976858,\"longitude\":113.52948419739,\"speed\":37.847819822382,\"direction\":137.30195481465},{\"loc_time\":1583399449,\"latitude\":23.163801445183,\"longitude\":113.53073069295,\"speed\":37.847819822382,\"direction\":146.23050869127},{\"loc_time\":1583399449,\"latitude\":23.16228116034,\"longitude\":113.53163497605,\"speed\":37.847819822382,\"direction\":159.06793377491},{\"loc_time\":1583399449,\"latitude\":23.160993293862,\"longitude\":113.5321522328,\"speed\":37.847819822382,\"direction\":163.88213698104},{\"loc_time\":1583399449,\"latitude\":23.160120875115,\"longitude\":113.53238363609,\"speed\":37.847819822382,\"direction\":170.15279090211},{\"loc_time\":1583399449,\"latitude\":23.157268664264,\"longitude\":113.53285049657,\"speed\":37.847819822382,\"direction\":174.5297098459},{\"loc_time\":1583399449,\"latitude\":23.156201744204,\"longitude\":113.53280248365,\"speed\":37.847819822382,\"direction\":192.16149216075},{\"loc_time\":1583399449,\"latitude\":23.15555077287,\"longitude\":113.53260268045,\"speed\":37.847819822382,\"direction\":204.3163658703},{\"loc_time\":1583399449,\"latitude\":23.153833328637,\"longitude\":113.53167724688,\"speed\":37.847819822382,\"direction\":209.27214190257},{\"loc_time\":1583399449,\"latitude\":23.153328880903,\"longitude\":113.53132750687,\"speed\":37.847819822382,\"direction\":218.87579258447},{\"loc_time\":1583399449,\"latitude\":23.152357452816,\"longitude\":113.5304209881,\"speed\":37.847819822382,\"direction\":204.99670303117},{\"loc_time\":1583399449,\"latitude\":23.151859239325,\"longitude\":113.53018043694,\"speed\":37.847819822382,\"direction\":195.93493922138},{\"loc_time\":1583399449,\"latitude\":23.151305500481,\"longitude\":113.53007996114,\"speed\":37.847819822382,\"direction\":179.54975783186},{\"loc_time\":1583399449,\"latitude\":23.15048122781,\"longitude\":113.53012441097,\"speed\":37.847819822382,\"direction\":173.10272815816},{\"loc_time\":1583399449,\"latitude\":23.149151141542,\"longitude\":113.53037871505,\"speed\":37.847819822382,\"direction\":150.49499844661},{\"loc_time\":1583399449,\"latitude\":23.148626742375,\"longitude\":113.53072666039,\"speed\":37.847819822382,\"direction\":131.91670589797},{\"loc_time\":1583399449,\"latitude\":23.148404609413,\"longitude\":113.53099575145,\"speed\":37.847819822382,\"direction\":118.73487151249},{\"loc_time\":1583399449,\"latitude\":23.148183933337,\"longitude\":113.53158516133,\"speed\":37.847819822382,\"direction\":94.470359767506},{\"loc_time\":1583399653,\"latitude\":23.14826716477,\"longitude\":113.53424443876,\"speed\":12.021108698947,\"direction\":92.495390802844},{\"loc_time\":1583399653,\"latitude\":23.148238342474,\"longitude\":113.5346329981,\"speed\":12.021108698947,\"direction\":103.22457320961},{\"loc_time\":1583399681,\"latitude\":23.148073084388,\"longitude\":113.53518676677,\"speed\":14.8802858657,\"direction\":95.52115012411},{\"loc_time\":1583399681,\"latitude\":23.148138326596,\"longitude\":113.53553137105,\"speed\":14.8802858657,\"direction\":32.057014194984},{\"loc_time\":1583399681,\"latitude\":23.148244847107,\"longitude\":113.53559153523,\"speed\":14.8802858657,\"direction\":336.84985530828},{\"loc_time\":1583399681,\"latitude\":23.149233096039,\"longitude\":113.53520450818,\"speed\":14.8802858657,\"direction\":346.34324804698},{\"loc_time\":1583399750,\"latitude\":23.150704939569,\"longitude\":113.53483306171,\"speed\":66.432999082979,\"direction\":280.08973641095},{\"loc_time\":1583400030,\"latitude\":23.158843612527,\"longitude\":113.48508972352,\"speed\":79.146881275283,\"direction\":290.74518949722},{\"loc_time\":1583400040,\"latitude\":23.159600453448,\"longitude\":113.48272874135,\"speed\":88.987410059891,\"direction\":287.86178323893},{\"loc_time\":1583400040,\"latitude\":23.160300867479,\"longitude\":113.48020593536,\"speed\":88.987410059891,\"direction\":285.35445006762},{\"loc_time\":1583400059,\"latitude\":23.160928788632,\"longitude\":113.4774785491,\"speed\":91.856984275663,\"direction\":282.36719785897},{\"loc_time\":1583400059,\"latitude\":23.161387677458,\"longitude\":113.47503435825,\"speed\":91.856984275663,\"direction\":279.76342983325},{\"loc_time\":1583400152,\"latitude\":23.164040851946,\"longitude\":113.45814013803,\"speed\":104.21870176093,\"direction\":278.07769433886},{\"loc_time\":1583400162,\"latitude\":23.164420039071,\"longitude\":113.45487855572,\"speed\":125.51493184798,\"direction\":275.7431200208},{\"loc_time\":1583400162,\"latitude\":23.164671462773,\"longitude\":113.45176055685,\"speed\":125.51493184798,\"direction\":273.75227149299},{\"loc_time\":1583400162,\"latitude\":23.164809968038,\"longitude\":113.44873439398,\"speed\":125.51493184798,\"direction\":271.69742251431},{\"loc_time\":1583400214,\"latitude\":23.165109701668,\"longitude\":113.43746359905,\"speed\":105.35890972817,\"direction\":269.45133703821},{\"loc_time\":1583400229,\"latitude\":23.164985134107,\"longitude\":113.43370883144,\"speed\":82.818277121804,\"direction\":265.7464824944},{\"loc_time\":1583400243,\"latitude\":23.164692446988,\"longitude\":113.43044196124,\"speed\":78.703515857804,\"direction\":262.44660333588},{\"loc_time\":1583400258,\"latitude\":23.164034205797,\"longitude\":113.42610194307,\"speed\":75.318254237498,\"direction\":258.03585220452},{\"loc_time\":1583400281,\"latitude\":23.163051682242,\"longitude\":113.4217824915,\"speed\":53.884835459714,\"direction\":253.54928258048},{\"loc_time\":1583400299,\"latitude\":23.162087767777,\"longitude\":113.41849866507,\"speed\":55.089942044814,\"direction\":251.27760662131},{\"loc_time\":1583400355,\"latitude\":23.159311711903,\"longitude\":113.40972253005,\"speed\":57.819775495139,\"direction\":252.55277446174},{\"loc_time\":1583400355,\"latitude\":23.159109911165,\"longitude\":113.40888387809,\"speed\":57.819775495139,\"direction\":260.6004225747},{\"loc_time\":1583400417,\"latitude\":23.158503903957,\"longitude\":113.40185571517,\"speed\":49.732489453861,\"direction\":261.82826528758},{\"loc_time\":1583400417,\"latitude\":23.158361521034,\"longitude\":113.40132806477,\"speed\":49.732489453861,\"direction\":266.29694695985},{\"loc_time\":1583400485,\"latitude\":23.157406530732,\"longitude\":113.39072603522,\"speed\":52.181063729218,\"direction\":265.11553291043},{\"loc_time\":1583400504,\"latitude\":23.157342783724,\"longitude\":113.38926902472,\"speed\":55.732593494325,\"direction\":279.23971566515},{\"loc_time\":1583400514,\"latitude\":23.157419312627,\"longitude\":113.38873963024,\"speed\":29.729251239863,\"direction\":279.61171779071},{\"loc_time\":1583400525,\"latitude\":23.157842682026,\"longitude\":113.38712988468,\"speed\":108.91337776256,\"direction\":293.99298538097},{\"loc_time\":1583400525,\"latitude\":23.158154239149,\"longitude\":113.38644432948,\"speed\":108.91337776256,\"direction\":300.44950791765},{\"loc_time\":1583400525,\"latitude\":23.158630095325,\"longitude\":113.38566328733,\"speed\":108.91337776256,\"direction\":308.24517593253},{\"loc_time\":1583400538,\"latitude\":23.159713759394,\"longitude\":113.38432674561,\"speed\":76.631764311082,\"direction\":315.51562461077},{\"loc_time\":1583400538,\"latitude\":23.166315392386,\"longitude\":113.37674243507,\"speed\":76.631764311082,\"direction\":309.86987360779},{\"loc_time\":1583400592,\"latitude\":23.167153085438,\"longitude\":113.37554070537,\"speed\":27.088470326807,\"direction\":302.73090259713},{\"loc_time\":1583400616,\"latitude\":23.167842800289,\"longitude\":113.37422522244,\"speed\":119.63317853209,\"direction\":294.83141638579},{\"loc_time\":1583400616,\"latitude\":23.168458362595,\"longitude\":113.37266251139,\"speed\":119.63317853209,\"direction\":290.99729627629},{\"loc_time\":1583400629,\"latitude\":23.169078389788,\"longitude\":113.37080773393,\"speed\":72.400981825585,\"direction\":287.020435896},{\"loc_time\":1583400629,\"latitude\":23.169530645641,\"longitude\":113.36891073007,\"speed\":72.400981825585,\"direction\":281.25429324893},{\"loc_time\":1583400645,\"latitude\":23.16979285321,\"longitude\":113.36731030286,\"speed\":75.142197517085,\"direction\":276.34698529325},{\"loc_time\":1583400650,\"latitude\":23.169965578358,\"longitude\":113.36479334554,\"speed\":73.734854164121,\"direction\":275.97906319817},{\"loc_time\":1583400664,\"latitude\":23.170226624336,\"longitude\":113.36234259273,\"speed\":91.625445480706,\"direction\":281.66331755165},{\"loc_time\":1583400673,\"latitude\":23.170708525823,\"longitude\":113.3602364546,\"speed\":74.213469151744,\"direction\":292.10132361966},{\"loc_time\":1583400684,\"latitude\":23.171614523911,\"longitude\":113.3581181116,\"speed\":77.340782613906,\"direction\":298.26735857332},{\"loc_time\":1583400738,\"latitude\":23.175918293412,\"longitude\":113.34923086251,\"speed\":80.443267506063,\"direction\":291.50899639234},{\"loc_time\":1583400738,\"latitude\":23.17620053008,\"longitude\":113.34834748405,\"speed\":80.443267506063,\"direction\":284.42643537991},{\"loc_time\":1583400747,\"latitude\":23.176361505182,\"longitude\":113.34750584165,\"speed\":61.641324870852,\"direction\":277.373231788},{\"loc_time\":1583400756,\"latitude\":23.176426121824,\"longitude\":113.34664697953,\"speed\":63.675332851144,\"direction\":269.6935725742}"],"success":true}

补充一下json格式的解析方式

public static ArrayList<?> MultipleJson(String json, Class T) {

        try {
            if (TextUtils.isEmpty(json))
                return null;
            Gson gson = new Gson();
            Map map = gson.fromJson(json,Map.class);

            ArrayList<BaiduTrack> xylist = new ArrayList<>();
            JsonParser parser = new JsonParser();
            JsonArray Jarray = parser.parse(map.get("data").toString()).getAsJsonArray();
            for(int i = 0;i < Jarray.size(); i++){
                JsonArray jsonArray = Jarray.get(i).getAsJsonObject().get("points").getAsJsonArray();
               // JsonArray jsonArray = parser.parse(point.get("points").toString()).getAsJsonArray();
                xylist.addAll(gson.fromJson(jsonArray.toString(), new TypeToken<ArrayList<BaiduTrack>>() {}.getType()));
            }
            LogUtils.i(TAG,"经纬度的长度"+xylist.size());
            return xylist;

        } catch (Exception e) {
            LogUtils.e(TAG, "dealwithJson-error=" + e.toString());
        }
        return null;
    }

map_bullet_box.xml文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:background="@drawable/map_infowindow_bg">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_marginTop="8dp"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="@color/font_color"
            android:text="@string/speed_per_hour"
            android:textSize="@dimen/font_size_13"/>
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="@color/font_color"
            android:text="@string/colon"
            android:textSize="@dimen/font_size_13"/>
        <TextView
            android:id="@+id/speed_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="@color/app_title"
            android:textSize="@dimen/font_size_13" />

    </LinearLayout>
    <TextView
        android:id="@+id/time_tv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textColor="@color/font_color"
        android:textSize="@dimen/font_size_13"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp"
        android:text="2020-03-07 18:06:53"/>

</LinearLayout>

BackTrack类

package com.boxin.truck.model;

import java.util.List;

/**
 * @author lsx
 * @time 2020/4/20  17:06
 */
public class BaiduTrack extends BaseModel{

    private double longitude;//经度
    private double latitude;//纬度
    private double speed;//速度
    private long loc_time;//定位时的设备时间
    private double direction;//方向



    public double getLongitude() {
        return longitude;
    }

    public void setLongitude(double longitude) {
        this.longitude = longitude;
    }

    public double getLatitude() {
        return latitude;
    }

    public void setLatitude(double latitude) {
        this.latitude = latitude;
    }

    public double getSpeed() {
        return speed;
    }

    public void setSpeed(double speed) {
        this.speed = speed;
    }

    public long getLoc_time() {
        return loc_time;
    }

    public void setLoc_time(long loc_time) {
        this.loc_time = loc_time;
    }

    public double getDirection() {
        return direction;
    }

    public void setDirection(double direction) {
        this.direction = direction;
    }

}


 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值