Android实现手机监控摄像头

Rose ·
更新时间:2024-11-10
· 221 次阅读

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

功能点:

1、Android和PC通过socket通信。

2、Android下Camera的使用。

看代码:

package com.wenix.androidcameramonitor; import android.app.Activity; import android.app.AlertDialog; import android.app.AlertDialog.Builder; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.os.Bundle; import android.view.Window; import android.view.WindowManager; import android.widget.EditText; import android.widget.TableLayout; public class GetIP extends Activity {     String ipname = null;     @Override     public void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);     // 设置全屏     requestWindowFeature(Window.FEATURE_NO_TITLE);     getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,         WindowManager.LayoutParams.FLAG_FULLSCREEN);     setContentView(R.layout.activity_main);     final Builder builder = new AlertDialog.Builder(this); // 定义一个AlertDialog.Builder对象     builder.setTitle("登录服务器对话框"); // 设置对话框的标题     // 装载/res/layout/login.xml界面布局     TableLayout loginForm = (TableLayout) getLayoutInflater().inflate(         R.layout.login, null);     final EditText iptext = (EditText) loginForm         .findViewById(R.id.ipedittext);     builder.setView(loginForm); // 设置对话框显示的View对象     // 为对话框设置一个“登录”按钮     builder.setPositiveButton("登录"     // 为按钮设置监听器         , new OnClickListener() {             @Override             public void onClick(DialogInterface dialog, int which) {             // 此处可执行登录处理             ipname = iptext.getText().toString().trim();             Bundle data = new Bundle();             data.putString("ipname", ipname);             Intent intent = new Intent(GetIP.this, MainActivity.class);             intent.putExtras(data);             startActivity(intent);             }         });     // 为对话框设置一个“取消”按钮     builder.setNegativeButton("取消", new OnClickListener() {         @Override         public void onClick(DialogInterface dialog, int which) {         // 取消登录,不做任何事情。         System.exit(1);         }     });     // 创建、并显示对话框     builder.create().show();     } }

获取ip后就跳转到MainActivity。

