简单的工作室

Android下实现一个手机监控摄像头

时间:2015-06-25 00:21来源:未知 作者:简单的工作室 点击:
一直想在自己的Android手机上实现一个手机监控摄像头功能。今天逛论坛,看到一个例子,于是做了出来,留着以后完善。 功能点: 1。Android和PC通过socket通信。 2。Android下Camera的使用。 看代码: [java] view plaincopy package com.wenix.androidcameramonitor; import

一直想在自己的Android手机上实现一个手机监控摄像头功能。今天逛论坛,看到一个例子,于是做了出来,留着以后完善。

功能点:

1。Android和PC通过socket通信。

2。Android下Camera的使用。

看代码:


[java] view plaincopy
  1. package com.wenix.androidcameramonitor;  
  2.   
  3. import android.app.Activity;  
  4. import android.app.AlertDialog;  
  5. import android.app.AlertDialog.Builder;  
  6. import android.content.DialogInterface;  
  7. import android.content.DialogInterface.OnClickListener;  
  8. import android.content.Intent;  
  9. import android.os.Bundle;  
  10. import android.view.Window;  
  11. import android.view.WindowManager;  
  12. import android.widget.EditText;  
  13. import android.widget.TableLayout;  
  14.   
  15. public class GetIP extends Activity {  
  16.     String ipname = null;  
  17.   
  18.     @Override  
  19.     public void onCreate(Bundle savedInstanceState) {  
  20.     super.onCreate(savedInstanceState);  
  21.     // 设置全屏  
  22.     requestWindowFeature(Window.FEATURE_NO_TITLE);  
  23.     getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,  
  24.         WindowManager.LayoutParams.FLAG_FULLSCREEN);  
  25.     setContentView(R.layout.activity_main);  
  26.   
  27.     final Builder builder = new AlertDialog.Builder(this); // 定义一个AlertDialog.Builder对象  
  28.     builder.setTitle("登录服务器对话框"); // 设置对话框的标题  
  29.   
  30.     // 装载/res/layout/login.xml界面布局  
  31.     TableLayout loginForm = (TableLayout) getLayoutInflater().inflate(  
  32.         R.layout.login, null);  
  33.     final EditText iptext = (EditText) loginForm  
  34.         .findViewById(R.id.ipedittext);  
  35.     builder.setView(loginForm); // 设置对话框显示的View对象  
  36.     // 为对话框设置一个“登录”按钮  
  37.     builder.setPositiveButton("登录"  
  38.     // 为按钮设置监听器  
  39.         , new OnClickListener() {  
  40.             @Override  
  41.             public void onClick(DialogInterface dialog, int which) {  
  42.             // 此处可执行登录处理  
  43.             ipname = iptext.getText().toString().trim();  
  44.             Bundle data = new Bundle();  
  45.             data.putString("ipname", ipname);  
  46.             Intent intent = new Intent(GetIP.this, MainActivity.class);  
  47.             intent.putExtras(data);  
  48.             startActivity(intent);  
  49.             }  
  50.         });  
  51.     // 为对话框设置一个“取消”按钮  
  52.     builder.setNegativeButton("取消"new OnClickListener() {  
  53.         @Override  
  54.         public void onClick(DialogInterface dialog, int which) {  
  55.         // 取消登录,不做任何事情。  
  56.         System.exit(1);  
  57.         }  
  58.     });  
  59.     // 创建、并显示对话框  
  60.     builder.create().show();  
  61.     }  
  62. }  

获取ip后就跳转到MainActivity。



