监控系统是一项关键的技术和工程领域,旨在实时监测和评估环境中的各种因素,以便更好地理解、保护和管理我们的生活环境[1]。将视频、音频、传感器等多种类型的监控数据进行融合,提高对环境情况的感知和理解能力,使得监控可视化、人性化,方便人们实时了解、管理。
本文通过结合多模态数据融合,开发一种基于Android Studio的智能监控APP。通过SQLite数据库存储账号密码等相关信息,保证各类数据安全,同时对拥有的监控摄像进行增删改查等功能;通过结合类 SoundPool 和 MediaPlayer实现报警开关,对场景突发情况实现警报;利用类VideoView 和 SurfaceView实现监控画面显示以及其他视频流推送功能。本APP开发提供用户+管理员不同身份使用,进而拓展APP的不同功能。
SQLite 是嵌入式的轻量级数据库,它支持 SQL 语言,并且只利用很少的内存就有很好的性能。许多开源项目((Mozilla、PHP、Python)都使用了 SQLite。 SQLite 由 SQL 编译器、内核、后端以及附件组成。SQLite 通过利用虚拟机和虚拟数据库引擎(VDBE)技术,使调试、修改和扩展 SQLite 的内核变得更加方便。
通过网络连接,实现用户可以随时随地通过APP远程查看和监控所需的实时视频流。这可以提供更大的灵活性和便利性,让用户能够及时了解监控区域的情况。利用不同身份对不同用户设置不同的权限级别,实现不同功能实现以及数据安全保护。利用不同UI用户界面优化和交互体验改进:改进APP的用户界面设计,使其更加直观、易用、美观。
- 功能
4.1 APP框架
4.2 登录注册功能
通过SQLite数据库存储账号密码等相关信息[2],在本机内实现对账号密码的识别与验证,同时通过预选框选择管理员或用户进行注册与登录;用户与管理员个人信息存储在俩张表内,在登陆时利用管理员或用户的权限选择不同的表进行验证,保证各类数据安全,避免数据冲突。
SQLite提供了对数据库的加密和访问权限控制,可以保护存储在数据库中的敏感信息。
方便的数据管理:使用SQL语言进行数据库操作,可以轻松地进行数据的插入、更新、删除和查询。SQLite支持创建多个表,可以根据需要存储各种类型的数据。同时可以在多种操作系统上运行,使得数据库的迁移和部署变得更加容易。
本文设计的APP创建三张表d_manager、d_user、d_eye分别用以存储管理员信息、用户信息以及监控信息。在实际使用中,可以根据具体的需求设计和操作这些表格,例如插入管理员或用户信息,查询特定的监控信息等。
4.3 管理员功能
在管理员权限下登录后,会进入管理员界面,管理员共分为3个模块,分别是首页、管理、个人界面,通过授予相机、存储、播放等权限可以实现对监控的智能管理和报警功能。
4.3.1 首页
首页界面下,可以对已拥有的设备进行搜索,并且可以查看已拥有的设备和具体信息,包括编号、设备名称、功能描述等。利用SQLite进行数据存储备份,作为一个轻量级的数据库,支持基本 SQL 语法,是常被采用的一种数据库。
在登录或注册时,对d_manager表格进行查询或插入操作,从而完成APP的进入权限审核与设置。
4.3.2 管理
管理界面下,可以对已拥有的设备进行增删改查操作,通过长按实现查看设备画面,并且管理员可以通过画面显示手动开启报警功能,测温功能使用模拟数据代替实现,未来通过连接温度传感器实现实际温度显示。
设备的相关操作由android.database.sqlite 包导入具体方法,根据给定 SQL语句,通过rawQuery(Stringsql,String[] selectionArgs)方法实现操作[3]。
画面显示采用模拟机虚拟场景代替实际摄像头,将完全初始化的 SurfaceHolder 传入到 setPreviewDisplay(Surface Holder)中完成。先调用 getParameters()获取当前(默认)的 settings,并定义 Camera.Parameters对象,调用setParameters(Camera.Parameters)来进行Camera的配置。
报警操作使用MediaPlayer类提供的方法,将MediaPlayer 对象进入 Prepared 状态,同步和异步两种方式可以使 MediaPlayer 对象进入 Prepared 状态。准备好 MediaPlayer 后,调用start()方法进行“报警”
4.3.3 个人界面
管理员个人界面下,拥有修改密码、注销账号和退出账号三个功能模块,修改密码采用数据库SQL更新修改语句对数据库数据进行修改,注销账号会在数据库中删除该条数据,退出账号会直接退出该软件,重新打开后需要重新输入账号密码进行登录。
在修改密码模块中,对于数据库更新操作进行了显式的提交,以确保数据的持久性。
4.4 用户功能
在用户权限下登录后,会进入用户界面,用户共分为3个模块,分别是购买、日志、个人界面,通过授予存储、播放等权限可以实现个人用户多方面体验不同的功能。
4.3.1 购买
购买界面下,用户会跳转到购买店铺信息界面,在这里可以购买所需要的监控摄像头。
该功能使用 HttpURLConnection 访问网络[4],HttpURLConnection 是 java 的标准类,继承自 URLConnection,可用于向指定网站发送GET 请求或 POST 请求,利用 HttpURLConnection 对象从网络中获取网页数据。
通过创建一个 URL 对象,参数指定了请求的 URL,包括请求参数。接着,创建一个 HttpURLConnection 对象,打开连接,并设置请求方法为 GET。然后,调用 connect() 方法建立与服务器的连接,在获取响应状态码后判断请求是否成功。如果响应请求成功,可以通过 getInputStream() 方法获取服务器返回的数据流,并进行相应的解析和处理。
4.3.2 日志
日志界面下,用户可以进行填写日志信息,日志信息会显示具体日期和时间,日志为缓存,会自动清空。
利用SimpleDateFormat处理日期格式化的类,将日期对象格式化成具有指定格式的字符串,也可以将字符串解析成日期对象。
4.3.3 个人界面
用户个人界面下,分为多个模块,包括修改密码,注销账号,退出账号,天气定位以及视频流推送存储模块。
- 修改密码,注销账号,退出账号
采用数据库SQL更新修改语句对数据库数据进行修改,注销账号会在数据库中删除该条数据,退出账号会直接退出该软件,重新打开后需要重新输入账号密码进行登录。
- 天气定位
天气定位功能使用了WebView来加载指定的URL,其中设置id为地点变量,用于指定需要加载的天气网页的城市id,当WebView的loadUrl方法被调用时,会发送一个HTTP请求到指定的URL并加载相应的页面。页面加载完成后,WebView会自动将页面渲染出来并显示在应用程序中。
- 视频推送存储
视频推送存储为个人界面中“大世界”模块,该模块界面模仿常见视频网站加载视频列表,点击视频信息栏目进入具体视频播放,可以对视频进行点赞。
该功能使用Movie 类型的对象创建以及对象的添加操作。其中,Movie 类型的构造函数需要传入参数,分别指定视频的名称和资源,可以将网络资源进行推送,再利用通过使用movieList.add() 方法,将创建好的对象添加到了列表中。
用户个人界面功能种类相对管理员个人界面有所增多,管理员管理界面功能较为详细;用户在购置监控后连接完成可利用管理员身份完成智能监测,亦可通过用户身份进行日志填写等其他事务操作。通过不同权限实现不同视角的体验。
- 结论
本文所设计的APP智能监控实现了在不同权限使用者下的不同功能,主要运用到了SQLite数据库增删改查、读取和存储数据库、MediaPlayer报警、视频流推送、URL网页连接等多种方法完成了智能监控的不同功能的设计。
本APP设计为之后的功能拓展提供了一个基本的平台。其中,在智能监控监测界面,在未来结合深度学习模块,实现机器智能识别监控,自动对危险行为给予警报提示,同时可以叠加多种传感器实现包括但不限于温度,湿度,二氧化碳浓度的测量和显示,帮助管理员从更多维的角度观察和管理环境。
在用户个人界面可通过订单功能了解监控摄像头购置情况,优化小世界模块功能,添加评论收藏等小功能,达到实现刷视频,推送视频的效果界面,同时引入支付和余额的显示插件,多方面提升用户的体验感。
监测系统是一项关键的技术和工程领域,通过监测系统,我们能够及时掌握各种系统的运行情况,预警潜在的安全隐患并及时采取措施,保障人们的生命财产安全。随着信息技术的快速发展,监控系统正在变得越来越智能化和高效化,将在未来起到更加重要的作用。
附录
主要源程序:
public class MainActivity extends AppCompatActivity {
//@RequiresApi(api = Build.VERSION_CODES.Q)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DBUtil dbUtil = new DBUtil(MainActivity.this);
SQLiteDatabase db = dbUtil.getWritableDatabase();
DBUtil.db=db;
//test
//Intent intent = new Intent(MainActivity.this, UserMyActivity.class);
//Intent intent = new Intent(MainActivity.this, ManageActivity.class);
//startActivity(intent);
//注册跳转
final RadioButton ma = this.findViewById(R.id.manager);
ma.setChecked(true);
Button zhuce = this.findViewById(R.id.make);
zhuce.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(ma.isChecked()){
Intent intent = new Intent(MainActivity.this, RegisteredManager.class);
startActivity(intent);
}else{
Intent intent = new Intent(MainActivity.this, RegisteredUsers.class);
startActivity(intent);
}
}
});
//登录跳转
final EditText zh = this.findViewById(R.id.login_id);
final EditText mima = this.findViewById(R.id.login_pwd);
Button dl = this.findViewById(R.id.login);
dl.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String idD = zh.getText().toString();
String pwdD = mima.getText().toString();
if(idD.isEmpty()){
Toast.makeText(MainActivity.this,"用户名不能为空",Toast.LENGTH_SHORT).show();
}else if(pwdD.isEmpty()){
Toast.makeText(MainActivity.this,"密码不能为空",Toast.LENGTH_SHORT).show();
}else{
if(ma.isChecked()){ //管理员
int a = UserDao.loginUser(idD,pwdD,"1");
if(a==0){
Toast.makeText(MainActivity.this,"登录失败!",Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(MainActivity.this,"登录成功!",Toast.LENGTH_SHORT).show();
Intent intent = new Intent(MainActivity.this, ManagerActivity.class);
startActivity(intent);
}
}else{ //用户
int a = UserDao.loginUser(idD,pwdD,"2");
if(a==0){
Toast.makeText(MainActivity.this,"登录失败!",Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(MainActivity.this,"登录成功!",Toast.LENGTH_SHORT).show();
Intent intent = new Intent(MainActivity.this, UserHomeActivity.class);
startActivity(intent);
}
}
}
}
});
}
}
数据库:
private static final String DB_NAME = "db_info.db";
public static SQLiteDatabase db = null;
private static final int VERSION = 11; //版本
private Context context;
public DBUtil(Context context){
super(context,DB_NAME,null,VERSION);
this.context=context;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("PRAGMA foreign_keys = false");
byte tx[]=Getimg(R.drawable.default_img2) ;//将二进制转换成图品
String filePath= Tools.getimagePath()+"/tx.png";
Tools.saveByteArrayAsPng(tx,filePath,context);
System.out.println("我草泥马");
//byte tx[]=;
db.execSQL("drop table if exists d_user");
db.execSQL( "create table d_user(" +
"s_id varchar(20) primary key," +
"s_pwd varchar(20), " +
"s_name varchar(20)," +
"s_sex varchar(20),"+
"s_add varchar(20)," +
"s_tele varchar(20)," +
"s_img varchar(255))");
//System.out.println("我草泥马");
db.execSQL("drop table if exists d_manager");//如果这个表存在则刷除
db.execSQL("CREATE TABLE d_manager(" +
"s_id varchar(20) primary key," +
"s_pwd varchar(20), " +
"s_name varchar(20)," +
"s_sex varchar(20),"+
"s_add varchar(20)," +
"s_tele varchar(20)," +
"s_img varchar(255))");
ContentValues valueM = new ContentValues();
valueM.put("s_id", "root");
valueM.put("s_pwd", " 111");
valueM.put("s_name","高业成");
valueM.put("s_sex","男");
valueM.put("s_add" , "jit");
valueM.put("s_tele ", "15252547651");
String txPath= Tools.getimagePath()+"/default_img2.png";
Tools.saveByteArrayAsPng(Getimg(R.drawable.default_img2),txPath,context);
valueM.put("s_eye_img", txPath);
db.insert("d_manager",null,valueM);
db.execSQL("drop table if exists d_eye");//如果这个表存在则刷
db.execSQL("CREATE TABLE d_eye(" +
"s_eye_id varchar(20) primary key," +
"s_manager_id varchar(20), " +
"s_eye_name varchar(20)," +
"s_eye_des varchar(200),"+ //描述
"s_eye_add varchar(20)," +
"s_eye_img varchar(255))");
//db.insert( "d_eye",null,valuesM);
UserDao.addManager();
ContentValues values = new ContentValues();
values.put("s_eye_id", "1");
values.put("s_manager_id", " root");
values.put("s_eye_name","天眼#1");
values.put("s_eye_des","教学,办公室监控");
values.put("s_eye_add" , "科技楼办公室");
String e1Path= Tools.getimagePath()+"/e1.png";
Tools.saveByteArrayAsPng(Getimg(R.drawable.e1),e1Path,context);
values.put("s_eye_img", e1Path);
db.insert( "d_eye",null,values);
values.put("s_eye_id", "2");
values.put("s_manager_id", " root");
values.put("s_eye_name","大鹏监控#1");
values.put("s_eye_des","教室,走廊监控");
values.put("s_eye_add" , "教学楼办公室");
String e2Path= Tools.getimagePath()+"/e2.png";
Tools.saveByteArrayAsPng(Getimg(R.drawable.e2),e2Path,context);
values.put("s_eye_img", e2Path);
db.insert( "d_eye",null,values);
db.execSQL("PRAGMA foreign_keys = true");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
private byte[] Getimg(int value){
Resources res = context.getResources();
Bitmap e1 = BitmapFactory.decodeResource(res,value);
ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream(); //将Bitmap转换为字节数组 e1.compress(Bitmap.CompressFormat.PNG,100,byteArrayOutputStream);
byte[] imagee1 = byteArrayOutputStream.toByteArray();//执行插入操作
return imagee1;
}
}
监控:
public class CarmerEye extends AppCompatActivity {
Button btn_Back;
SurfaceView surfaceView;
MediaRecorder mediaRecorder;
private MediaPlayer mediaPlayer;
private Button toggleButton;
private boolean isCameraOpen = false;
Camera camera;
SurfaceHolder holder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_carmer_eye);
surfaceView =findViewById(R.id.surfaceview_PhoneCamera);
holder = surfaceView.getHolder();
holder.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
// 打开摄像头
try {
camera = Camera.open();
camera.setPreviewDisplay(holder);
camera.startPreview();
camera.autoFocus(null);//设置自动对焦
camera.setDisplayOrientation(90);
Camera.Parameters parameters = camera.getParameters();
//parameters.setPreviewSize(1920, 1080);
camera.setParameters(parameters);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
});
btn_Back = findViewById(R.id.btn_Back_PhoneCameraVideoPreview);
btn_Back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
final Button playStopButton = findViewById(R.id.button_play_stop);
playStopButton.setText("报 警");
mediaPlayer = MediaPlayer.create(this, R.raw.alarm);
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
playStopButton.setText("报 警");
}
});
toggleButton = findViewById(R.id.toggleButton);
toggleButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (isCameraOpen) {
closeCamera();
} else {
openCamera();
}
}
});
}
public void playOrStopMusic(View view) {
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
((Button) view).setText("报 警");
} else {
mediaPlayer.start();
((Button) view).setText("停 止");
}
}
@Override
protected void onDestroy() {
super.onDestroy();
mediaPlayer.release();
mediaPlayer = null;
}
private void openCamera() {
try {
camera = Camera.open();
isCameraOpen = true;
toggleButton.setText("测 温");
} catch (Exception e) {
e.printStackTrace();
}
}
private void closeCamera() {
if (camera != null) {
camera.release();
camera = null;
isCameraOpen = false;
toggleButton.setText("测 温");
}
}
}
APP所需权限:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.INTERNET" />