地图轨迹跟踪系统设计与实现(Android+Eclipse+APP)

news2024/11/28 9:47:23

目 录
1 在线地图轨迹APP概述 1
1.1 本论文的背景及意义 1
1.2 本论文的主要方法和研究进展 1
1.3 本论文的主要内容 1
1.4 本论文的结构安排 1
2 系统分析 3
2.1 研究目标 3
2.2 可行性分析 3
2.2.1 经济可行性 3
2.2.2 技术的可行性 3
2.3 需求分析 3
2.4 性能分析 4
3 系统开发环境及相关技术介绍 5
3.1 开发环境搭建 5
3.1.1 安装JDK 5
3.1.2 安装Eclipse集成开发环境 5
3.1.3 下载安装Android SDK 5
3.1.4 为Eclipse安装ADT插件 6
3.1.5 创建AVD模拟器 6
3.2 相关技术 6
3.2.1百度地图 6
3.2.2 Sqlite 7
3.2.3 Android 12
3.2.4 GPS技术 12
4 系统介绍 13
4.1 APP介绍 13
5 程序设计与实现 14
5.1 UI设计 14
5.2 数据库设计 15
5.2.1 数据库设计规范 15
5.2.2 SQLite 数据库介绍 15
5.2.3 数据库详解 16
5.3 程序模块设计 16
5.3.1 登录注册 16
5.3.2 首页模块 20
5.3.3 轨迹模块 21
5.3.4 我的模块 29
5.3.5 查看历史记录模块 30
6 系 统 展示 38
6.1 进入系统 38
6.2 注册登录 38
6.3 进入系统 39
6.4 轨迹跟踪服务 40
6.5 历史轨迹查询 41
结 论 44
参考文献 45
致 谢 46
附录一 外文文献(原文) 47
附录二 外文文献(译文) 57
1.3 本论文的主要内容
主要内容为记录轨迹App开发的整个周期过程,其中包括对前期用户数据统计分析,对系统进行详细的分析,包括功能可行性,实现可行性等。介绍系统开发的环境以及相关的技术;系统的设计,包括UI设计,数据库设计程序模块设计;程序开发的过程以及系统测试。
1.4 本论文的结构安排
本论文第一部分是封面,里面包括本人的个人信息。第二部分是摘要,有中文版和英文。第三部分是目录。第四部分则是根据目录一一对应的内容。第五部分是总结。第六部分是参考文献与致谢。

2 系统分析
2.1 研究目标
这个系统的目标是做出一个记录人们走动轨迹的基于Android系统的平台,方便人们知道的自己的日常走动情况。记录每次的走动的轨迹。开发一个界面简单清晰,UI友好易懂,而且无赘余功能的运动平台。
2.2 可行性分析
采用开源的免费的手机安卓系统,并且利用的也是免费的百度地图API技术来实现课题。
2.2.1经济可行性
一个免费平台的软件开发时间和成本都不是太高,而且是面向个人,不会产生企业级应用的成本预算,在开发的过程中,考虑到课题的特性,需要拥有一台可以使用GPS定位,并且是安卓系统的智能手机,本人已拥有一台可用的安卓手机,其它方面,测试,编码,并不会产生太多硬设备的费用。
2.2.2 技术的可行性
本系统主要用到了目前比较流行的手机系统安卓,以及 百度地图 API技术,由于以前Android开发的经验比较少,相关知识掌握也不是特别多,所以需要付出一些努力去深入学习Android,不过在掌握了JAVA的基本开发的基础上,学习Android的过程中并没有遇到很大的难题,因为Google提供了在eclipse上面的ADK,一步一步的完善课题,并且参照到了百度地图API提供的详细的开发说明书,不懂一点问一点,慢慢完善课题也变得简单起来,在理论上是可行的。
2.3 需求分析
问题描述:
设计一款可以应用于在线地图轨迹重现的安卓APP,在硬件上需要一台安卓系统的可以应用GPS定位的手持设备。
程序运行的时候,要求能够实时的记录运动中的GPS经纬点数据,创建数据表,并存储,然后通过调用程序中保存好的轨迹数据,通过点与点相连,连接成一条轨迹,实现轨迹的实时记录。
为了提高程序的可用性、人性化,在UI设计方面需要做的更好一些,要比类似的市场中的GPS记录程序更加的吸引用户,还需要提高软件的交互性,来留住用户。
2.4 性能分析
程序安全性高、响应速度快、信息处理速度快。没有出现卡顿或导致死机现象。数据存储安全,由于数据流并不是很大,所以读取快,因此程序性能比较高。
3 系统开发环境及相关技术介绍
3.1 开发环境搭建
在windows上搭建安卓开发环境是所有Android应用程序开发的第一步,Android开发工具包括:JDK(JAVA development kit)、Eclipse IDE(Eclipse Integrated Development)、Android SDK(Android software development kit)和ADT(Android Development Tools)。
3.1.1 安装JDK
JDK是Java语言的软件开发工具包,主要用于移动设备、嵌入式设备上的java应用程序。
进入Oracle官方网站JDK下载页面,选择电脑系统对应版本的JAVA SE(JDK)8进行下载,下载完成后运行.exe文件按提示进行安装。最后进行环境变量配置(以本人环境配置为例):
JAVA_HOME值为:E:\Java\jdk1.8.0_40
CLASSPATH值为:.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar,Path值:在开始追加 %JAVA_HOME%\bin;
安装成功后可在CMD窗口查看到对话框。