[java] view plaincopy
  1. package com.wenix.androidcameramonitor;  
  2.   
  3. import java.io.ByteArrayInputStream;  
  4. import java.io.ByteArrayOutputStream;  
  5. import java.io.IOException;  
  6. import java.io.OutputStream;  
  7. import java.net.Socket;  
  8.   
  9. import android.app.Activity;  
  10. import android.content.Intent;  
  11. import android.graphics.ImageFormat;  
  12. import android.graphics.Rect;  
  13. import android.graphics.YuvImage;  
  14. import android.hardware.Camera;  
  15. import android.hardware.Camera.Size;  
  16. import android.os.Bundle;  
  17. import android.util.Log;  
  18. import android.view.SurfaceHolder;  
  19. import android.view.SurfaceHolder.Callback;  
  20. import android.view.SurfaceView;  
  21. import android.view.Window;  
  22. import android.view.WindowManager;  
  23.   
  24. public class MainActivity extends Activity {  
  25.     SurfaceView sView;  
  26.     SurfaceHolder surfaceHolder;  
  27.     int screenWidth, screenHeight;  
  28.     Camera camera; // 定义系统所用的照相机  
  29.     boolean isPreview = false// 是否在浏览中  
  30.     private String ipname;  
  31.   
  32.     @Override  
  33.     public void onCreate(Bundle savedInstanceState) {  
  34.         super.onCreate(savedInstanceState);  
  35.         // 设置全屏  
  36.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  37.         getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);  
  38.         setContentView(R.layout.activity_main);  
  39.   
  40.         // 获取IP地址  
  41.         Intent intent = getIntent();  
  42.         Bundle data = intent.getExtras();  
  43.         ipname = data.getString("ipname");  
  44.   
  45.         screenWidth = 640;  
  46.         screenHeight = 480;  
  47.         sView = (SurfaceView) findViewById(R.id.sView); // 获取界面中SurfaceView组件  
  48.         surfaceHolder = sView.getHolder(); // 获得SurfaceView的SurfaceHolder  
  49.   
  50.         // 为surfaceHolder添加一个回调监听器  
  51.         surfaceHolder.addCallback(new Callback() {  
  52.             @Override  
  53.             public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {  
  54.             }  
  55.   
  56.             @Override  
  57.             public void surfaceCreated(SurfaceHolder holder) {  
  58.                 initCamera(); // 打开摄像头  
  59.             }  
  60.   
  61.             @Override  
  62.             public void surfaceDestroyed(SurfaceHolder holder) {  
  63.                 // 如果camera不为null ,释放摄像头  
  64.                 if (camera != null) {  
  65.                     if (isPreview)  
  66.                         camera.stopPreview();  
  67.                     camera.release();  
  68.                     camera = null;  
  69.                 }  
  70.                 System.exit(0);  
  71.             }  
  72.         });  
  73.         // 设置该SurfaceView自己不维护缓冲  
  74.         surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);  
  75.   
  76.     }  
  77.   
  78.     private void initCamera() {  
  79.         if (!isPreview) {  
  80.             camera = Camera.open();  
  81.         }  
  82.         if (camera != null && !isPreview) {  
  83.             try {  
  84.                 Camera.Parameters parameters = camera.getParameters();  
  85.                 parameters.setPreviewSize(screenWidth, screenHeight); // 设置预览照片的大小  
  86.                 parameters.setPreviewFpsRange(2030); // 每秒显示20~30帧  
  87.                 parameters.setPictureFormat(ImageFormat.NV21); // 设置图片格式  
  88.                 parameters.setPictureSize(screenWidth, screenHeight); // 设置照片的大小  
  89.                 // camera.setParameters(parameters); // android2.3.3以后不需要此行代码  
  90.                 camera.setPreviewDisplay(surfaceHolder); // 通过SurfaceView显示取景画面  
  91.                 camera.setPreviewCallback(new StreamIt(ipname)); // 设置回调的类  
  92.                 camera.startPreview(); // 开始预览  
  93.                 camera.autoFocus(null); // 自动对焦  
  94.             } catch (Exception e) {  
  95.                 e.printStackTrace();  
  96.             }  
  97.             isPreview = true;  
  98.         }  
  99.     }  
  100.   
  101. }  
  102.   
  103. class StreamIt implements Camera.PreviewCallback {  
  104.     private String ipname;  
  105.   
  106.     public StreamIt(String ipname) {  
  107.         this.ipname = ipname;  
  108.     }  
  109.   
  110.     @Override  
  111.     public void onPreviewFrame(byte[] data, Camera camera) {  
  112.         Size size = camera.getParameters().getPreviewSize();  
  113.         try {  
  114.             // 调用image.compressToJpeg()将YUV格式图像数据data转为jpg格式  
  115.             YuvImage image = new YuvImage(data, ImageFormat.NV21, size.width, size.height, null);  
  116.             if (image != null) {  
  117.                 ByteArrayOutputStream outstream = new ByteArrayOutputStream();  
  118.                 image.compressToJpeg(new Rect(00, size.width, size.height), 80, outstream);  
  119.                 outstream.flush();  
  120.                 // 启用线程将图像数据发送出去  
  121.                 Thread th = new MyThread(outstream, ipname);  
  122.                 th.start();  
  123.             }  
  124.         } catch (Exception ex) {  
  125.             Log.e("Sys""Error:" + ex.getMessage());  
  126.         }  
  127.     }  
  128. }  
  129.   
  130. class MyThread extends Thread {  
  131.     private byte byteBuffer[] = new byte[1024];  
  132.     private OutputStream outsocket;  
  133.     private ByteArrayOutputStream myoutputstream;  
  134.     private String ipname;  
  135.   
  136.     public MyThread(ByteArrayOutputStream myoutputstream, String ipname) {  
  137.         this.myoutputstream = myoutputstream;  
  138.         this.ipname = ipname;  
  139.         try {  
  140.             myoutputstream.close();  
  141.         } catch (IOException e) {  
  142.             e.printStackTrace();  
  143.         }  
  144.     }  
  145.   
  146.     public void run() {  
  147.         try {  
  148.             // 将图像数据通过Socket发送出去  
  149.             Socket tempSocket = new Socket(ipname, 6000);  
  150.             outsocket = tempSocket.getOutputStream();  
  151.             ByteArrayInputStream inputstream = new ByteArrayInputStream(myoutputstream.toByteArray());  
  152.             int amount;  
  153.             while ((amount = inputstream.read(byteBuffer)) != -1) {  
  154.                 outsocket.write(byteBuffer, 0, amount);  
  155.             }  
  156.             myoutputstream.flush();  
  157.             myoutputstream.close();  
  158.             tempSocket.close();  
  159.         } catch (IOException e) {  
  160.             e.printStackTrace();  
  161.         }  
  162.     }  
  163.   
  164. }  
