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

来源:互联网 发布:人工智能进入国考试卷 编辑:程序博客网 时间:2024/04/30 13:48

基本过程是android作为socket客户端将采集到的每一帧图像数据发送出去,PC作为服务器接收并显示每一帧图像实现远程监控。图片如下(后来PC端加了个拍照功能)。。。

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

 

(PS。刚学android和java不久很多东西还不懂,高手若是知道哪些地方可以继续优化的话还请多多指点下啊)

系统代码如下:
一、android手机客户端
(1)AndroidManifest.xml文件。添加camera和socket权限,并设置了程序开始执行的activity、

查看源码
打印?
01<?xmlversion="1.0"encoding="utf-8"?>
02<manifestxmlns: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-sdkandroid:minSdkVersion="15"/>
08       
09    <!-- 授予程序使用摄像头的权限 -->
10        <uses-permissionandroid:name="android.permission.CAMERA"/>
11        <uses-featureandroid:name="android.hardware.camera"/>
12        <uses-featureandroid:name="android.hardware.camera.autofocus"/>
13        <uses-permissionandroid:name="android.permission.INTERNET"/>
14    <uses-permissionandroid:name="android.permission.KILL_BACKGROUND_PROCESSES"/>
15    <uses-permissionandroid: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                <actionandroid:name="android.intent.action.MAIN"/>
27                <categoryandroid: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<?xmlversion="1.0"encoding="utf-8"?>
44<LinearLayoutxmlns: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<?xmlversion="1.0"encoding="utf-8"?>
60<TableLayoutxmlns: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?
003public class GetIP extendsActivity {
004        String ipname =null;
005        @Override
006    publicvoid 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              finalBuilder builder = newAlertDialog.Builder(this);  //定义一个AlertDialog.Builder对象                                        
014                builder.setTitle("登录服务器对话框");                         // 设置对话框的标题
015                   
016                //装载/res/layout/login.xml界面布局
017                TableLayout loginForm = (TableLayout)getLayoutInflater().inflate( R.layout.login,null);               
018                finalEditText iptext = (EditText)loginForm.findViewById(R.id.ipedittext);                               
019                builder.setView(loginForm);                             // 设置对话框显示的View对象
020                // 为对话框设置一个“登录”按钮
021                builder.setPositiveButton("登录"
022                        // 为按钮设置监听器
023                        ,new OnClickListener() {
024                                @Override
025                                publicvoid 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                                publicvoid 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?
053public class CameraTest extendsActivity {
054        SurfaceView sView;
055        SurfaceHolder surfaceHolder;
056        intscreenWidth, screenHeight;       
057        Camera camera;                   // 定义系统所用的照相机       
058        booleanisPreview = false;       //是否在浏览中
059        privateString ipname;
060   
061        @SuppressWarnings("deprecation")
062        @Override
063    publicvoid 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(newCallback() {
082                        @Override
083                        publicvoid surfaceChanged(SurfaceHolder holder,int format, int width,intheight) {                               
084                        }
085                        @Override
086                        publicvoid surfaceCreated(SurfaceHolder holder) {                                                       
087                                initCamera();                                           // 打开摄像头
088                        }
089                        @Override
090                        publicvoid 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    privatevoid 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(newStreamIt(ipname));         // 设置回调的类                               
120                                camera.startPreview();                                  // 开始预览                               
121                                camera.autoFocus(null);                                 // 自动对焦
122                        }catch (Exception e) {
123                                e.printStackTrace();
124                        }
125                        isPreview =true;
126                }
127    }
128       
129}
130   
131class StreamIt implements Camera.PreviewCallback {
132        privateString ipname;
133        publicStreamIt(String ipname){
134                this.ipname = ipname;
135        }
136           
137    @Override
138    publicvoid 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(newRect(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       
157class MyThread extends Thread{       
158        privatebyte byteBuffer[] = new byte[1024];
159        privateOutputStream outsocket;       
160        privateByteArrayOutputStream myoutputstream;
161        privateString ipname;
162           
163        publicMyThread(ByteArrayOutputStream myoutputstream,String ipname){
164                this.myoutputstream = myoutputstream;
165                this.ipname = ipname;
166        try{
167                        myoutputstream.close();
168                }catch (IOException e) {
169                        e.printStackTrace();
170                }
171        }
172           
173    publicvoid run() {
174        try{
175                //将图像数据通过Socket发送出去
176            Socket tempSocket =new Socket(ipname,6000);
177            outsocket = tempSocket.getOutputStream();
178            ByteArrayInputStream inputstream =new ByteArrayInputStream(myoutputstream.toByteArray());
179            intamount;
180            while((amount = inputstream.read(byteBuffer)) != -1) {
181                outsocket.write(byteBuffer,0, amount);
182            }
183            myoutputstream.flush();
184            myoutputstream.close();
185            tempSocket.close();                  
186        }catch (IOException e) {
187            e.printStackTrace();
188        }
189    }
190   
191}
192  
193        二、PC服务器端
194ImageServer.java 用于显示图像,并且可以拍照
195?
196public class ImageServer {       
197    publicstatic ServerSocket ss =null;
198       
199    publicstatic void main(String args[]) throws IOException{   
200            ss =new ServerSocket(6000);
201           
202        finalImageFrame frame = newImageFrame(ss);
203        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
204        frame.setVisible(true);
205          
206        while(true){
207                frame.panel.getimage();
208            frame.repaint();
209        }       
210    }
211          
212}
213   
214/**
215    A frame with an image panel
216*/
217@SuppressWarnings("serial")
218class ImageFrame extends JFrame{
219        publicImagePanel panel;
220        publicJButton jb;
221      
222    publicImageFrame(ServerSocket ss){
223               // get screen dimensions             
224               Toolkit kit = Toolkit.getDefaultToolkit();
225        Dimension screenSize = kit.getScreenSize();
226        intscreenHeight = screenSize.height;
227        intscreenWidth = screenSize.width;
228   
229        // center frame in screen
230        setTitle("ImageTest");
231        setLocation((screenWidth - DEFAULT_WIDTH) /2, (screenHeight - DEFAULT_HEIGHT) /2);
232        setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
233   
234        // add panel to frame
235        this.getContentPane().setLayout(null);
236        panel =new ImagePanel(ss);
237        panel.setSize(640,480);
238        panel.setLocation(0,0);
239        add(panel);
240        jb =new JButton("拍照");
241        jb.setBounds(0,480,640,50);
242        add(jb);
243        saveimage saveaction =new saveimage(ss);
244        jb.addActionListener(saveaction);
245    }
246   
247    publicstatic final int DEFAULT_WIDTH = 640;
248    publicstatic final int DEFAULT_HEIGHT = 560
249}
250   
251/**
252   A panel that displays a tiled image
253*/
254@SuppressWarnings("serial")
255class ImagePanel extends JPanel {    
256    privateServerSocket ss;
257    privateImage image;
258    privateInputStream ins;
259            
260    publicImagePanel(ServerSocket ss) { 
261            this.ss = ss;
262    }
263       
264    publicvoid getimage() throws IOException{
265            Socket s =this.ss.accept();
266        System.out.println("连接成功!");
267        this.ins = s.getInputStream();
268                this.image = ImageIO.read(ins);
269                this.ins.close();
270    }
271      
272    publicvoid paintComponent(Graphics g){ 
273        super.paintComponent(g);   
274        if(image == null)return;
275        g.drawImage(image,0, 0,null);
276    }
277   
278}
279   
280class saveimage implements ActionListener {
281        RandomAccessFile inFile =null;
282        bytebyteBuffer[] = newbyte[1024];
283        InputStream ins;
284        privateServerSocket ss;
285           
286        publicsaveimage(ServerSocket ss){
287                this.ss = ss;
288        }
289           
290        publicvoid actionPerformed(ActionEvent event){
291        try{
292                        Socket s = ss.accept();
293                        ins = s.getInputStream();
294                           
295                        // 文件选择器以当前的目录打开
296                JFileChooser jfc =new JFileChooser(".");
297                jfc.showSaveDialog(newjavax.swing.JFrame());
298                // 获取当前的选择文件引用
299                File savedFile = jfc.getSelectedFile();
300                   
301                // 已经选择了文件
302                if(savedFile != null) {
303                    // 读取文件的数据,可以每次以快的方式读取数据
304                    try{
305                                        inFile =new RandomAccessFile(savedFile,"rw");
306                                }catch (FileNotFoundException e) {
307                                        e.printStackTrace();
308                                }
309                }
310   
311            intamount;
312            while((amount = ins.read(byteBuffer)) != -1) {
313                inFile.write(byteBuffer,0, amount);
314            }
315            inFile.close();
316            ins.close();
317            s.close();
318            javax.swing.JOptionPane.showMessageDialog(newjavax.swing.JFrame(),
319                    "已接保存成功","提示!", javax.swing.JOptionPane.PLAIN_MESSAGE);
320                }catch (IOException e) {
321   
322                        e.printStackTrace();
323                }
324        }
325}

        开放源码如下(android我使用的是4.03的SDK,其它版本请自行更改。2.3.3版本以下的请注意initCamera()里被注释掉的哪一行)

只能在android4.04系统的手机上运行成功哦。

下面是测试成功时的启动画面:

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

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

转自:http://www.cnblogs.com/feifei1010/archive/2012/08/31/2664939.html  
0 0
原创粉丝点击