package com.my.map;


import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Timer;


import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClientOption;
import com.baidu.location.Poi;
import com.baidu.mapapi.SDKInitializer;
import com.baidu.mapapi.map.BaiduMap;
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.utils.DistanceUtil;
import com.baidu.trace.LBSTraceClient;
import com.baidu.trace.OnEntityListener;
import com.baidu.trace.OnStartTraceListener;
import com.baidu.trace.OnStopTraceListener;
import com.baidu.trace.Trace;
import com.baidu.trace.TraceLocation;
import com.my.map.config.MsgConfig;
import com.my.map.service.MapService;
import com.my.map.ui.BaseActivity;
import com.my.map.ui.RecordActivity;
import com.my.map.utils.DateUtils;
import com.my.map.utils.LocationEntry;
import com.my.map.utils.Utils;

public class MainActivity extends BaseActivity implements View.OnClickListener {
	private final static String TAG = "MainActivity";
	
	private ViewPager mViewPager;
	private final int tabCount = 3;/** Tab数 */
	private TextView[] tabTextView = new TextView[tabCount];/** TextView数组存储 */
	private String[] tabText = new String[tabCount];/** 底部Tab文字 */
	private List<View> mViews; // ViewPager包含的View
	private View view_home;
	private View view_run;
	private View view_mine;
	private LayoutInflater mInflater; 
	private TextView tv_tab_mine;
	private TextView tv_tab_run;
	private TextView tv_tab_home;
	private int showTabIndex = 0;/**要显示的Tab*/
	private int currentTabIndex = 0;/** 当前选择Tab索引 */
	private TextView rightTitle;
    private PagerAdapter mViewPagerAdapter;//mViewPager的适配器 
    
    private BDLocation tempLocation;//最新位置缓存
    