这样就打开了socket,然后把camera获取的数据发送到PC端。


PC端代码:


[java] view plaincopy
  1. package com.wenix;  
  2.   
  3. import java.awt.Dimension;  
  4. import java.awt.Graphics;  
  5. import java.awt.Image;  
  6. import java.awt.Toolkit;  
  7. import java.awt.event.ActionEvent;  
  8. import java.awt.event.ActionListener;  
  9. import java.io.File;  
  10. import java.io.FileNotFoundException;  
  11. import java.io.IOException;  
  12. import java.io.InputStream;  
  13. import java.io.RandomAccessFile;  
  14. import java.net.ServerSocket;  
  15. import java.net.Socket;  
  16.   
  17. import javax.imageio.ImageIO;  
  18. import javax.swing.JButton;  
  19. import javax.swing.JFileChooser;  
  20. import javax.swing.JFrame;  
  21. import javax.swing.JPanel;  
  22.   
  23. public class ImageServer {          
  24.     public static ServerSocket ss = null;  
  25.       
  26.     public static void main(String args[]) throws IOException{      
  27.             ss = new ServerSocket(6000);  
  28.           
  29.         final ImageFrame frame = new ImageFrame(ss);  
  30.         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
  31.         frame.setVisible(true);  
  32.          
  33.         while(true){  
  34.                 frame.panel.getimage();  
  35.             frame.repaint();  
  36.         }          
  37.     }  
  38.          
  39. }  
  40.   
  41. /**  
  42.     A frame with an image panel 
  43. */  
  44. @SuppressWarnings("serial")  
  45. class ImageFrame extends JFrame{  
  46.         public ImagePanel panel;  
  47.         public JButton jb;  
  48.      
  49.     public ImageFrame(ServerSocket ss){  
  50.                // get screen dimensions                
  51.                Toolkit kit = Toolkit.getDefaultToolkit();  
  52.         Dimension screenSize = kit.getScreenSize();  
  53.         int screenHeight = screenSize.height;  
  54.         int screenWidth = screenSize.width;  
  55.   
  56.         // center frame in screen  
  57.         setTitle("ImageTest");  
  58.         setLocation((screenWidth - DEFAULT_WIDTH) / 2, (screenHeight - DEFAULT_HEIGHT) / 2);  
  59.         setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);  
  60.   
  61.         // add panel to frame  
  62.         this.getContentPane().setLayout(null);  
  63.         panel = new ImagePanel(ss);  
  64.         panel.setSize(640,480);  
  65.         panel.setLocation(00);  
  66.         add(panel);  
  67.         jb = new JButton("拍照");  
  68.         jb.setBounds(0,480,640,50);  
  69.         add(jb);  
  70.         saveimage saveaction = new saveimage(ss);  
  71.         jb.addActionListener(saveaction);  
  72.     }  
  73.   
  74.     public static final int DEFAULT_WIDTH = 640;  
  75.     public static final int DEFAULT_HEIGHT = 560;    
  76. }  
  77.   
  78. /** 
  79.    A panel that displays a tiled image 
  80. */  
  81. @SuppressWarnings("serial")  
  82. class ImagePanel extends JPanel {       
  83.     private ServerSocket ss;  
  84.     private Image image;  
  85.     private InputStream ins;  
  86.            
  87.     public ImagePanel(ServerSocket ss) {    
  88.             this.ss = ss;  
  89.     }  
  90.       
  91.     public void getimage() throws IOException{  
  92.             Socket s = this.ss.accept();  
  93.         System.out.println("连接成功!");  
  94.         this.ins = s.getInputStream();  
  95.                 this.image = ImageIO.read(ins);  
  96.                 this.ins.close();  
  97.     }  
  98.      
  99.     public void paintComponent(Graphics g){    
  100.         super.paintComponent(g);      
  101.         if (image == nullreturn;  
  102.         g.drawImage(image, 00null);  
  103.     }  
  104.   
  105. }  
  106.   
  107. class saveimage implements ActionListener {  
  108.         RandomAccessFile inFile = null;  
  109.         byte byteBuffer[] = new byte[1024];  
  110.         InputStream ins;  
  111.         private ServerSocket ss;  
  112.           
  113.         public saveimage(ServerSocket ss){  
  114.                 this.ss = ss;  
  115.         }  
  116.           
  117.         public void actionPerformed(ActionEvent event){  
  118.         try {  
  119.                         Socket s = ss.accept();  
  120.                         ins = s.getInputStream();  
  121.                           
  122.                         // 文件选择器以当前的目录打开  
  123.                 JFileChooser jfc = new JFileChooser(".");  
  124.                 jfc.showSaveDialog(new javax.swing.JFrame());  
  125.                 // 获取当前的选择文件引用  
  126.                 File savedFile = jfc.getSelectedFile();  
  127.                   
  128.                 // 已经选择了文件  
  129.                 if (savedFile != null) {  
  130.                     // 读取文件的数据,可以每次以快的方式读取数据  
  131.                     try {  
  132.                                         inFile = new RandomAccessFile(savedFile, "rw");  
  133.                                 } catch (FileNotFoundException e) {  
  134.                                         e.printStackTrace();  
  135.                                 }  
  136.                 }  
  137.   
  138.             int amount;  
  139.             while ((amount = ins.read(byteBuffer)) != -1) {  
  140.                 inFile.write(byteBuffer, 0, amount);  
  141.             }  
  142.             inFile.close();  
  143.             ins.close();  
  144.             s.close();  
  145.             javax.swing.JOptionPane.showMessageDialog(new javax.swing.JFrame(),  
  146.                     "已接保存成功""提示!", javax.swing.JOptionPane.PLAIN_MESSAGE);  
  147.                 } catch (IOException e) {  
  148.   
  149.                         e.printStackTrace();  
  150.                 }  
  151.         }  
  152. }  

运行结果如下:



手机视频:

pc端视频:

可以看到视频数据已经上传到了PC端。

接下来要完善的地方:

1。Android端可以提供一个Url,然后PC端使用浏览器来浏览。

2。PC端添加视频录制功能。

3。添加图像检测功能,比如运动物体检测等,这样就可以扩展为监控摄像头了。


源代码下载

MyAndroidTest_75_ZXingSample摄像头修改源码测试

(责任编辑:简单的工作室)
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片