package com.wenix.androidcameramonitor; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; import android.app.Activity; import android.content.Intent; import android.graphics.ImageFormat; import android.graphics.Rect; import android.graphics.YuvImage; import android.hardware.Camera; import android.hardware.Camera.Size; import android.os.Bundle; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceHolder.Callback; import android.view.SurfaceView; import android.view.Window; import android.view.WindowManager; public class MainActivity extends Activity {     SurfaceView sView;     SurfaceHolder surfaceHolder;     int screenWidth, screenHeight;     Camera camera; // 定义系统所用的照相机     boolean isPreview = false; // 是否在浏览中     private String ipname;     @Override     public void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         // 设置全屏         requestWindowFeature(Window.FEATURE_NO_TITLE);         getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);         setContentView(R.layout.activity_main);         // 获取IP地址         Intent intent = getIntent();         Bundle data = intent.getExtras();         ipname = data.getString("ipname");         screenWidth = 640;         screenHeight = 480;         sView = (SurfaceView) findViewById(R.id.sView); // 获取界面中SurfaceView组件         surfaceHolder = sView.getHolder(); // 获得SurfaceView的SurfaceHolder         // 为surfaceHolder添加一个回调监听器         surfaceHolder.addCallback(new Callback() {             @Override             public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {             }             @Override             public void surfaceCreated(SurfaceHolder holder) {                 initCamera(); // 打开摄像头             }             @Override             public void surfaceDestroyed(SurfaceHolder holder) {                 // 如果camera不为null ,释放摄像头                 if (camera != null) {                     if (isPreview)                         camera.stopPreview();                     camera.release();                     camera = null;                 }                 System.exit(0);             }         });         // 设置该SurfaceView自己不维护缓冲         surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);     }     private void initCamera() {         if (!isPreview) {             camera = Camera.open();         }         if (camera != null && !isPreview) {             try {                 Camera.Parameters parameters = camera.getParameters();                 parameters.setPreviewSize(screenWidth, screenHeight); // 设置预览照片的大小                 parameters.setPreviewFpsRange(20, 30); // 每秒显示20~30帧                 parameters.setPictureFormat(ImageFormat.NV21); // 设置图片格式                 parameters.setPictureSize(screenWidth, screenHeight); // 设置照片的大小                 // camera.setParameters(parameters); // android2.3.3以后不需要此行代码                 camera.setPreviewDisplay(surfaceHolder); // 通过SurfaceView显示取景画面                 camera.setPreviewCallback(new StreamIt(ipname)); // 设置回调的类                 camera.startPreview(); // 开始预览                 camera.autoFocus(null); // 自动对焦             } catch (Exception e) {                 e.printStackTrace();             }             isPreview = true;         }     } } class StreamIt implements Camera.PreviewCallback {     private String ipname;     public StreamIt(String ipname) {         this.ipname = ipname;     }     @Override     public void onPreviewFrame(byte[] data, Camera camera) {         Size size = camera.getParameters().getPreviewSize();         try {             // 调用image.compressToJpeg()将YUV格式图像数据data转为jpg格式             YuvImage image = new YuvImage(data, ImageFormat.NV21, size.width, size.height, null);             if (image != null) {                 ByteArrayOutputStream outstream = new ByteArrayOutputStream();                 image.compressToJpeg(new Rect(0, 0, size.width, size.height), 80, outstream);                 outstream.flush();                 // 启用线程将图像数据发送出去                 Thread th = new MyThread(outstream, ipname);                 th.start();             }         } catch (Exception ex) {             Log.e("Sys", "Error:" + ex.getMessage());         }     } } class MyThread extends Thread {     private byte byteBuffer[] = new byte[1024];     private OutputStream outsocket;     private ByteArrayOutputStream myoutputstream;     private String ipname;     public MyThread(ByteArrayOutputStream myoutputstream, String ipname) {         this.myoutputstream = myoutputstream;         this.ipname = ipname;         try {             myoutputstream.close();         } catch (IOException e) {             e.printStackTrace();         }     }     public void run() {         try {             // 将图像数据通过Socket发送出去             Socket tempSocket = new Socket(ipname, 6000);             outsocket = tempSocket.getOutputStream();             ByteArrayInputStream inputstream = new ByteArrayInputStream(myoutputstream.toByteArray());             int amount;             while ((amount = inputstream.read(byteBuffer)) != -1) {                 outsocket.write(byteBuffer, 0, amount);             }             myoutputstream.flush();             myoutputstream.close();             tempSocket.close();         } catch (IOException e) {             e.printStackTrace();         }     } }

这样就打开了socket,然后把camera获取的数据发送到PC端。

PC端代码:

package com.wenix; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Image; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.ServerSocket; import java.net.Socket; import javax.imageio.ImageIO; import javax.swing.JButton; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JPanel; public class ImageServer {             public static ServerSocket ss = null;     public static void main(String args[]) throws IOException{                 ss = new ServerSocket(6000);         final ImageFrame frame = new ImageFrame(ss);         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);         frame.setVisible(true);         while(true){                 frame.panel.getimage();             frame.repaint();         }             } } /**      A frame with an image panel */ @SuppressWarnings("serial") class ImageFrame extends JFrame{         public ImagePanel panel;         public JButton jb;     public ImageFrame(ServerSocket ss){                // get screen dimensions                              Toolkit kit = Toolkit.getDefaultToolkit();         Dimension screenSize = kit.getScreenSize();         int screenHeight = screenSize.height;         int screenWidth = screenSize.width;         // center frame in screen         setTitle("ImageTest");         setLocation((screenWidth - DEFAULT_WIDTH) / 2, (screenHeight - DEFAULT_HEIGHT) / 2);         setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);         // add panel to frame         this.getContentPane().setLayout(null);         panel = new ImagePanel(ss);         panel.setSize(640,480);         panel.setLocation(0, 0);         add(panel);         jb = new JButton("拍照");         jb.setBounds(0,480,640,50);         add(jb);         saveimage saveaction = new saveimage(ss);         jb.addActionListener(saveaction);     }     public static final int DEFAULT_WIDTH = 640;     public static final int DEFAULT_HEIGHT = 560;   } /**    A panel that displays a tiled image */ @SuppressWarnings("serial") class ImagePanel extends JPanel {          private ServerSocket ss;     private Image image;     private InputStream ins;     public ImagePanel(ServerSocket ss) {               this.ss = ss;     }     public void getimage() throws IOException{             Socket s = this.ss.accept();         System.out.println("连接成功!");         this.ins = s.getInputStream();                 this.image = ImageIO.read(ins);                 this.ins.close();     }     public void paintComponent(Graphics g){           super.paintComponent(g);             if (image == null) return;         g.drawImage(image, 0, 0, null);     } } class saveimage implements ActionListener {         RandomAccessFile inFile = null;         byte byteBuffer[] = new byte[1024];         InputStream ins;         private ServerSocket ss;         public saveimage(ServerSocket ss){                 this.ss = ss;         }         public void actionPerformed(ActionEvent event){         try {                         Socket s = ss.accept();                         ins = s.getInputStream();                         // 文件选择器以当前的目录打开                 JFileChooser jfc = new JFileChooser(".");                 jfc.showSaveDialog(new javax.swing.JFrame());                 // 获取当前的选择文件引用                 File savedFile = jfc.getSelectedFile();                 // 已经选择了文件                 if (savedFile != null) {                     // 读取文件的数据,可以每次以快的方式读取数据                     try {                                         inFile = new RandomAccessFile(savedFile, "rw");                                 } catch (FileNotFoundException e) {                                         e.printStackTrace();                                 }                 }             int amount;             while ((amount = ins.read(byteBuffer)) != -1) {                 inFile.write(byteBuffer, 0, amount);             }             inFile.close();             ins.close();             s.close();             javax.swing.JOptionPane.showMessageDialog(new javax.swing.JFrame(),                     "已接保存成功", "提示!", javax.swing.JOptionPane.PLAIN_MESSAGE);                 } catch (IOException e) {                         e.printStackTrace();                 }         } }

运行结果如下:

手机视频:

pc端视频:

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

接下来要完善的地方:

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

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

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



监控 摄像 摄像头 手机 Android

需要 登录 后方可回复, 如果你还没有账号请 注册新账号