	private Handler locHander = new Handler() {// 接收定位结果消息,并显示在地图上
		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);
			switch(msg.what){
			case MsgConfig.MSG_MODE_MAP:
				try {
					Log.i(TAG,"开启定位");
					BDLocation location = msg.getData().getParcelable("loc");
					int iscal = msg.getData().getInt("iscalculate");
					if (location != null) {
						LatLng point = new LatLng(location.getLatitude(), location.getLongitude());
						// 构建Marker图标
						BitmapDescriptor bitmap = null;
						if (iscal == 0) {
							bitmap = BitmapDescriptorFactory.fromResource(R.drawable.icon_openmap_mark); // 非推算结果
						} else {
							bitmap = BitmapDescriptorFactory.fromResource(R.drawable.icon_openmap_focuse_mark); // 推算结果
						}
						// 构建MarkerOption,用于在地图上添加Marker
						OverlayOptions option = new MarkerOptions().position(point).icon(bitmap);
						mBaiduMap.addOverlay(option);// 在地图上添加Marker,并显示
						mBaiduMap.setMapStatus(MapStatusUpdateFactory.newLatLng(point));
					}
					else{
						Log.i(TAG,"location为空");
					}
				} catch (Exception e) {
				}
				break;
            case RUN_STOP:
            	bt_start.setText("开启轨迹服务");
            	break;
            case MsgConfig.SHOW_INFO:
            	String text = (String) msg.getData().get("content");
            	Toast.makeText(MainActivity.this, text, Toast.LENGTH_LONG).show();
            	break;
            default:
                super.handleMessage(msg);
			}
		}
	};
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		SDKInitializer.initialize(getApplicationContext());  
		setContentView(R.layout.activity_main);
		mInflater = LayoutInflater.from(this); 
		initView();
		initMapView();
		initRunView();
		initMineView();
	}
	@Override
	protected void onStart() {
		super.onStart();
		resetTab(showTabIndex);//开始时显示首页
		//setActionBar(showTabIndex);//初始化ActionBar
	}
	private void initView() {
		mViewPager = (ViewPager) findViewById(R.id.id_ViewPager);
		tabText[0] = getResources().getString(R.string.home);
		tabText[1] = getResources().getString(R.string.run);
		tabText[2] = getResources().getString(R.string.mine);
		tv_tab_home = (TextView) findViewById(R.id.tab_home_btn);
		tv_tab_home.setClickable(true);
		tv_tab_home.setOnClickListener(this);
		tv_tab_mine = (TextView) findViewById(R.id.tab_mine_btn);
		tv_tab_mine.setClickable(true);
		tv_tab_mine.setOnClickListener(this);
		tv_tab_run = (TextView) findViewById(R.id.tab_run_btn);
		tv_tab_run.setClickable(true);
		tv_tab_run.setOnClickListener(this);
		//便于设置选择状态
		tabTextView[0] = tv_tab_home;
		tabTextView[1] = tv_tab_run;
		tabTextView[2] = tv_tab_mine;
		mViews = new ArrayList<View>();  
	    view_home = mInflater.inflate(R.layout.tab_map, null);  
        view_run = mInflater.inflate(R.layout.tab_run, null);  
        view_mine = mInflater.inflate(R.layout.tab_mine, null);  
        mViews.add(view_home);  
        mViews.add(view_run);  
        mViews.add(view_mine);  
		mViewPagerAdapter = new PagerAdapter()  {  
            @Override  
            public void destroyItem(ViewGroup container, int position, Object object){  
                container.removeView(mViews.get(position));  
            }  
            @Override  
            public Object instantiateItem(ViewGroup container, int position){  
                View view = mViews.get(position);  
                container.addView(view);  
                return view;  
            }  
            @Override  
            public boolean isViewFromObject(View arg0, Object arg1){  
                return arg0 == arg1;  
            }  
            @Override  
            public int getCount(){  
                return mViews.size();  
            }  
        }; 
        mViewPager.setAdapter(mViewPagerAdapter);
        mViewPager.setOnPageChangeListener(new OnPageChangeListener(){ 
            @Override  
            public void onPageSelected(int position){  
            	resetTab(position);
            	//setActionBar(position);
            }  
            @Override  
            public void onPageScrolled(int arg0, float arg1, int arg2){  
            }  
            @Override  
            public void onPageScrollStateChanged(int arg0){  
            }  
        });  
	}
	@Override
	public void onClick(View v) {
		int selectTabIndex = -1;
		switch(v.getId()) {
		case R.id.tab_home_btn://点击底部Tab地图
			selectTabIndex = 0;
			break;
		case R.id.tab_run_btn://点击底部Tab轨迹
			selectTabIndex = 1;
			break;
		case R.id.tab_mine_btn://点击底部Tab我的
			selectTabIndex = 2;
			break;
		}
		if(selectTabIndex != -1 && selectTabIndex != currentTabIndex) {
			if(selectTabIndex < 0 || selectTabIndex >= tabCount) {
				Log.e(TAG, "selectTabIndex is " + selectTabIndex + " and out of 0 ~ " + (tabCount-1));
			} else {
				resetTab(selectTabIndex);//重新设置Tab
				//setActionBar(selectTabIndex);//重新设置ActionBar
			}
		}
		mViewPager.setCurrentItem(selectTabIndex);
	}
	
	private void resetTab(int selectTabIndex) {
		tabTextView[currentTabIndex].setSelected(false);//原先选择的Tab设置为不选择
		tabTextView[selectTabIndex].setSelected(true);//设置新的Tab
		currentTabIndex = selectTabIndex;
		TextView tv = setCenterTitle(tabText[currentTabIndex]);
		tv.setCompoundDrawables(null, null, null, null);
		showTabIndex = currentTabIndex;
	}
	
	//首页地图相关控件
	private BaiduMap mBaiduMap;
    private MapService locService;
    private MapView mMapView = null;    
	private LinkedList<LocationEntry> locationList = new LinkedList<LocationEntry>(); // 存放历史定位结果的链表,最大存放当前结果的前5次定位结果
	public TextView tv_location;
	
	private void initMapView() {
		//获取地图控件引用  
        mMapView = (MapView) view_home.findViewById(R.id.bmapView);  
        tv_location = (TextView) view_home.findViewById(R.id.tv_location);
        mBaiduMap = mMapView.getMap();
		mBaiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL);
		mBaiduMap.setMapStatus(MapStatusUpdateFactory.zoomTo(15));
		locService = ((MapApplication) getApplication()).healthService;
		LocationClientOption mOption = locService.getDefaultLocationClientOption();
		mOption.setLocationMode(LocationClientOption.LocationMode.Battery_Saving); 
		mOption.setCoorType("bd09ll");
		locService.setLocationOption(mOption);
		locService.registerListener(mListener);
		locService.start();
	}
	/***
	 * 定位结果回调,在此方法中处理定位结果
	 */
	BDLocationListener mListener = new BDLocationListener() {
		@Override
		public void onReceiveLocation(BDLocation location) {
			Log.i(TAG,"定位返回信息");
			if (location != null && (location.getLocType() == 161 || location.getLocType() == 66)) {
				tempLocation = location;
				locate(location);
			}
		}
	};
	//记录轨迹模块相关控件
	private TextView run_time;
	private TextView run_step;
	private TextView run_distance;
	private Boolean isRunning = false;
	private Button bt_start;
	private static BaiduMap mRunBaiduMap;
    private MapView bmapView = null;
    LBSTraceClient client = new LBSTraceClient(MainActivity.this);//实例化轨迹服务客户端
    protected static Trace trace = null; // 轨迹服务
    protected static OnEntityListener entityListener = null;// Entity监听器
    protected OnStartTraceListener  startTraceListener;
    protected OnStopTraceListener stopTraceListener;
    
    long serviceId  = 116488;//鹰眼服务ID
    private int gatherInterval = 5; // 采集周期(单位 : 秒)
    private int packInterval = 60;//打包周期(单位 : 秒)
	String entityName = "mycar";//entity标识
	//轨迹服务类型(0 : 不上传位置数据,也不接收报警信息; 1 : 不上传位置数据,但接收报警信息;2 : 上传位置数据,且接收报警信息)
	int traceType = 2;
	RefreshThread refreshThread;//该线程用来查询实时位置
	private static List<LatLng> pointList = new ArrayList<LatLng>();
	private static BitmapDescriptor realtimeBitmap; //图标
	protected static OverlayOptions overlay;// 覆盖物
	private static PolylineOptions polyline = null;// 路线覆盖物 
	protected static MapStatusUpdate msUpdate = null;
	long start_run;
	long stop_run;
	private static int run_time_show = 0;
	Timer timer = new Timer();  
	 private static final int RUN_STOP = 15;
    private void initRunView() {
    	initTrace();
		bt_start = (Button) view_run.findViewById(R.id.run_start);
		bt_start.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				startRun();
			}
		});
	}
    private void  initTrace(){
	    trace = new Trace(getApplicationContext(), serviceId, entityName,traceType);
        initOnEntityListener();
        initStartListener();
        initStopListener();
        // 设置采集周期
        client.setInterval(gatherInterval, packInterval);
        bmapView = (MapView) view_run.findViewById(R.id.run_mapView);  
        mRunBaiduMap = bmapView.getMap();
        bmapView.showZoomControls(false);
	}
    
    /**
     * 初始化OnEntityListener
     */
    private void initOnEntityListener() {
        entityListener = new OnEntityListener() {
            @Override
            public void onRequestFailedCallback(String arg0) {// 请求失败回调接口
                Looper.prepare();
                Log.i(TAG,"entity请求失败回调接口消息 : " + arg0);
                Looper.loop();
            }
            @Override
            public void onAddEntityCallback(String arg0) {// 添加entity回调接口
                Looper.prepare();
                Log.i(TAG,"添加entity回调接口消息 : " + arg0);
                Looper.loop();
            }
            @Override
            public void onQueryEntityListCallback(String message) {// 查询entity列表回调接口
            }
            @Override
            public void onReceiveLocation(TraceLocation location) {
            	// showMessage("onReceiveLocation拿到回调位置");
            	showRealLocation(location);
            }
        };
    }
    private void initStartListener() {
		//实例化开启轨迹服务回调接口
		startTraceListener = new OnStartTraceListener() {       
		    //开启轨迹服务回调接口(arg0 : 消息编码,arg1 : 消息内容,详情查看类参考)
		     @Override
		     public void onTraceCallback(int arg0, String arg1) {   
		    	 Log.i(TAG,"onTraceCallback开启轨迹服务回调" + arg0 + ",消息内容 : " + arg1 + "]");
		    	 showMessage("开启轨迹服务");
	                if (0 == arg0 || 10006 == arg0 || 10008 == arg0) {
	                    isRunning = true;
	                    startRefreshThread(true);
	                }
		     }
		    //轨迹服务推送接口(用于接收服务端推送消息,arg0 : 消息类型,arg1 : 消息内容,详情查看类参考)
		     @Override
		     public void onTracePushCallback(byte arg0, String arg1) {
		    	 Log.i(TAG,"轨迹服务推送接口消息 [消息类型 : " + arg0 + ",消息内容 : " + arg1 + "]");
		     }
		};
	}
    private void initStopListener() {
		 stopTraceListener = new OnStopTraceListener() {
           public void onStopTraceSuccess() {// 轨迹服务停止成功
           	Log.i(TAG,"onStopTraceSuccess关闭轨迹服务");
               showMessage("停止轨迹服务成功");
               locHander.sendEmptyMessage(RUN_STOP);
               isRunning = false;
               startRefreshThread(false);
           }
           // 轨迹服务停止失败(arg0 : 错误编码,arg1 : 消息内容,详情查看类参考)
           public void onStopTraceFailed(int arg0, String arg1) {
           	}
           };
	}
    //用来展示当前的运动轨迹
    private void showRealLocation(TraceLocation location) {
    	Log.i(TAG,"showRealLocation展示当前运动轨迹");
    	 if (null == refreshThread || !refreshThread.refresh) {
    		 return;
         }
         double latitude = location.getLatitude();
         double longitude = location.getLongitude();
         if (Math.abs(latitude - 0.0) < 0.000001 && Math.abs(longitude - 0.0) < 0.000001) {
         } else {
             LatLng latLng = new LatLng(latitude, longitude);
             pointList.add(latLng);
             drawRealtimePoint(latLng);
         }
	}
    /**
     * 绘制实时点
     * @param points
     */
    private void drawRealtimePoint(LatLng point) {
    	Log.i(TAG,"绘制路线的点");
        mRunBaiduMap.clear();
        MapStatus mMapStatus = new MapStatus.Builder().target(point).zoom(18).build();
        msUpdate = MapStatusUpdateFactory.newMapStatus(mMapStatus);
        realtimeBitmap = BitmapDescriptorFactory
                .fromResource(R.drawable.icon_gcoding);
        overlay = new MarkerOptions().position(point)
                .icon(realtimeBitmap).zIndex(9).draggable(true);
        if (pointList.size() >= 2 && pointList.size() <= 10000) {
            polyline = new PolylineOptions().width(10)// 添加路线(轨迹)
                    .color(Color.RED).points(pointList);
        }
        addMarker();
    }
    /**
     * 添加地图覆盖物
     */
    protected static void addMarker() {
        if (null != msUpdate) {
        	Log.i(TAG,"设置mRunBaiduMap的状态");
            mRunBaiduMap.setMapStatus(msUpdate);
        }
        if (null != polyline) {// 路线覆盖物
        	Log.i(TAG,"添加mRunBaiduMap的路线覆盖物");
            mRunBaiduMap.addOverlay(polyline);
        }
        if (null != overlay) {// 实时点覆盖物
        	Log.i(TAG,"添加mRunBaiduMap的实时点覆盖物");
            mRunBaiduMap.addOverlay(overlay);
        }
    }
    
    protected void startRefreshThread(boolean isStart) {
    	Log.i(TAG,"开启监控线程");
        if (null == refreshThread) {
            refreshThread = new RefreshThread();
        }
        refreshThread.refresh = isStart;
        if (isStart) {
            if (!refreshThread.isAlive()) {
                refreshThread.start();
            }
        } else {
            refreshThread = null;
        }
    }
    protected class RefreshThread extends Thread {
        protected boolean refresh = true;
        @Override
        public void run() {
            while (refresh) {
                queryRealtimeTrack();// 查询实时轨迹
                try {
                    Thread.sleep(gatherInterval * 1000);
                } catch (InterruptedException e) {
                    System.out.println("线程休眠失败");
                }
            }
        }
    }
    /**
     * 查询实时轨迹
     */
    private void queryRealtimeTrack() {
        client.queryRealtimeLoc(serviceId, entityListener);
    }
    long temp_time = 0;
	private void startRun() {
		if(!isRunning){
			start_run = System.currentTimeMillis();
			bt_start.setText("停止轨迹服务");
			startService();
		}
		else{ 
			String curDate = DateUtils.getCurrentDate();
			stop_run = System.currentTimeMillis();
			temp_time = stop_run-start_run+temp_time;
			stop_run = 0;
			start_run = 0;
			//updateInfo(curDate,temp_time,mStepValue,mDistanceValue);
			bt_start.setText("正在停止轨迹服务...");
			stopService();
		}
	}
	
	private void startService() {
        if (! isRunning) {
            Log.i(TAG, "Start StepService");
            isRunning = true;
            client.startTrace(trace, startTraceListener);//开启轨迹服务
        }
    }
    private void stopService() {
    	 Log.i(TAG, "stopService");
        client.stopTrace(trace, stopTraceListener);
    }
    
    
    //初始化我的模块
	private void initMineView() {
		view_mine.findViewById(R.id.mine_record).setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				Intent intend = new Intent(MainActivity.this,RecordActivity.class);
				startActivity(intend);
			}
		});
		view_mine.findViewById(R.id.exit).setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				if(isRunning){
					showExit();
				}else{
					MainActivity.this.finish();
				}
			}
		});
	}
	private void locate(BDLocation location){
		if (location != null && (location.getLocType() == 161 || location.getLocType() == 66)) {
			Message locMsg = new Message();
			locMsg.what = MsgConfig.MSG_MODE_MAP;
			Bundle locData;
			locData = Algorithm(location);
			if (locData != null) {
				locData.putParcelable("loc", location);
				locMsg.setData(locData);
				locHander.sendMessage(locMsg);
			}
			String str = "";
			if (location.getPoiList() != null && !location.getPoiList().isEmpty()) {
				for (int i = 0; i < location.getPoiList().size(); i++) {
					Poi poi = (Poi) location.getPoiList().get(i);
					str = ("当前位置:"+poi.getName() + ";");
				}
			}
			if(str!=""){
				tv_location.setVisibility(View.VISIBLE);
				tv_location.setText(str);
			}
		}
	}
	 @Override  
    protected void onDestroy() {  
        super.onDestroy();  
        //在activity执行onDestroy时执行mMapView.onDestroy(),实现地图生命周期管理  
        locService.unregisterListener(mListener);
		locService.stop();
		stopService();
        mMapView.onDestroy();  
    }  
    @Override  
    protected void onResume() {  
        super.onResume();  
        //在activity执行onResume时执行mMapView. onResume (),实现地图生命周期管理  
        mMapView.onResume();  
    }  
    @Override  
    protected void onPause() {  
        super.onPause();  
        //在activity执行onPause时执行mMapView. onPause (),实现地图生命周期管理  
        mMapView.onPause();  
    }  
	/***
	 * 平滑策略代码实现方法,主要通过对新定位和历史定位结果进行速度评分,
	 * 来判断新定位结果的抖动幅度,如果超过经验值,则判定为过大抖动,进行平滑处理,若速度过快,
	 * 则推测有可能是由于运动速度本身造成的,则不进行低速平滑处理 ╭(●`∀´●)╯
	 */
	private Bundle Algorithm(BDLocation location) {
		Bundle locData = new Bundle();
		double curSpeed = 0;
		if (locationList.isEmpty() || locationList.size() < 2) {
			LocationEntry temp = new LocationEntry();
			temp.location = location;
			temp.time = System.currentTimeMillis();
			locData.putInt("iscalculate", 0);
			locationList.add(temp);
		} else {
			if (locationList.size() > 5)
				locationList.removeFirst();
			double score = 0;
			for (int i = 0; i < locationList.size(); ++i) {
				LatLng lastPoint = new LatLng(locationList.get(i).location.getLatitude(),
						locationList.get(i).location.getLongitude());
				LatLng curPoint = new LatLng(location.getLatitude(), location.getLongitude());
				double distance = DistanceUtil.getDistance(lastPoint, curPoint);
				curSpeed = distance / (System.currentTimeMillis() - locationList.get(i).time) / 1000;
				score += curSpeed * Utils.EARTH_WEIGHT[i];
			}
			if (score > 0.00000999 && score < 0.00005) { // 经验值,开发者可根据业务自行调整,也可以不使用这种算法
				location.setLongitude((locationList.
						get(locationList.size() - 1).location.getLongitude() + location.getLongitude())/ 2);
				location.setLatitude((locationList.
						get(locationList.size() - 1).location.getLatitude() + location.getLatitude())/ 2);
				locData.putInt("iscalculate", 1);
			} else {
				locData.putInt("iscalculate", 0);
			}
			LocationEntry newLocation = new LocationEntry();
			newLocation.location = location;
			newLocation.time = System.currentTimeMillis();
			locationList.add(newLocation);
		}
		return locData;
	}
	
	//点击后退键弹出对话框提示
	@Override
	public void onBackPressed() {
		if(isRunning){
			showExit();	
		}else{
			this.finish();
		}
	}
	private void showExit() {
		AlertDialog.Builder normalDia=new AlertDialog.Builder(MainActivity.this);  
        normalDia.setIcon(R.drawable.ic_launcher);  
        normalDia.setMessage("退出程序会停止轨迹服务,你确定要退出程序吗");  
        normalDia.setPositiveButton("确定", new DialogInterface.OnClickListener() {  
            @Override  
            public void onClick(DialogInterface dialog, int which) {  
                dialog.dismiss();
            	MainActivity.this.finish();  
            }  
        });  
        normalDia.setNegativeButton("取消", new DialogInterface.OnClickListener() {  
            @Override  
            public void onClick(DialogInterface dialog, int which) {  
            	dialog.dismiss();
            }  
        });  
        normalDia.create().show();  
    }  
	private void showMessage(String text){
		Message msg = new Message();
    	Bundle data = new Bundle();
    	data.putString("content",text);
    	msg.setData(data);
    	msg.what = MsgConfig.SHOW_INFO;
    	locHander.sendMessage(msg);
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/41915.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

TPAMI 2022 | 自动搜索文本识别网络的高性能特征提取器

©PaperWeekly 原创 作者 | 陈卓群单位 | 清华大学论文标题&#xff1a;Searching a High Performance Feature Extractor for Text Recognition Network收录情况&#xff1a;TPAMI论文链接&#xff1a;https://ieeexplore.ieee.org/document/9887897代码链接&#xff1a;…

HTTPS(对称加密+非对称加密+证书)

目录 1. 加密和解密 HTTPS工作过程 2. 对称加密 3. 对称加密 4. 既然都有非对称加密了,那为啥还要有对称加密 5. 中间人攻击 6. 引入证书 HTTPS 也是一个应用层协议. 是在 HTTP 协议的基础上引入了一个加密层. HTTP 协议内容都是按照文本的方式明文传输的. 这就导致在…

笔记本电脑恢复删除数据的5种方法

我们都知道笔记本电脑比台式电脑拥有方便携带的优势&#xff0c;但是不论是笔记本还是台式电脑&#xff0c;难免会出现数据丢失情况&#xff0c;如最近有位小伙伴&#xff0c;不小心将自己出差需要使用的工作资料误删了&#xff0c;那么问题来了&#xff0c;笔记本数据删除怎么…

Vuex的搭建与使用

Vuex 专门在Vue中实现集中式状态&#xff08;数据&#xff09;管理的插件 (Vue.use(Vuex))&#xff0c;对Vue应用中多个组件的共享状态进行集中式的管理&#xff08;读、写&#xff09;&#xff0c;也是一种组件间通信的方式&#xff0c;且适用于任意组件间通信。 如果多个组…

git的使用规范及技巧总结

一、什么是Git&#xff1f; Git是一个开源的分布式版本控制系统&#xff0c;可以有效、高速地处理从很小到非常大的项目版本管理。 也是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。 Git 与常用的版本控制工具 CVS, Subversion 等不同&#x…

聚观早报 | 黑五电子产品销售额飙升;谷歌不满微软收购动视暴雪

今日要闻&#xff1a;黑五电子产品销售额飙升&#xff1b;谷歌不满微软收购动视暴雪&#xff1b;特斯拉海外充电站价格下降&#xff1b;欧盟对微软发起反垄断调查&#xff1b;小米13渲染图曝光黑五电子产品销售额飙升 据消息&#xff0c;Adobe数据和分析部门Adobe Analytics发布…

Navicat Premium 16 连接Oracle注意事项

起因 新同学使用的新版本的Mac电脑 但是装的W系统M芯片 发现 PLSQL Developer 并不兼容 导致无法连接到Oracle数据 就临时换成Navicat Premium 16进行连接 然后就出现了一系列问题 Oracle默认编码集 ZHS16GBK 该问题是Navicat Premium默认使用Navicat自带的instantclient_…

激光雷达发射的PCB布局

1、激光发射的电路如下图所示。 重点就是要考虑电容、GaN、激光器三部分的布局。 2>第一种布局方式 激光器、GaN、电容三者都在同一层上,放电的回路也都在顶层上,此时临近的第二层没有铺地。 用ANSYS仿真得到此时得回路电感为2nH左右。我们都以500M时得寄生电感来评估。…

面试官:介绍一下 Redis 三种集群模式

小码今天去面试。 面试官&#xff1a;给我介绍一下Redis集群&#xff0c; 小码&#xff1a;啊&#xff0c;平时开发用的都是单机Redis&#xff0c;没怎么用过集群了。 面试官&#xff1a;好的&#xff0c;出门右转不谢。 小码内心困惑&#xff1a;在小公司业务量也不大&…

操作系统

文章目录一&#xff0c;操作系统是什么二&#xff0c;操作系统的发展史1) 1945~1955年2) 1955~1965年&#xff1a;首个操作系统诞生3) 1964~1979年&#xff1a;多道程序系统诞生4) 1979~至今&#xff1a;网络操作系统和分布式操作系统快速发展三&#xff0c;操作系统的类别一&a…

静态HTML旅行主题网页设计与实现——联途旅游网服务平台网(39页)HTML+CSS+JavaScript

&#x1f468;‍&#x1f393;学生HTML静态网页基础水平制作&#x1f469;‍&#x1f393;&#xff0c;页面排版干净简洁。使用HTMLCSS页面布局设计,web大学生网页设计作业源码&#xff0c;这是一个不错的旅游网页制作&#xff0c;画面精明&#xff0c;排版整洁&#xff0c;内容…

KafKa C++实战

1 集群 1. Kafka架构是由producer&#xff08;消息生产者&#xff09;、consumer&#xff08;消息消费者&#xff09;、borker(kafka集群的 server&#xff0c;负责处理消息读、写请求&#xff0c;存储消息&#xff0c;在kafka cluster这一层这里&#xff0c;其实里面是有很多个…

SpringBoot+Vue项目校园防疫管理系统

文末获取源码 开发语言&#xff1a;Java 使用框架&#xff1a;spring boot 前端技术&#xff1a;JavaScript、Vue.js 、css3 开发工具&#xff1a;IDEA/MyEclipse/Eclipse、Visual Studio Code 数据库&#xff1a;MySQL 5.7/8.0 数据库管理工具&#xff1a;phpstudy/Navicat JD…

Apollo 应用与源码分析:Monitor监控-硬件监控-GPS

硬件架构图 可以看到左下角的“GNSS定位模块”其实是有IMU和GPS Antenna 组成的。 执行分析 代码 class GpsMonitor : public RecurrentRunner {public:GpsMonitor();void RunOnce(const double current_time) override; };void GpsMonitor::RunOnce(const double current_t…

为什么要把Linux机器加入到Windows AD/域控制器(Linux机器为什么要入域)?

文章目录1. 如何入域&#xff1f;2. 如何判断入域成功&#xff1f;3. 入域的效果(目的)是什么&#xff1f;4. 入域和SSSD之间是什么关系&#xff1f;1. 如何入域&#xff1f; sudo yum -y install oddjob oddjob-mkhomedir sssd samba-common-tools adcli \krb5-workstation o…

Java项目:jsp+servlet实现的新闻发布系统

作者主页&#xff1a;源码空间站2022 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 本项目分为前后台&#xff1b; 前台主要功能为&#xff1a; 首页、娱乐新闻、经济新闻、文化新闻、小道新闻、用户评价等&#xff1b; 后台主要…

HTML5学习笔记(五)

CSS3 多列布局 CSS3新增了一种布局方式——多列布局。使用多列布局&#xff0c;可以轻松实现类似报纸那样的布局。 多列布局的应用非常广泛&#xff0c;像各大电商网站、素材网站中常见的“瀑布流效果”。 column-count属性来定义多列布局的列数。 column-width属性来定义多列…

【云原生系列】第四讲:Knative 之 Eventing

目录 序言 1.基础介绍 2.组成要素 2.1 事件源&#xff08;Event Source&#xff09; 2.2 事件处理&#xff08;Flow&#xff09; 2.3 事件消费者&#xff08;Event Consumer&#xff09; 3.架构模式 3.1 Source to Service ​编辑 3.2Channels & Subscriptions …

思科配置SVI实现VLAN间路由

思科SVI配置 说明 SVI技术与单臂路由和传统VLAN间路由一样&#xff0c;都是解决多个VLAN间通信问题。 SVI技术利用了多层交换机&#xff08;本文以三层交换机为例&#xff09;。 示例拓扑 其中S1为三层交换机 S2的Fa0/2接口于VLAN 10下 S3的Fa0/2接口于VLAN 20下 PC 1地…

NH2-picolyl-azide|2168629-06-7|Amine azide Picolyl叠氮生物标记基团

【产品描述】 西安凯新生物科技有限公司​picolyl-azide-NH2含有叠氮基&#xff0c;叠氮基可以通过点击化学与炔烃、BCN、DBCO反应&#xff0c;生成稳定的三唑键。末端羧酸在活化剂&#xff08;如EDC或HATU&#xff09;存在下可与伯胺基反应&#xff0c;形成稳定的酰胺键。叠氮…