版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
附录[7]。为了创建或打开现有数据库并返回一个可以读写数据库的对象,需要在构造SQLiteOpenHelper的实例之后,还需要调用getReadableDatabase()方法来创建数据库。数据库文件将存放于/data/data/<packageName>/databases/目录中。在明确了用户信息表的内容和SQLiteOpenHelper的使用方法后,下面编写SQLiteOpenHelper类来创建用于存储用户注册信息的SQLite数据库,SQLiteOpenHelper类中的方法如表3-1所示。表3-1SQLiteOpenHelper类下面通过具体代码来说明数据库创建的步骤以及表3-1中各方法的定义:为了在代码中执行SQL语句,编写DBOpenHelper类继承自SQLiteOpenHelper,重写onCreate()方法,在onCreate()方法中调用SQLiteDatabase的execSQL()方法执行建表语句,此部分的代码如下:Code:在DBOpenHelper中执行建表语句CREATETABLEIFNOTEXISTSuser(_idINTEGERPRIMARYKEYAUTOINCREMENT,uesrnameVARCHAR(20)userpasswordVARCHAR(20),userphonenumVARCHAR(20);useremailVARCHAR(20))当用户完成注册后,需要向数据库中添加数据,因此定义add方法用于向数据库中添加数据,调用add方法后,数据库将执行SQL的插入语句将数据添加到数据库中。具体代码如下所示:Code:add方法publicvoidadd(Stringusername,Stringuserpassword,Stringuseremail,Stringuserphonenum){
db.execSQL("INSERTINTOuser(username,userpassword,useremail,userphonenum)VALUES(?,?,?,?)",newObject[]{username,userpassword,useremail,userphonenum});
}在后面的登录过程中,要将用户输入的用户名和密码与数据库中存在的信息进行匹配,因此定义方法getAllData()用于获取数据库当中的全部数据并将其以数组列表的形式返回。在Android中查询数据是通过Cursor类来实现的,在getAllData()中,首先通过调用SQLiteDatabase.query()方法来构造Cursor对象,Cursor指向数据库中的一行数据,再在while循环中调用Cursor类的moveToNext()将光标依次移动到下一行,若下一行的数据不为空,则调用Cursor的getString()方法以及ArrayList<User>.add()方法将光标指向的该行数据添加到ArrayList<User>中,当while循环结束以后,即所有的用户信息数据都被添加到ArrayList<User>,将ArrayList<User>对象返回。该方法中对象和方法名的如表3-2和表3-3所示。类名对象名说明ArrayList<User>list存储用户数据Cursorcursor定位数据库中的行,移动到指定行,获取该行数据Stringname存储cursor指定行的用户名Stringphonenum存储cursor指定行的电话号码Stringemail存储cursor指定行的邮箱地址Stringpassword存储cursor指定行的密码表3-2getAllData方法中的对象方法名说明cursor.moveToNext存储用户数据db.query定位数据库中的行,移动到指定行,获取该行数据cursor.getString用户密码list.add电子邮箱地址userphonenum电话号码表3-3getAllData方法中的方法名getAllData方法的具体代码如下:Code:getAllData方法publicArrayList<User>getAllData(){
ArrayList<User>list=newArrayList<User>();
@SuppressLint("Recycle")Cursorcursor=db.query("user",null,null,null,null,null,"nameDESC");
while(cursor.moveToNext()){
Stringname=cursor.getString(cursor.getColumnIndex("name"));
Stringemail=cursor.getString(cursor.getColumnIndex("email"));
Stringphonenum=cursor.getString(cursor.getColumnIndex("phonenum"));
Stringpassword=cursor.getString(cursor.getColumnIndex("password"));
list.add(newUser(name,password,email,phonenum));
}
returnlist;
}3.3.2用户注册界面的设计通过上述步骤实现了SQLiteOpenHelper类后,就可以利用它来实现注册和登录功能。表3-4和表3-5为用户注册界面设计中用到的部分对象和方法。类名对象名说明EditTextrName用户名输入框EditTextrEmail电子邮箱输入框EditTextrPhone电话号码输入框EditTextrPsw1密码输入框EditTextrPsw2确认密码输入框DBOpenHelpermDBOpenHelper实现对数据库相关操作StringUsername存储用户输入的用户名Stringpassword1存储用户输入的密码StringPassword2存储用户输入的确认密码StringEmail存储用户输入的邮箱地址Stringphonenum存储用户输入的电话号码Intentintent实现界面跳转表3-4用户注册界面的对象方法名说明btn_register.setOnClickListener(this)设置按钮监听器rName.getText().toString().trim()返回用户输入的用户名TextUtils.isEmpty(username)判断username是否非空password1.equals(password2)判断密码和确认密码输入框的内容是否相同mDBOpenHelper.add(username,password2,email,phonenum)添加用户注册数据到数据库中表3-5用户注册界面的方法以下说明注册功能实现的具体步骤:(1)构造EditText对象rName,rEmail,rPhone,rPsw1,rPsw2,使用findViewById()方法获取用户注册界面输入框控件,然后对EditText对象使用getText().toString().trim()方法来返回字符串对象,用于获得用户注册时在输入框中输入的信息。(2)在if语句中使用TextUtils.isEmpty()方法来判断用户输入的注册信息是否为空,如果都不为空则使用password1.equals(password2)来判断两次输入的密码是否一致,若两次输入的密码一致,则构造SQLiteOpenHelper类的对象,调用SQLiteOpenHelper的add方法,将用户输入的注册信息添加到数据库中。若用户输入的两次密码不一致或者注册信息不完善,则不执行add方法,并通过Toast提示用户注册失败。(3)注册完成后,利用Intent将注册界面跳转到登录界面,用户可进行下一步的登录操作。此部分的代码如下:Code:注册按钮点击事件代码if(!TextUtils.isEmpty(username)&&!TextUtils.isEmpty(password1)&&!TextUtils.isEmpty(password2)){
//判断两次密码是否一致
if(password1.equals(password2)){
//将用户名和密码加入到数据库中
mDBOpenHelper.add(username,password2,email,phonenum);
Intentintent1=newIntent(registered.this,login.class);
startActivity(intent1);
finish();
Toast.makeText(this,"验证通过,注册成功",Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(this,"两次输入的密码不一致,注册失败,请重写输入注册信息",Toast.LENGTH_SHORT).show();
}
}else{
Toast.makeText(this,"注册信息不完善,注册失败",Toast.LENGTH_SHORT).show();
}3.3.3用户登录界面的设计为实现用户登录界面,在布局文件中创建activety_login.xml,整个界面采取垂直方向的LinearLayout布局,并在其中嵌套水平方向的LinearLayout布局,在里面放置用户名和密码的文本框TextView以及输入框EditText,并放置两个按钮Button,用于登录或者注册,还有复选框CheckBox,用于勾选是否需要记住密码,登录界面如图3-6所示。图3-6用户登录界面图在登录界面中,要实现的功能是:用户将自己在注册时填写的用户名和密码输入到文本框中,点击“登录”按钮完成登录,之后将跳转到车辆监控系统的界面当中。用户如果需要使用“记住密码”功能,可以勾选记住密码复选框,下次打开APP后就不用重复输入用户名和密码,若用户当前还未注册,则点击“注册”按钮跳转到注册界面进行用户信息的注册。图3-7说明了登录的流程。图3-7用户登录流程通过以下几个步骤来编写用户登录的功能:(1)在onCreate()中使用mDBOpenHelper=newDBOpenHelper(this)构造一个DBOpenHelper对象用于对数据库进行管理,便于后面对数据库中的用户信息进行查询。(2)构造ArrayList<User>对象data,调用mDBOpenHelper.getAllData()来将数据库中所有的用户信息存储到data中(3)调用EditText对象的方法getText().toString().trim(),用Sting对象name和password来分别存储用户登录时输入的用户名和密码。(4)通过语句name.equals(user.getName())&&password.equals(user.getPassword())来判断用户输入的用户名和密码是否与数据库中存储的用户名和密码相同。(5)若用户输入的用户名和密码与数据库中存储的用户名和密码相同,则新建一个子线程,用于用户登录,并在线程中使用sleep(2000),让程序休眠两秒,模拟登录时间,之后再用intent跳转到MainActivity.class,即车辆监控系统的界主面。子线程的代码如下:Code:子线程中实现登录按钮点击事件Threadthread=newThread(){
@Override
publicvoidrun(){
try{
sleep(2000);
Stringuser_name=userName;
Intentintent1=newIntent(login.this,MainActivity.class);
startActivity(intent1);
finish();
}catch(Exceptione){
e.printStackTrace();
}
}
};
thread.start();根据用户登录界面所要实现的功能,除了上述步骤外,还需利用SharedPreferences来完成记住密码的功能,SharedPreferences存储不同于文件的存储方式,它是使用键值对的方式来存储数据的,也就是说,当保存一条数据的时候,需要给这条数据提供一个对应的键,这样在读取数据的时候就可以通过这个键把相应的值取出来。在获取一个SharedPreferences对象之后,要在SharedPreferences文件中存储数据,主要分为3步实现。(1)调用SharedPreferences对象的edit()方法来获取一个SharedPreferences.Editor对象。(2)向SharedPreferences.Editor对象中用putString()方法添加数据。(3)调用apply()方法将添加的数据提交,从而完成数据的存储操作。记住密码功能实现的代码为:Code:记住密码功能的实现SharedPreferencessp=getSharedPreferences("user_mes",MODE_PRIVATE);editor=sp.edit();if(cb_rmbPsw.isChecked()){
editor.putBoolean("flag",true);
editor.putString("user",user.getName());
editor.putString("psw",user.getPassword());
editor.apply();
match2=true;
}else{
editor.putString("user",user.getName());
editor.putString("psw","");
editor.apply();
match2=false;
}如果记住密码按钮被勾选,则在editor中添加当前用户输入的用户名和密码,并通过apply()提交,否则将editor中不添加当前用户输入的密码。通过上述的代码将用户登录信息存储到SharedPreferences中后,下次用户登录时,就可以利用SharedPreferences读取数据来获取用户登录信息。SharedPreferences对象提供了一系列的get方法,用于对存储的数据进行提取,当读取字符串时可以使用getString()方法,它接收两个参数,第一个参数是键,传入存储数据时使用的键就可以得到相应的值;第二个参数是默认值,表示当传入的键找不到对应的值时会以什么样的默认值进行返回。在本文中,通过以下代码来实现:Code:选择“记住密码”功能后,填写用户和密码信息Stringuser_read=sp.getString("user","");
Stringpsw_read=sp.getString("psw","");
et_User.setText(user_read);
et_Psw.setText(psw_read);3.4GIS界面的设计Android设备获取位置可以使用GPS和Android网络位置提供器(NLP),为了实现对车辆位置信息的监控,本文选择使用百度地图API对百度地图进行二次开发,利用百度地图的地图和地理信息显示功能来完成对车辆位置的实时监控。在车辆监控系统中使用百度地图API,需要完成一些准备步骤。第一步:申请APIkey(AK),因为地图初始化时需要使用AK,获取AK的流程大致可分为如下四个步骤:(1)登录API控制台;(2)创建应用;(3)配置SHA1和包名;(4)提交生成AK。第二步:在申请了AK后下载Android定位SDK并解压,将libs中的jar和so放置到工程中jniLibs目录相应的位置,如图3-8所示。在项目中集成BaiduMapSDK,才能继续对百度地图进行开发。图3-8jniLibs目录第三步:配置build.gradle文件,在build.gradle文件中添加如下代码后再对项目进行SYNC操作:Code:配置build.gradle文件sourceSets{
main{
jniLibs.srcDir'libs'
jni.srcDirs=[]
}
}dependencies{
implementationfileTree(dir:'libs',include:['*.jar'])
androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2',{
excludegroup:'com.android.support',module:'support-annotations'
})}第四步:添加AK。完成上述准备步骤后,获得开发者密钥AK,在AndroidManifest.xml文件中对开发者密钥进行配置,由于地图的显示还需要网络和定位等相关权限,还需在AndroidManifest.xml中添加相应代码以获取相应的权限,AndroidManifest.xml中添加的代码如下:Code:配置AndroidManifest.xml文件<meta-dataandroid:name="com.baidu.lbsapi.API_KEY"
android:value="bz3zeOp8LQhPavNQKf37aY7VUjw2pBFp"></meta-data><uses-permissionandroid:name="android.permission.INTERNET"/><!--获取网络状态,根据网络状态切换进行数据请求网络转换--><uses-permissionandroid:name="android.permission.ACCESS_NETWORK_STATE"/><!--读取外置存储。如果开发者使用了so动态加载功能并且把so文件放在了外置存储区域,则需要申请该权限,否则不需要--><uses-permissionandroid:name="android.permission.READ_EXTERNAL_STORAGE"/><!--写外置存储。如果开发者使用了离线地图,并且数据写在外置存储区域,则需要申请该权限-->
<uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>为了实现地图定位界面,在布局文件中编写fragment_home.xml,整个界面采取垂直方向的LinearLayout布局,放置com.baidu.mapapi.map.MapView和TextView用于显示地图和地理位置信息,又通过嵌套RelativeLayout在com.baidu.mapapi.map.MapView中放置一个“定位”按钮Button,整个地图定位界面如图3-9所示。图3-9地图定位界面图在地图定位界面Java代码中用到的对象和方法如表3-6和表3-7所示。类名对象名说明TextViewlocationInfo显示定位信息MapViewmapView地图控件MyLocationListenermyListener获取定位数据Buttonlocationbt定位按钮LocationClientOptionoptionMapView初始化选项,用于设置地图LocationClientmLocationClient用于发起定位BaiduMapmbaiduMap用于显示地图StringBuildercurrentPosition用于添加定位信息LatLngll地理坐标基本数据结构,用于获取经纬度MyLocationDatalocData定位数据构造器MapStatus.Builderbuilder地图状态构造器表3-6地图定位界面用到的对象方法名说明mapView.getMap()获取地图控件引用mLocationClient.registerLocationListener(myListener)注册监听函数mbaiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL)设置地图显示样式mbaiduMap.setMyLocationEnabled(true)开启地图定位图层mLocationClient.start()开启定位mLocationClient.setLocOption(option)设置地图定位选项mbaiduMap.setMyLocationData(locData)设置定位数据builder.target(ll).zoom(18f)缩放视图mbaiduMap.animateMapStatus()更新位置表3-7地图定位界面用到的对象3.4.1显示地图在Java代码文件中通过mapView=root.findViewById(R.id.bmapView)获取百度map控件,再利用mapView.getMap()方法获取地图控件引用。再调用mbaiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL)设置地图的显示样式,最后调用SDKInitializer.initialize(getApplicationContext())完成SDK的初始化,即可显示地图。该部分代码如下:Code:显示地图SDKInitializer.initialize(getActivity().getApplicationContext());mapView=root.findViewById(R.id.bmapView);//获取百度map控件
mbaiduMap=mapView.getMap();//获取地图控件引用
mbaiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL);//设置地图显示为普通样式3.4.2显示地图的定位为了显示车辆在地图中的定位,在布局文件中添加一个按钮,在Java代码文件中编写按钮点击事件代码,具体实现步骤如下:1、通过LatLngll=newLatLng(bdLocation.getLatitude(),bdLocation.getLongitude())构造LatLng对象,LatLng对象用于获取经纬度,构造定位数据;2、构造MyLocationData对象,用于获取定位数据。调用mbaiduMap的setMyLocationData方法,传入MyLocationData对象,用于设置定位数据。4、构造MapStatus.Builder对象,用于缩放当前视图并更新当前的定位信息。该部分代码如下:Code:显示定位LatLngll=newLatLng(bdLocation.getLatitude(),bdLocation.getLongitude())MyLocationDatalocData=newMyLocationData.Builder()
.accuracy(bdLocation.getRadius())
//此处设置开发者获取到的方向信息,顺时针0-360
.direction(100).latitude(bdLocation.getLatitude())
.longitude(bdLocation.getLongitude()).build();;mbaiduMap.setMyLocationData(locData);MapStatus.Builderbuilder=newMapStatus.Builder();
builder.target(ll).zoom(18f);//缩放当前视图
mbaiduMap.animateMapStatus(MapStatusUpdateFactory.newMapStatus(builder.build()));//更新当前位置信息3.4.3显示定位数据信息地图下方通过locationInfo=root.findViewById(R.id.locationInfo)获取TextView控件,用于显示定位的数据信息,包括经纬度、国家、省份、地区、街道、定位方式等。具体实现步骤如下:声明LocationClient类对象,该对象初始化需传入Context类型参数。使用getApplicationConext()方法获取全进程有效的Context。利用LocationClientOption类配置定位SDK参数。其中,option.setLocationMode用于设置定位模式,默认高精度编写MyLocationListener类,其继承BDAbstractLocationListener类,在MyLocationListener类中重写onReceiveLocation方法,在onReceiveLocation中创建StringBuilder对象用于添加定位信息,定位信息的添加的内容来自bdLocation对象,其getLatitude()方法返回当前定位的纬度,getLongitude()返回定位的经度,getProvince()返回定位的省份,getCity()返回定位的城市,getAddrStr()返回地址。3.5车载视频与方向盘转角获取的设计编写用于显示车载视频和方向盘的布局文件fragment_dashboard.xml,整个界面采取垂直方向的LinearLayout布局,在里面包含RadioGroup,RadioGroup采用水平布局,并在RadioGroup中放置三个RadioButton,RadioButton提供了互斥选项组成的选项集。使用户在同一时间只能选择“车载监控视频”、“方向盘”、“方向盘数据”三项中的一项进行显示。在RadioGroup下方嵌套RelativeLayout并在其中放置VideoView、com.github.mikephil.charting.charts.LineChart、ImageView、TextView分别用于显示视频、图表、方向盘图片、方向盘转角信息。整个界面如图3-9所示。图3-9车载视频与方向盘界面图3.5.1车载视频车载视频的播放可以使用VideoView来完成,VideoView继承了SurfaceView同时实现了MediaPlayerControl接口,可以方便地实现对视频的播放。具体实现步骤如下:在布局文件中放置VideoView控件用于播放视频,并在在Java代码中初始化。在Androidstudio项目路径中的app\src\main\res\raw文件夹下放置将要用于播放的MP4格式视频文件。在Java代码中编写initLocalVideo方法用于播放视频initLocalVideo方法首先调用VideoView的setVideoURI方法用于设置视频播放的路径。再调用requestFocus方法用于获取焦点,最后再通过start方法启动播放视频。initvideo方法代码如下:Code:显示定位privatevoidinitLocalVideo(){vedio.setVideoURI(Uri.parse("android.resource://"+getResources().getResourcePackageName(R.raw.video)+"/raw/video"));vedio.requestFocus();vedio.start();}3.5.2方向盘转角为了实现对方向盘转角的获取,需要借助手机的传感器服务。本文利用手机的加速度传感器来对车辆的方向盘转角进行模拟。加速度传感器中的加速度是指重力加速度,当静止时,重力传感器的返回值与加速度传感器的返回值相同,即返回X、Y、Z三个方向上的加速度值。如果手机平放在桌面上,则X轴方向加速度默认为0,Y轴方向加速度默认为0,Z轴方向加速度默认为9.81(这个值是由地球的固有重力决定的)。把手机朝下放在桌上,z轴是-9.81。将手机向右倾斜,x轴为负值。将手机向上倾斜,y轴为负值。将手机向下倾斜,y轴为正值。要调用手机加速度传感器对车辆的方向盘转角进行模拟,首先需要初始化传感器服务,并实现SensorEventListener接口,具体步骤为:创建一个SensorManager来获取系统的传感器服务,再为加速度传感器注册监听器。实现SensorEventListener接口中的onSensorChanged方法与onAccuracyChanged方法。在onSensorChanged方法中使用event.values[]获取传感器在x、y、z轴上的分量大小。其中event.values[0]代表x轴分量,event.values[1]代表y轴分量,event.values[2]代表z轴分量。上述步骤的具体代码为:Code:显示定位 sm=(SensorManager)getActivity().getSystemService(Context.SENSOR_SERVICE);
sm.registerListener(this,sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),SensorManager.SENSOR_DELAY_NORMAL);在完成以上步骤后,就可以在onSensorChanged方法中使用加速度传感器的值,本文通过使用加速度传感器在y轴方向分量来模拟车辆方向盘的转角。为了显示方向盘转角的大小并对其进行可视化,先通过root.findViewById方法获取布局文件中的TextView以及ImageView,分别以文字和图片的方式来实时显示方向盘转角的变化。对于TextView,对其进行初始化后调用其setText方法,并传入event.values[1]参数,即方向盘的转角大小,来设置显示当前方向盘转角大小,通过在手机端进行的测试,此时event.values[1]的值与相应的方向盘旋转角度的值不相同,需要将event.values[1]的值乘以9.174,因此将方向盘图片旋转的角度为event.values[1]*9.174。对于ImageView,在对其进行初始化后,为了能够让方向盘的图片能够直观显示当前方向盘转角的状态,通过根据当前方向盘转角来对图片实时旋转的方法来完成。此部分代码:Code:显示定位 mtextViewy.setText("当前方向盘\n旋转角度为:"+y+"°");//以文字显示当前转角大小fang.setRotation(event.values[1]*9.174f);//对方向盘图片进行旋转3.6车辆状态信息的获取与显示为实现车辆状态信息的获取,在布局文件中编写fragment_notifications.xml,整个界面采取垂直方向的LinearLayout布局,在里面包含了RadioGroup,RadioGroup采用水平布局并在RadioGroup中放置三个RadioButton,使用户在同一时间只能选择“车速”、“油量”、“挡位”三项中的一项进行显示。在RadioGroup下方嵌套水平方向的LinearLayout并在其中放置两个按钮Button“接收”、“结束”分别完成接收UDP数据报和结束接收UDP数据报的功能。Button再在下方嵌套RelativeLayout放置三个com.github.mikephil.charting.charts.LineChart,分别用于显示车速、油量、挡位的可视化图表,并在com.github.mikephil.charting.charts.LineChart下方放置两个TextView,分别用于显示接收到的数据报内容和当前的车辆状态信息,整个界面的设计如图3-10所示。图3-10车辆状态信息获取与可视化界面图本文通过网络编程来获取车辆状态信息数据,利用UDP协议来完成对车辆状态信息的传输和获取。UDP是非面向连接的提供不可靠的数据包式的数据传输协议。其数据的传递过程类似于从邮局发送信件的过程,发送信件是通过邮局系统进行传递,中间也有可能丢失。在Android中UDP协议可以通过使用DatagramSocket、DatagramPacket两个类来完成收发报文的操作,其中DatagramSocket表示数据报套接字,可以它来创建数据报套接字并将其绑定到本地主机上的指定端口。DatagramPacket表示数据包,可以利用它来用来接收数据包。表3-8和3-9给出了车辆状态信息获取过程中用到的对象和方法。类名对象名说明Threadthread新建子线程DatagramSocketSocketUDP协议的SocketDatagramPacketpacket数据包Messagemsg包含数据对象的消息,用于传递给HandlerStringreceive以utf-8编码接收到的数据包中的数据表3-8车辆状态信息获取过程中用到的对象方法名说明socket.receive(packet)接收数据包mHandler.sendMessage(msg)将数据发送到Handler中用于后续更新UI表3-9车辆状态信息获取过程中用到的方法为了通过利用UDP协议实现车辆状态信息的获取,具体采取以下步骤来完成:新建一个子线程用于完成UDP报文的接收操作。在子线程中需要选择一个手机端的端口号用于接收数据包,构造DatagramSocket对象。创建发送的DatagramPacket数据包对象。调用DatagramSocket对象的receive(datagramPacket)方法,构造String对象接收通过receive方法收到的UDP报文,将其转码为UTF-8格式。具体代码如下:Code:UDP通信获取车辆状态信息Threadthread=newThread(){
@Override
publicvoidrun(){
try{
socket=newDatagramSocket(PhonePort);
}catch(SocketExceptione){
e.printStackTrace();
}
byte[]receBuf=newbyte[1024];
packet=newDatagramPacket(receBuf,receBuf.length);
while(stopReceiver==false){
try{
socket.receive(packet);
Stringreceive=newString(packet.getData(),0,packet.getLength(),"utf-8");
Messagemsg=newMessage();
msg.obj=receive;
mHandler.sendMessage(msg);
}catch(IOExceptione){
e.printStackTrace();
}
}
}
};通过上述步骤接收到UDP报文中的车辆状态信息后,需要对这些信息进行显示并进行可视化处理。但由于Android中无法直接通过子线程来进行UI更新操作,还需要使用Android中提供的异步消息处理机制Handler来更新UI。表3-10和3-11说明了Handler类中用到的对象和方法。类名对象名说明TextViewmessage显示UDP收到的数据包内容float(变量)sp1、sp2、sp3、sp4存储速度信息可视化图表中各点的y轴坐标值float(变量)oi1、oil2、oil3、oil4存储油量信息可视化图表中各点的y轴坐标值float(变量)ge1、ge2、ge3、ge4存储挡位信息可视化图表中各点的y轴坐标值float(变量)speed、oil、gear存储UDP收到的最新速度、油量、挡位的值Stringmes存储子线程中发来的数据包表3-10Handler中用到的对象方法名说明Speed=Float.parseFloat(mes.substring(0,5))提取数据包中的前5位字符作为车速的大小oil=Float.parseFloat(mes.substring(5,8))提取数据包中的6-8位字符作为油量的大小gear=Integer.parseInt(mes.substring(8,9))提取数据包中的第9位字符作为挡位的大小message.setText在界面中显示收到的UDP数据包内容表3-11Handler中用到的方法车辆状态信息获取的具体实现步骤如下:在子线程中构造message对象,message是Handler接收与处理的消息对象。构造mHandler类继承handler类,通过复写handlerMessage()方法,编写代码来完成更新UI的操作。在子线程中设置好的消息,由handler发送出去:handler.sendMessage(message),就可以在mhandler类中使用子线程中传递的message中的数据。handler类代码如下:Code:Handler类classmHandlerextendsHandler{
//通过复写handlerMessage()从而确定更新UI的操作
@Override
publicvoidhandleMessage(Messagemsg){
message.setText("socket收到车辆信息:"+(String)msg.obj);
mes=(String)msg.obj;
speed=Float.parseFloat(mes.substring(0,5));
oil=Float.parseFloat(mes.substring(5,8));
gear=Integer.parseInt(mes.substring(8,9));
sp1=sp2;
sp2=sp3;
sp3=sp4;
sp4=speed;
oi1=oi2;
oi2=oi3;
oi3=oi4;
oi4=oil;
ge1=ge2;
ge2=ge3;
ge3=ge4;
ge4=gear;
}
}为了识别数据包中不同类型的车辆状态信息,本文通过对数据包中不同位的数据进行划分来表示不同的车辆状态信息。规定数据包中第1到5位字符串表示车速大小,第6到8位字符串表示当前油量剩余,第9位字符串表示当前车辆的挡位。例如52.350692表示当前车速为52.35km/h,当前油量剩余69%,当前挡位为2挡。有了以上对数据包数据的规定,本文在handler的handleMessage方法中通过TextView对象的setText方法在界面中显示手机收到的报文。再通过将从子线程中接收到message转换为字符串对象,利用String对象的substring方法对数据包中不同位的数据进行提取分别赋值给存储车速、油量、挡位信息的float型变量,便于后续显示以及可视化。3.7车辆状态信息的可视化3.7.1方向盘数据的可视化为了实现对车辆状态信息的可视化,本文利用MPAndroidChart将车辆状态信息以线型图的方式显示出来,对于方向盘转角,其显示的数据来源为加速度传感器的event.values[1],event.values[1]将根据手机的转角实时变化,对于车辆的速度、油量、挡位信息的监控,将根据UDP每次获取的报文对图表进行更新,每收到一次UDP报文则对图表进行一次更新,以对车辆状态信息进行实时显示。MPAndroidChart是一个强大的Android图表库,可以提供线图和饼状图,支持选择、缩放和拖放等功能。为了在AndroidStudio项目中集成MPAndroidChart库,需要在Project的build.gradle里添加如下代码:Code:配置build.gradle文件allprojects{
repositories{
jcenter()
maven{url"https://jitpack.io"}
}
}添加完上述代码后对项目进行SYNC操作,将自动下载MPAndroidChart库,对MPAndroidChart库添加之后,编写代码实现对方向盘转角的显示,表3-12和表3-13说明了方向盘数据可视化过程中用到的对象和方法。类名对象名说明ArrayList<Entry>entry存储Entry数组Entryc1e1-c1e7存储数据坐标值LineDataSetData存储坐标的数据集LineDatage1、ge2、ge3、ge4与折线图关联的所有数据的数据对象LineChartmylineChart线型图对象Stringmes存储子线程中发来的数据包表3-12方向盘数据可视化用到的对象方法名说明mylineChart.setData(lineData)设置线性图的数据,进行显示mylineChart.invalidate()刷新图表表3-13方向盘数据可视化用到的方法通过以下步骤实现:设置数据,构造动态数组List<Entry>entry以及Entry对象,Entry对象存储图表数据点的x、y轴坐标。调用数组List<Entry>entry的add方法动态添加entry。构造数据集LineDataSet的对象,传入数组List<Entry>entry作为参数,构造LineData,对象,将数据集添加到LineData中,再调用LineChart的setData方法,传入LineData对象,在图表中显示数据。此部分代码如下:Code:配置build.gradle文件List<Entry>entry=newArrayList<Entry>();
Entryc1e1=newEntry(1,c2e1);
Entryc1e2=newEntry(2,c2e2);
Entryc1e3=newEntry(3,c2e3);
Entryc1e4=newEntry(4,c2e4);
Entryc1e5=newEntry(5,c2e5);
Entryc1e6=newEntry(6,c2e6);
Entryc1e7=newEntry(7,c2e7);
entry.add(c1e1);
entry.add(c1e2);
entry.add(c1e3);
entry.add(c1e4);
entry.add(c1e5);
entry.add(c1e6);
entry.add(c1e7);
LineDataSetdata=newLineDataSet(entry,"方向盘的角度变化");
LineDatalineData=newLineData(data);
mylineChart.setData(lineData);在每显示一次当前的图表数据后,使用Entry类的setY方法将变量c2e1-c2e7的值分别赋给c1e1-c1e7的y轴坐标值,再将当前c2e2-c2e7分别赋给c2e1-c2e6,将c2e7的值更新为当前方向盘转角的大小,以更新图表数据,对图表进行刷新,使得图表能够达到实时显示方向盘转角大小的目的。Code:配置build.gradle文件c1e1.setY(c2e1);
c1e2.setY(c2e2);
c1e3.setY(c2e3);
c1e4.setY(c2e4);
c1e5.setY(c2e5);
c1e6.setY(c2e6);
c1e7.setY(c2e7);
c2e1=c2e2;
c2e2=c2e3;
c2e3=c2e4;
c2e4=c2e5;
c2e5=c2e6;
c2e6=c2e7;
c2e7=(float)(Y_longitudinal*9.174+90);
mylineChart.invalidate();3.7.2其他车辆状态信息的可视化其他车辆状态信息的可视化与上述方向盘数据的可视化方法基本相同,通过定义三个List<Entry>entry对象用于存储三个图表的数据,分别构造三个数据集,在三个数据集中添加List<Entry>entry,最后再将每次从UDP获取的车辆状态信息数据通过添加到数据集中进行显示。需要注意的是,其他车辆状态信息的可视化与方向盘数据可视化存在一些差别,方向盘数据可视化利用的传感器数据随手机转角变化而实时进行变化,即传感器一直都在采集手机转角的大小,所以可以根据需要的时间间隔进行采集进行显示,对图表进行实时更新。而其他车辆状态信息,如车速、油量、挡位的数据是通过UDP方式从服务器端发送来的,在手机端每接收到一次报文则进行对图表更新一次。该过程可由图3-11表示。图3-11其他车辆状态信息的可视化过程其他车辆状态信息的可视化的代码如下(仅列出车速变化可视化的代码,其他两种状态信息的可视化代码与此基本相同):Code:配置build.gradle文件List<Entry>entry1=newArrayList<Entry>();
Entryspeed1=newEntry(1,0);
Entryspeed2=newEntry(2,0);
Entryspeed3=newEntry(3,0);
Entryspeed4=newEntry(4,0);
speed1.setY(sp1);
speed2.setY(sp2);
speed3.setY(sp3);
speed4.setY(sp4);
entry1.add(speed1);
entry1.add(speed2);
entry1.add(speed3);
entry1.add(speed4);
LineDataSetdata1=newLineDataSet(entry1,"车辆速度变化");
LineDatalineData1=newLineData(data1);
mylinespeed.setData(lineData1);
mylinespeed.notifyDataSetChanged();
mylinespeed.invalidate();sp1,sp2,sp3,sp4分别用于存储x坐标分别为1、2、3、4点的y坐标,并在handler类中,通过以下代码来实现对y轴坐标的更新,其中speed是通过udp最新获取到的车辆速度的大小。sp1=sp2;
sp2=sp3;
sp3=sp4;
sp4=speed;3.8本章小结本章是本论文的核心章节,首先介绍了Android开发环境的搭建,接着对本文在AndroidStudio中开发的项目文件结构以及文件的作用进行了阐述。其次,详细地介绍了车辆监控系统APP各个界面的设计过程,并给出了每个部分的代码部分。
4车辆监控系统的测试在完成车辆监控系统APP代码的编写后,在Androidstudio菜单的build栏中选择GenerateSignedBundle/APK进行APP的打包,如图4-1所示。图4-1Build栏弹出窗口后需要创建密钥库及密钥,点击createnew生成密钥后,再点击next后在如图4-2所示窗口中选择“release”以及“V2”生成发布版APP,点击finish。图4-2生成发布版APP窗口AndroidStudio提示生成apk文件完成之后,在项目目录下的app\release中就能看到.apk文件,如图4-3所示。之后再将此apk文件安装到手机上,对车辆监控系统进行测试。图4-3apk文件图4.1用户注册登录功能测试在Android手机中,用户点击应用程序图标后,将进入用户注册登录界面,如4-4所示。图4-4登录功能测试图用户如果还未注册用户名和密码,可以点击“注册”按钮,跳转到注册界面,并在注册界面填入相应的用户名、密码、手机号、邮箱信息,如图4-5所示。在信息填入完成后点击注册按钮返回登录界面。图4-6注册完成后返回登录界面图4.2地图定位功能的测试用户在登录界面登录成功后将进入车辆监控系统的主界面,如图所示。当前屏幕的上方显示了地图,下方显示了车辆的定位信息,点击地图中的“定位”按钮后,地图将跳转到车辆所处的位置上,并以蓝色图表标注具体的地理位置,此外用户还可以根据自己的需要滑动地图,进行放大、缩小、平移等操作。4.3车载视频和方向盘功能的测试用户通过屏幕下方的导航栏选中“车辆状态”后,将跳转到车载视频与方向盘监控的界面,点击上方的“车载监控视频”按钮后,将自动播放视频,如图4-8所示。图4-8车载监控视频点击“方向盘”按钮后将显示当前方向盘的旋转角度,方向盘的图片也将根据当前的旋转角度进行旋转,如图4-9所示。图4-9方向盘点击“方向盘变化”按钮后,将以图表的方式显示目前的方向盘转角大小,并实时进行更新,如图4-10所示。图4-10方向盘图表数据4.4车辆状态信息获取以及可视化测试服务器端通过利用NetFox来通过UDP进行数据发送的测试,NetFox是一个可以进行UDP发送数据包的工具,其界面如图4-11所示。图4-11NetFox界面点击上方的“系统”-“设置”,配置使用的IP地址以及端口,如图4-12所示。图4-12NetFox配置UDP选项配置完成后,点击“系统”-“启动”,然后在窗口下方选择“发送”,在“发送到”框中输入用户使用的Android手机的IP地址以及端口号,并在下方的文本框中输入要发送的数据030.30892后,根据APP设计过程中对数据包数据的规定,这个数据表示当前车速为30km/h,油量剩余为89%,车辆的挡位处于2挡,按回车键可将数据发送,如图4-13所示。图4-13NetFox发送数据此时将在Android手机端的车辆状态信息界面点击“接收”按钮开始接收UDP数据报数据,在服务器端发送数据后,将显示接收到的报文内容,并将报文内容进行解析,提取为车速、油量、挡位信息,进行显示,分别点击“车速”、“油量”、“挡位”按钮,将分别显示车辆的信息以及图表,如图4-14、图4-15、图4-16所示,分别显示了车辆的车速、油量、挡位信息。图4-14车辆车速信息的显示图4-15车辆油量信息的显示图4-16车辆挡位信息的显示进行多次的数据包发送后,图表将显示根据每次收到的数据绘制线性图,如图4-17所示图表显示了车速变化的信息。图4-17车速变化图4.5本章小结对车辆监控系统设计完成后,本章通过在Android手机上对APP的各功能依次进行测试,将APP运行结果以截图的形式进行展示。测试结果表明,本系统能够完成毕业设计课题的设计目标,达到了预期的效果。
5结论与展望5.1结论在车辆不断朝着智能化、信息化发展的今天,伴随着城市交通的大发展,车辆数量正以惊人的速度增长,给交通管理带来了许多问题。车辆监控系统为解决车辆监控管理问题提供了很好的方案。基于Android平台开发车辆监控系统,使系统功能更加完善,不仅为用户了提供便携性的支持,而且很大程度上提高了用户对于车辆进行监控的效率,具有广阔的应用前景。本文对基于Android、百度地图API、无线通信、数据库存储、数据可视化等多种技术对车辆监控系统进行了研究,设计了车辆监控系统终端的APP,以模拟的方式获取车辆信息后将这些信息实时显示。APP具有开放式体系结构和良好人机界面,易于扩展和维护,实现了在Android端对车辆进行监控管理。本文具体完成的工作如下:利用SQLite数据库存储技术构建了存储用户注册信息的数据库,并结合SharedPreferences实现了“记住密码”的功能。将用户注册信息添加到数据库中完成了注册功能,注册信息与登录信息进行匹配,实现了登录功能,为用户对车辆监控系统的使用提供了一定的安全性保护,提高APP功能的完整性。调用百度地图API,初始化百度地图SDK后,在屏幕中显示地图。以手机位置来模拟车辆位置的条件下,通过获取网络和定位权限,完成对车辆位置定位的功能,并在地图下方以文字方式显示具体的地理位置定位信息。通过本地视频来模拟车载视频的播放,并调用手机的加速度传感器对车辆的方向盘进行模拟,实时显示方向盘转角的大小,此外还对方向盘图片实时旋转达到使用户能够实时看到目前方向盘的旋转具体情况的效果。新建子线程编写UDP网络接口,用来获取服务器发来的车辆状态信息,并将这些车辆状态信息数据传到Handler类中来更新UI,显示车辆状态信息。结合开源的MPAndroid库,对车辆状态信息数据进行可视化处理,将车辆状态信息绘制成图表,对图表实时的更新。5.2展望从改进的角度来看,如果需要进一步完善系统的功能,为用户提供更好的服务,可以从以下几个方面进行对车辆监控系统进行功能上的补充:1、结合百度地图提供的基于鹰眼提供的接口和云端服务,构建一套轨迹管理系统,使得用户可以对车辆的行驶轨迹等进行分析。2、考虑建立云数据库,将用户的注册信息、车辆状态信息、可视化信息通过云数据进行存储,使得企业、单位等可以对庞大的车群进行管理,并利用这些数据结合大数据技术进行分析。3、在真实的车辆端组建车辆数据采集系统,进行硬件方面的设计,将车辆数据通过无线网络发到手机上,构建一套完整的车辆监控系统。参考文献杨洋.城市智能交通系统的发展现状与趋势探讨[J].城市建设理论研究(电子版),2020(11):53.于中天.浅谈Android应用软件与未来发展趋势[J].数字化
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 稻田泳池施工方案(3篇)
- 水电表施工方案(3篇)
- 2025年仓储行业仓储管理员(中级)职业技能考试真题及答案
- 进口镀银施工方案(3篇)
- 电厂降水施工方案(3篇)
- 学校防腐施工方案(3篇)
- 重庆除锈施工方案(3篇)
- 友谊小路施工方案(3篇)
- 2025年物业管理师考试真题及答案《物业管理基本制度与政策》
- 城市小区智能化系统设计方案
- 全国硕士研究生2024年-管理类综合能力真题(管理类联考)
- 长津湖课件教学课件
- 聚焦前沿:2025年职业教育产教融合共同体建设难题与对策研究
- 2025年广西国家工作人员学法用法考试试题及答案
- (2025秋新版)苏教版科学三年级上册全册教案
- 农商行法律培训课件
- 部编版小学二年级语文上册教学反思集体备课计划
- 执法用手机管理办法
- 双重管理安全员管理办法
- 2019-2025年中国鲜切水果行业市场调查研究及投资前景预测报告
- 染色体核型分析报告解读要点
评论
0/150
提交评论