一直想在自己的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;@Overridepublic 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() {@Overridepublic 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() {@Overridepublic 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;@Overridepublic 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() {@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}@Overridepublic void surfaceCreated(SurfaceHolder holder) {initCamera(); // 打开摄像头}@Overridepublic 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;}@Overridepublic 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 screensetTitle("ImageTest");setLocation((screenWidth - DEFAULT_WIDTH) / 2, (screenHeight - DEFAULT_HEIGHT) / 2);setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);// add panel to framethis.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下实现一个手机监控摄像头相关推荐

  1. Android下创建一个输入法

    输入法是一种可以让用户输入文字的控件.Android提供了一套可扩展的输入法框架,使得应用程序可以让用户选择各种类型的输入法,比如基于触屏的键盘输入或者基于语音.当安装了特定输入法之后,用户即可在系统 ...

  2. Android下写一个永远不会被KILL掉的进程/服务

    Android 系统对于内存管理有自己的一套方法,为了保障系统有序稳定的运信,系统内部会自动分配,控制程序的内存使用.当系统觉得当前的资源非常有限的时候,为了保 证一些优先级高的程序能运行,就会杀掉一 ...

  3. Android下仿一个优化大师的流量悬浮控件

    在平台项目里面做过一个service弹出对话框的功能.这个也差不多. 下面说下这个demo的功能点吧: 1.使用service来弹出此悬浮框,从而保证能长期存在. 2.使用window manager ...

  4. Android下创建一个sqlite数据库

    在Android平台上,集成了一个嵌入式关系型数据库-SQLite,SQLite3支持 NULL.INTEGER.REAL(浮点数字).TEXT(字符串文本)和BLOB(二进制对象)数据类型,虽然它支 ...

  5. android 命令使用详解,Android下pm 命令详解

    作者:Sam (甄峰) sam_code@hotmail.com Sam在看相关PackageManager代码时,无意中发现Android 下提供一个pm命令,通常放在/system/bin/下.这 ...

  6. Android下pm命令详解

    在看相关PackageManager代码时,无意中发现Android 下提供一个pm命令,通常放在/system/bin/下.这个命令与Package有关,且非常实用.所以研究之. 0. Usage: ...

  7. 求助一个手机答题APP

    求助:想用Android studio做一个手机答题APP,可以离线刷题,只有单选题,多选题,判断题,试题在一个Excel文件里面有1000多道,APP最好可以顺序做题,随机做题,模拟考试,错题集等功 ...

  8. 一个Android下ping的简单工具类

    这是一个自己写的Android下的ping的简单工具类,主要是通过ping获取到返回字符串之后截取信息得到自己想要的数据.不多说,上源码 import java.io.BufferedReader; ...

  9. Android之自制一个(以假乱真的)山寨的手机QQ

    概述 当前中国最主流的及时通讯工具之一腾讯QQ,经历过这么多年的更迭,其代码繁杂度可想而知,我闲着没事,就仿造手机QQ的布局写了个山寨货,只是长得像QQ而已,肚子里还没装货,并没有实现那些繁杂的功能, ...

最新文章

  1. 简洁版利用Python写俄罗斯方块游戏
  2. 【c++】 类与对象
  3. RUNOOB python练习题27 递归逆向输出字符串
  4. 关于计算机类课程实验教学的思考
  5. 网络流 (网络流问题汇总)
  6. 判断是否是完全二叉树和是否为满二叉树
  7. Iocomp ActiveX/VCL 2021 绿色版
  8. GM505高斯计使用方法图解
  9. 2018 IEEE International Conference on Cyborg and Bionic Systems (CBS)国际会议的组织和参入感悟
  10. 组装三代番木瓜基因组——by Serenity Fang
  11. 矩阵论笔记(一) - 线性空间、线性子空间、矩阵的值域和核空间
  12. python --安装pylab
  13. @Transactional 详解 示例
  14. QUIC不可靠的数据报扩展(An Unreliable Datagram Extension to QUIC)
  15. 本地打印机获取以及文件打印 java
  16. 课改类毕业论文文献包含哪些?
  17. Spring Boot2 redis
  18. 一种修改MCU主频的方法:类观察者模式
  19. C语言-全排列-递归
  20. 数据库领域的四位图灵奖得主及启示

热门文章

  1. 煽情的儿子551=随笔
  2. java 下载文件模板
  3. MobileNet V2 论文笔记
  4. 兰州大学计算机专业复试流程,兰大计算机复试相关事宜
  5. 增广拍卖——二跳页下的拍卖机制探索
  6. html查看器是什么 wifi,wifi display是什么意思
  7. 过一遍HTML标签(三)
  8. Spring Security OAuth2 优雅的集成短信验证码登录以及第三方登录
  9. 【亲测成功】springboot中.yml没有spring的小叶子标志和项目中也没有spring绿色标志的解决办法
  10. Vue 前端下载 Excel