zoukankan      html  css  js  c++  java
  • 基于android的远程视频监控系统

    转自http://www.apkbus.com/android-57452-1-1.html

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

    (PS。刚学android和java不久很多东西还不懂,高手若是知道哪些地方可以继续优化的话还请多多指点下啊)
    此贴是这个系统的介绍,没有基础的朋友可以参考下面教程(会陆续补充完整,让大家都学会如何实现整个功能):
    (1)#Testin杯#基于android的远程视频监控系统——学习第一步实现Camera预览


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

    1. <?xml version="1.0" encoding="utf-8"?>
    2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    3.     package="org.wanghai.CameraTest"
    4.     android:versionCode="1"
    5.     android:versionName="1.0" >

    6.     <uses-sdk android:minSdkVersion="15" />
    7.     
    8.     <!-- 授予程序使用摄像头的权限 -->
    9.         <uses-permission android:name="android.permission.CAMERA" /> 
    10.         <uses-feature android:name="android.hardware.camera" /> 
    11.         <uses-feature android:name="android.hardware.camera.autofocus" />
    12.         <uses-permission android:name="android.permission.INTERNET"/>
    13.     <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/>
    14.     <uses-permission android:name="android.permission.RESTART_PACKAGES"/>

    15.     <application
    16.         android:icon="@drawable/ic_launcher"
    17.         android:label="@string/app_name" >
    18.                 
    19.         <activity
    20.             android:name=".GetIP"
    21.             android:screenOrientation="landscape"
    22.             android:label="@string/app_name" >
    23.             <intent-filter>
    24.                 <action android:name="android.intent.action.MAIN" />
    25.                 <category android:name="android.intent.category.LAUNCHER" />
    26.             </intent-filter>
    27.         </activity>
    28.         <activity
    29.             android:name=".CameraTest"
    30.             android:screenOrientation="landscape"
    31.             android:label="@string/app_name" >

    32.         </activity>
    33.         
    34.     </application>

    35. </manifest>
    复制代码
    (2)main.xml 设置surfaceview用于摄像头采集图像的预览
    1. <?xml version="1.0" encoding="utf-8"?>
    2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    3.     android:layout_width="fill_parent"
    4.     android:layout_height="fill_parent"
    5.     android:orientation="vertical" >

    6.    <SurfaceView
    7.         android:id="@+id/sView"
    8.         android:layout_width="fill_parent" 
    9.         android:layout_height="fill_parent"
    10.         android:scaleType="fitCenter"/>

    11. </LinearLayout>
    复制代码
    (3)login.xml 登录界面,用于输入服务器IP
    1. <?xml version="1.0" encoding="utf-8"?>
    2. <TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    3.         android:id="@+id/loginForm"
    4.         android:orientation="vertical"
    5.         android:layout_width="fill_parent"
    6.         android:layout_height="fill_parent"
    7.         >

    8. <TableRow>            
    9. <TextView
    10.         android:layout_width="fill_parent"
    11.         android:layout_height="wrap_content"
    12.         android:text="IP:"
    13.         android:textSize="10pt"
    14.         />
    15. <!-- 输入用户名的文本框 -->
    16. <EditText
    17.     android:id="@+id/ipedittext"
    18.         android:layout_width="fill_parent"
    19.         android:layout_height="wrap_content"
    20.         android:digits="0123456789."
    21.         android:hint="请填写服务器IP"
    22.         android:selectAllOnFocus="true"
    23.         />
    24. </TableRow>

    25. </TableLayout>
    复制代码
    (4)GetIP.java 获得服务器IP后,通过Intent启动CameraTest的activity,ip信息通过Bundle传递
    1. public class GetIP extends Activity {
    2.         String ipname = null;
    3.         @Override
    4.     public void onCreate(Bundle savedInstanceState) {
    5.         super.onCreate(savedInstanceState);
    6.         // 设置全屏
    7.         requestWindowFeature(Window.FEATURE_NO_TITLE);
    8.              getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
    9.         setContentView(R.layout.main);        
    10.       
    11.               final Builder builder = new AlertDialog.Builder(this);   //定义一个AlertDialog.Builder对象                                         
    12.                 builder.setTitle("登录服务器对话框");                          // 设置对话框的标题
    13.                 
    14.                 //装载/res/layout/login.xml界面布局
    15.                 TableLayout loginForm = (TableLayout)getLayoutInflater().inflate( R.layout.login, null);                
    16.                 final EditText iptext = (EditText)loginForm.findViewById(R.id.ipedittext);                                
    17.                 builder.setView(loginForm);                              // 设置对话框显示的View对象
    18.                 // 为对话框设置一个“登录”按钮
    19.                 builder.setPositiveButton("登录"
    20.                         // 为按钮设置监听器
    21.                         , new OnClickListener() {
    22.                                 @Override
    23.                                 public void onClick(DialogInterface dialog, int which) {
    24.                                         //此处可执行登录处理
    25.                                         ipname = iptext.getText().toString().trim();
    26.                                         Bundle data = new Bundle();
    27.                                         data.putString("ipname",ipname);                                        
    28.                                         Intent intent = new Intent(GetIP.this,CameraTest.class);
    29.                                         intent.putExtras(data);
    30.                                         startActivity(intent);
    31.                                 }
    32.                         });
    33.                 // 为对话框设置一个“取消”按钮
    34.                 builder.setNegativeButton("取消"
    35.                         ,  new OnClickListener()
    36.                         {
    37.                                 @Override
    38.                                 public void onClick(DialogInterface dialog, int which)
    39.                                 {
    40.                                         //取消登录,不做任何事情。
    41.                                         System.exit(1);
    42.                                 }
    43.                         });
    44.                 //创建、并显示对话框
    45.                 builder.create().show();
    46.         }
    47. }
    复制代码
    (5)CameraTest.java 程序主体。设置PreviewCallback后,每当一帧图像数据采集完成后将调用PreviewCallback的onPreviewFrame函数。在这里我们将YUV格式数据转为jpg,再启用线程将数据通过socket发送出去。
    1. public class CameraTest extends Activity {
    2.         SurfaceView sView;
    3.         SurfaceHolder surfaceHolder;
    4.         int screenWidth, screenHeight;        
    5.         Camera camera;                    // 定义系统所用的照相机        
    6.         boolean isPreview = false;        //是否在浏览中
    7.         private String ipname;

    8.         @SuppressWarnings("deprecation")
    9.         @Override
    10.     public void onCreate(Bundle savedInstanceState) {
    11.         super.onCreate(savedInstanceState);
    12.         // 设置全屏
    13.              requestWindowFeature(Window.FEATURE_NO_TITLE);
    14.              getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
    15.         setContentView(R.layout.main);
    16.         
    17.         // 获取IP地址
    18.         Intent intent = getIntent();
    19.         Bundle data = intent.getExtras();
    20.         ipname = data.getString("ipname");
    21.                         
    22.                 screenWidth = 640;
    23.                 screenHeight = 480;                
    24.                 sView = (SurfaceView) findViewById(R.id.sView);                  // 获取界面中SurfaceView组件                
    25.                 surfaceHolder = sView.getHolder();                               // 获得SurfaceView的SurfaceHolder
    26.                 
    27.                 // 为surfaceHolder添加一个回调监听器
    28.                 surfaceHolder.addCallback(new Callback() {
    29.                         @Override
    30.                         public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {                                
    31.                         }
    32.                         @Override
    33.                         public void surfaceCreated(SurfaceHolder holder) {                                                        
    34.                                 initCamera();                                            // 打开摄像头
    35.                         }
    36.                         @Override
    37.                         public void surfaceDestroyed(SurfaceHolder holder) {
    38.                                 // 如果camera不为null ,释放摄像头
    39.                                 if (camera != null) {
    40.                                         if (isPreview)
    41.                                                 camera.stopPreview();
    42.                                         camera.release();
    43.                                         camera = null;
    44.                                 }
    45.                             System.exit(0);
    46.                         }                
    47.                 });
    48.                 // 设置该SurfaceView自己不维护缓冲    
    49.                 surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    50.                 
    51.     }
    52.     
    53.     private void initCamera() {
    54.             if (!isPreview) {
    55.                         camera = Camera.open();
    56.                 }
    57.                 if (camera != null && !isPreview) {
    58.                         try{
    59.                                 Camera.Parameters parameters = camera.getParameters();                                
    60.                                 parameters.setPreviewSize(screenWidth, screenHeight);    // 设置预览照片的大小                                
    61.                                 parameters.setPreviewFpsRange(20,30);                    // 每秒显示20~30帧                                
    62.                                 parameters.setPictureFormat(ImageFormat.NV21);           // 设置图片格式                                
    63.                                 parameters.setPictureSize(screenWidth, screenHeight);    // 设置照片的大小
    64.                                 //camera.setParameters(parameters);                      // android2.3.3以后不需要此行代码
    65.                                 camera.setPreviewDisplay(surfaceHolder);                 // 通过SurfaceView显示取景画面                                
    66.                         camera.setPreviewCallback(new StreamIt(ipname));         // 设置回调的类                                
    67.                                 camera.startPreview();                                   // 开始预览                                
    68.                                 camera.autoFocus(null);                                  // 自动对焦
    69.                         } catch (Exception e) {
    70.                                 e.printStackTrace();
    71.                         }
    72.                         isPreview = true;
    73.                 }
    74.     }
    75.     
    76. }

    77. class StreamIt implements Camera.PreviewCallback {
    78.         private String ipname;
    79.         public StreamIt(String ipname){
    80.                 this.ipname = ipname;
    81.         }
    82.         
    83.     @Override
    84.     public void onPreviewFrame(byte[] data, Camera camera) {
    85.         Size size = camera.getParameters().getPreviewSize();          
    86.         try{ 
    87.                 //调用image.compressToJpeg()将YUV格式图像数据data转为jpg格式
    88.             YuvImage image = new YuvImage(data, ImageFormat.NV21, size.width, size.height, null);  
    89.             if(image!=null){
    90.                     ByteArrayOutputStream outstream = new ByteArrayOutputStream();
    91.                 image.compressToJpeg(new Rect(0, 0, size.width, size.height), 80, outstream); 
    92.                 outstream.flush();
    93.                 //启用线程将图像数据发送出去
    94.                 Thread th = new MyThread(outstream,ipname);
    95.                 th.start();               
    96.             }  
    97.         }catch(Exception ex){  
    98.             Log.e("Sys","Error:"+ex.getMessage());  
    99.         }        
    100.     }
    101. }
    102.     
    103. class MyThread extends Thread{        
    104.         private byte byteBuffer[] = new byte[1024];
    105.         private OutputStream outsocket;        
    106.         private ByteArrayOutputStream myoutputstream;
    107.         private String ipname;
    108.         
    109.         public MyThread(ByteArrayOutputStream myoutputstream,String ipname){
    110.                 this.myoutputstream = myoutputstream;
    111.                 this.ipname = ipname;
    112.         try {
    113.                         myoutputstream.close();
    114.                 } catch (IOException e) {
    115.                         e.printStackTrace();
    116.                 }
    117.         }
    118.         
    119.     public void run() {
    120.         try{
    121.                 //将图像数据通过Socket发送出去
    122.             Socket tempSocket = new Socket(ipname, 6000);
    123.             outsocket = tempSocket.getOutputStream();
    124.             ByteArrayInputStream inputstream = new ByteArrayInputStream(myoutputstream.toByteArray());
    125.             int amount;
    126.             while ((amount = inputstream.read(byteBuffer)) != -1) {
    127.                 outsocket.write(byteBuffer, 0, amount);
    128.             }
    129.             myoutputstream.flush();
    130.             myoutputstream.close();
    131.             tempSocket.close();                   
    132.         } catch (IOException e) {
    133.             e.printStackTrace();
    134.         }
    135.     }

    136. }
    复制代码
    二、PC服务器端
    ImageServer.java 用于显示图像,并且可以拍照
    1. public class ImageServer {        
    2.     public static ServerSocket ss = null;
    3.     
    4.     public static void main(String args[]) throws IOException{    
    5.             ss = new ServerSocket(6000);
    6.         
    7.         final ImageFrame frame = new ImageFrame(ss);
    8.         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    9.         frame.setVisible(true);
    10.        
    11.         while(true){
    12.                 frame.panel.getimage();
    13.             frame.repaint();
    14.         }        
    15.     }
    16.        
    17. }

    18. /** 
    19.     A frame with an image panel
    20. */
    21. @SuppressWarnings("serial")
    22. class ImageFrame extends JFrame{
    23.         public ImagePanel panel;
    24.         public JButton jb;
    25.    
    26.     public ImageFrame(ServerSocket ss){
    27.                // get screen dimensions              
    28.                Toolkit kit = Toolkit.getDefaultToolkit();
    29.         Dimension screenSize = kit.getScreenSize();
    30.         int screenHeight = screenSize.height;
    31.         int screenWidth = screenSize.width;

    32.         // center frame in screen
    33.         setTitle("ImageTest");
    34.         setLocation((screenWidth - DEFAULT_WIDTH) / 2, (screenHeight - DEFAULT_HEIGHT) / 2);
    35.         setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);

    36.         // add panel to frame
    37.         this.getContentPane().setLayout(null);
    38.         panel = new ImagePanel(ss);
    39.         panel.setSize(640,480);
    40.         panel.setLocation(0, 0);
    41.         add(panel);
    42.         jb = new JButton("拍照");
    43.         jb.setBounds(0,480,640,50);
    44.         add(jb);
    45.         saveimage saveaction = new saveimage(ss);
    46.         jb.addActionListener(saveaction);
    47.     }

    48.     public static final int DEFAULT_WIDTH = 640;
    49.     public static final int DEFAULT_HEIGHT = 560;  
    50. }

    51. /**
    52.    A panel that displays a tiled image
    53. */
    54. @SuppressWarnings("serial")
    55. class ImagePanel extends JPanel {     
    56.     private ServerSocket ss;
    57.     private Image image;
    58.     private InputStream ins;
    59.          
    60.     public ImagePanel(ServerSocket ss) {  
    61.             this.ss = ss;
    62.     }
    63.     
    64.     public void getimage() throws IOException{
    65.             Socket s = this.ss.accept();
    66.         System.out.println("连接成功!");
    67.         this.ins = s.getInputStream();
    68.                 this.image = ImageIO.read(ins);
    69.                 this.ins.close();
    70.     }
    71.    
    72.     public void paintComponent(Graphics g){  
    73.         super.paintComponent(g);    
    74.         if (image == null) return;
    75.         g.drawImage(image, 0, 0, null);
    76.     }

    77. }

    78. class saveimage implements ActionListener {
    79.         RandomAccessFile inFile = null;
    80.         byte byteBuffer[] = new byte[1024];
    81.         InputStream ins;
    82.         private ServerSocket ss;
    83.         
    84.         public saveimage(ServerSocket ss){
    85.                 this.ss = ss;
    86.         }
    87.         
    88.         public void actionPerformed(ActionEvent event){
    89.         try {
    90.                         Socket s = ss.accept();
    91.                         ins = s.getInputStream();
    92.                         
    93.                         // 文件选择器以当前的目录打开
    94.                 JFileChooser jfc = new JFileChooser(".");
    95.                 jfc.showSaveDialog(new javax.swing.JFrame());
    96.                 // 获取当前的选择文件引用
    97.                 File savedFile = jfc.getSelectedFile();
    98.                 
    99.                 // 已经选择了文件
    100.                 if (savedFile != null) {
    101.                     // 读取文件的数据,可以每次以快的方式读取数据
    102.                     try {
    103.                                         inFile = new RandomAccessFile(savedFile, "rw");
    104.                                 } catch (FileNotFoundException e) {
    105.                                         e.printStackTrace();
    106.                                 }
    107.                 }

    108.             int amount;
    109.             while ((amount = ins.read(byteBuffer)) != -1) {
    110.                 inFile.write(byteBuffer, 0, amount);
    111.             }
    112.             inFile.close();
    113.             ins.close();
    114.             s.close();
    115.             javax.swing.JOptionPane.showMessageDialog(new javax.swing.JFrame(),
    116.                     "已接保存成功", "提示!", javax.swing.JOptionPane.PLAIN_MESSAGE);
    117.                 } catch (IOException e) {

    118.                         e.printStackTrace();
    119.                 }
    120.         }
    121. }
    复制代码
    开放源码如下(android我使用的是4.03的SDK,其它版本请自行更改。2.3.3版本以下的请注意initCamera()里被注释掉的哪一行)

    下载地址:http://download.csdn.net/detail/u014568921/8805009

  • 相关阅读:
    js加密
    sharepoint更新左侧列表的名字
    HTML转换JS
    Html空格字符代码:
    docker 与host互传文件
    Ubuntu里node命令出错,找不到
    docker查看运行容器详细信息
    docker保存容器的修改
    Docker容器中安装新的程序
    运行docker容器镜像
  • 原文地址:https://www.cnblogs.com/walccott/p/4957584.html
Copyright © 2011-2022 走看看