基于Android的远程视频监控系统(含源码)

2019-07-12 23:49发布

基本过程是android作为socket客户端将采集到的每一帧图像数据发送出去,PC作为服务器接收并显示每一帧图像实现远程监控。图片如下(后来PC端加了个拍照功能)。。。 基于Android的远程视频监控系统(含源码)   (PS。刚学android和java不久很多东西还不懂,高手若是知道哪些地方可以继续优化的话还请多多指点下啊) 系统代码如下:
一、android手机客户端
(1)AndroidManifest.xml文件。添加camera和socket权限,并设置了程序开始执行的activity、 查看源码 打印? 01 xml version="1.0" encoding="utf-8"?> 02 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 03     package="org.wanghai.CameraTest" 04     android:versionCode="1" 05     android:versionName="1.0" > 06     07     <uses-sdk android:minSdkVersion="15" /> 08         09      10         <uses-permission android:name="android.permission.CAMERA" /> 11         <uses-feature android:name="android.hardware.camera" /> 12         <uses-feature android:name="android.hardware.camera.autofocus" /> 13         <uses-permission android:name="android.permission.INTERNET"/> 14     <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/> 15     <uses-permission android:name="android.permission.RESTART_PACKAGES"/> 16     17     <application 18         android:icon="@drawable/ic_launcher" 19         android:label="@string/app_name" > 20                     21         <activity 22             android:name=".GetIP" 23             android:screenOrientation="landscape" 24             android:label="@string/app_name" > 25             <intent-filter> 26                 <action android:name="android.intent.action.MAIN" /> 27                 <category android:name="android.intent.category.LAUNCHER" /> 28             intent-filter> 29         activity> 30         <activity 31             android:name=".CameraTest" 32             android:screenOrientation="landscape" 33             android:label="@string/app_name" > 34     35         activity> 36             37     application> 38     39 manifest> 40    41         (2)main.xml 设置surfaceview用于摄像头采集图像的预览 42 ? 43 xml version="1.0" encoding="utf-8"?> 44 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 45     android:layout_width="fill_parent" 46     android:layout_height="fill_parent" 47     android:orientation="vertical" > 48     49    <SurfaceView 50         android:id="@+id/sView" 51         android:layout_width="fill_parent" 52         android:layout_height="fill_parent" 53         android:scaleType="fitCenter"/> 54     55 LinearLayout> 56    57         (3)login.xml 登录界面,用于输入服务器IP 58 ? 59 xml version="1.0" encoding="utf-8"?> 60 <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" 61         android:id="@+id/loginForm" 62         android:orientation="vertical" 63         android:layout_width="fill_parent" 64         android:layout_height="fill_parent" 65         > 66     67 <TableRow>            68 <TextView 69         android:layout_width="fill_parent" 70         android:layout_height="wrap_content" 71         android:text="IP:" 72         android:textSize="10pt" 73         /> 74 75 <EditText 76     android:id="@+id/ipedittext" 77         android:layout_width="fill_parent" 78         android:layout_height="wrap_content" 79         android:digits="0123456789." 80         android:hint="请填写服务器IP" 81         android:selectAllOnFocus="true" 82         /> 83 TableRow> 84     85 TableLayout> 查看源码 打印? 001         4)GetIP.java 获得服务器IP后,通过Intent启动CameraTest的activity,ip信息通过Bundle传递 002 ? 003 public class GetIP extends Activity { 004         String ipname = null; 005         @Override 006     public void onCreate(Bundle savedInstanceState) { 007         super.onCreate(savedInstanceState); 008         // 设置全屏 009         requestWindowFeature(Window.FEATURE_NO_TITLE); 010              getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN); 011         setContentView(R.layout.main);        012           013               final Builder builder = new AlertDialog.Builder(this);   //定义一个AlertDialog.Builder对象                                         014                 builder.setTitle("登录服务器对话框");                          // 设置对话框的标题 015                     016                 //装载/res/layout/login.xml界面布局 017                 TableLayout loginForm = (TableLayout)getLayoutInflater().inflate( R.layout.login, null);                018                 final EditText iptext = (EditText)loginForm.findViewById(R.id.ipedittext);                                019                 builder.setView(loginForm);                              // 设置对话框显示的View对象 020                 // 为对话框设置一个“登录”按钮 021                 builder.setPositiveButton("登录" 022                         // 为按钮设置监听器 023                         , new OnClickListener() { 024                                 @Override 025                                 public void onClick(DialogInterface dialog, int which) { 026                                         //此处可执行登录处理 027                                         ipname = iptext.getText().toString().trim(); 028                                         Bundle data = new Bundle(); 029                                         data.putString("ipname",ipname);                                        030                                         Intent intent = new Intent(GetIP.this,CameraTest.class); 031                                         intent.putExtras(data); 032                                         startActivity(intent); 033                                 } 034                         }); 035                 // 为对话框设置一个“取消”按钮 036                 builder.setNegativeButton("取消" 037                         new OnClickListener() 038                         { 039                                 @Override 040                                 public void onClick(DialogInterface dialog, int which) 041                                 { 042                                         //取消登录,不做任何事情。 043                                         System.exit(1); 044                                 } 045                         }); 046                 //创建、并显示对话框 047                 builder.create().show(); 048         } 049 } 050    051         5)CameraTest.java 程序主体。设置PreviewCallback后,每当一帧图像数据采集完成后将调用PreviewCallback的onPreviewFrame函数。在这里我们将YUV格式数据转为jpg,再启用线程将数据通过socket发送出去。 052 ? 053 public class CameraTest extends Activity { 054         SurfaceView sView; 055         SurfaceHolder surfaceHolder; 056         int screenWidth, screenHeight;        057         Camera camera;                    // 定义系统所用的照相机        058         boolean isPreview = false;        //是否在浏览中 059         private String ipname; 060     061         @SuppressWarnings("deprecation") 062         @Override 063     public void onCreate(Bundle savedInstanceState) { 064         super.onCreate(savedInstanceState); 065         // 设置全屏 066              requestWindowFeature(Window.FEATURE_NO_TITLE); 067              getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN); 068         setContentView(R.layout.main); 069             070         // 获取IP地址 071         Intent intent = getIntent(); 072         Bundle data = intent.getExtras(); 073         ipname = data.getString("ipname"); 074                             075                 screenWidth = 640; 076                 screenHeight = 480;                077                 sView = (SurfaceView) findViewById(R.id.sView);                  // 获取界面中SurfaceView组件                078                 surfaceHolder = sView.getHolder();                               // 获得SurfaceView的SurfaceHolder 079                     080                 // 为surfaceHolder添加一个回调监听器 081                 surfaceHolder.addCallback(new Callback() { 082                         @Override 083                         public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {                                084                         } 085                         @Override 086                         public void surfaceCreated(SurfaceHolder holder) {                                                        087                                 initCamera();                                            // 打开摄像头 088                         } 089                         @Override 090                         public void surfaceDestroyed(SurfaceHolder holder) { 091                                 // 如果camera不为null ,释放摄像头 092                                 if (camera != null) { 093                                         if (isPreview) 094                                                 camera.stopPreview(); 095                                         camera.release(); 096                                         camera = null; 097                                 } 098                             System.exit(0); 099                         }                100                 }); 101                 // 设置该SurfaceView自己不维护缓冲    102                 surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 103                     104     } 105         106     private void initCamera() { 107             if (!isPreview) { 108                         camera = Camera.open(); 109                 } 110                 if (camera != null && !isPreview) { 111                         try{ 112                                 Camera.Parameters parameters = camera.getParameters();                                113                                 parameters.setPreviewSize(screenWidth, screenHeight);    // 设置预览照片的大小                                114                                 parameters.setPreviewFpsRange(20,30);                    // 每秒显示20~30帧                                115                                 parameters.setPictureFormat(ImageFormat.NV21);           // 设置图片格式                                116                                 parameters.setPictureSize(screenWidth, screenHeight);    // 设置照片的大小 117                                 //camera.setParameters(parameters);                      // android2.3.3以后不需要此行代码 118                                 camera.setPreviewDisplay(surfaceHolder);                 // 通过SurfaceView显示取景画面                                119                         camera.setPreviewCallback(new StreamIt(ipname));         // 设置回调的类                                120                                 camera.startPreview();                                   // 开始预览                                121                                 camera.autoFocus(null);                                  // 自动对焦 122                         } catch (Exception e) { 123                                 e.printStackTrace(); 124                         } 125                         isPreview = true; 126                 } 127     } 128         129 } 130     131 class StreamIt implements Camera.PreviewCallback { 132         private String ipname; 133         public StreamIt(String ipname){ 134                 this.ipname = ipname; 135         } 136             137     @Override 138     public void onPreviewFrame(byte[] data, Camera camera) { 139         Size size = camera.getParameters().getPreviewSize();          140         try{ 141                 //调用image.compressToJpeg()将YUV格式图像数据data转为jpg格式 142             YuvImage image = new YuvImage(data, ImageFormat.NV21, size.width, size.height, null);  143             if(image!=null){ 144                     ByteArrayOutputStream outstream = new ByteArrayOutputStream(); 145                 image.compressToJpeg(new Rect(0, 0, size.width, size.height), 80, outstream); 146                 outstream.flush(); 147                 //启用线程将图像数据发送出去 148                 Thread th = new MyThread(outstream,ipname); 149                 th.start();               150              151         }catch(Exception ex){  152             Log.e("Sys","Error:"+ex.getMessage());  153         }        154     } 155 } 156         157 class MyThread extends Thread{        158         private byte byteBuffer[] = new