`
king_tt
  • 浏览: 2101630 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

[Android实例] 基于android的远程视频监控系统

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

系统代码如下:
一、android手机客户端

(1)AndroidManifest.xml文件。添加camera和socket权限,并设置了程序开始执行的activity

  1. <font size="3"><?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="<a href="http://schemas.android.com/apk/res/android">http://schemas.android.com/apk/res/android</a>"
  3. package="org.wanghai.CameraTest"
  4. android:versionCode="1"
  5. android:versionName="1.0" >
  6. <uses-sdk android:minSdkVersion="15" />

  7. <!-- 授予程序使用摄像头的权限 -->
  8. <uses-permission android:name="android.permission.CAMERA" />
  9. <uses-feature android:name="android.hardware.camera" />
  10. <uses-feature android:name="android.hardware.camera.autofocus" />
  11. <uses-permission android:name="android.permission.INTERNET"/>
  12. <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/>
  13. <uses-permission android:name="android.permission.RESTART_PACKAGES"/>
  14. <application
  15. android:icon="@drawable/ic_launcher"
  16. android:label="@string/app_name" >

  17. <activity
  18. android:name=".GetIP"
  19. android:screenOrientation="landscape"
  20. android:label="@string/app_name" >
  21. <intent-filter>
  22. <action android:name="android.intent.action.MAIN" />
  23. <category android:name="android.intent.category.LAUNCHER" />
  24. </intent-filter>
  25. </activity>
  26. <activity
  27. android:name=".CameraTest"
  28. android:screenOrientation="landscape"
  29. android:label="@string/app_name" >[/size][/size]
  30. </activity>

  31. </application>
  32. </manifest>
  33. </font>
复制代码
(2)main.xml 设置surfaceview用于摄像头采集图像的预览

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="<a href="http://schemas.android.com/apk/res/android">http://schemas.android.com/apk/res/android</a>"
  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="<a href="http://schemas.android.com/apk/res/android">http://schemas.android.com/apk/res/android</a>"
  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. final Builder builder = new AlertDialog.Builder(this); //定义一个AlertDialog.Builder对象
  11. builder.setTitle("登录服务器对话框"); // 设置对话框的标题

  12. //装载/res/layout/login.xml界面布局
  13. TableLayout loginForm = (TableLayout)getLayoutInflater().inflate( R.layout.login, null);
  14. final EditText iptext = (EditText)loginForm.findViewById(R.id.ipedittext);
  15. builder.setView(loginForm); // 设置对话框显示的View对象
  16. // 为对话框设置一个“登录”按钮
  17. builder.setPositiveButton("登录"
  18. // 为按钮设置监听器
  19. , new OnClickListener() {
  20. @Override
  21. public void onClick(DialogInterface dialog, int which) {
  22. //此处可执行登录处理
  23. ipname = iptext.getText().toString().trim();
  24. Bundle data = new Bundle();
  25. data.putString("ipname",ipname);
  26. Intent intent = new Intent(GetIP.this,CameraTest.class);
  27. intent.putExtras(data);
  28. startActivity(intent);
  29. }
  30. });
  31. // 为对话框设置一个“取消”按钮
  32. builder.setNegativeButton("取消"
  33. ,new OnClickListener()
  34. {
  35. @Override
  36. public void onClick(DialogInterface dialog, int which)
  37. {
  38. //取消登录,不做任何事情。
  39. System.exit(1);
  40. }
  41. });
  42. //创建、并显示对话框
  43. builder.create().show();
  44. }
  45. }

复制代码

(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. // 获取IP地址
  17. Intent intent = getIntent();
  18. Bundle data = intent.getExtras();
  19. ipname = data.getString("ipname");

  20. screenWidth = 640;
  21. screenHeight = 480;
  22. sView = (SurfaceView) findViewById(R.id.sView); // 获取界面中SurfaceView组件
  23. surfaceHolder = sView.getHolder(); // 获得SurfaceView的SurfaceHolder

  24. // 为surfaceHolder添加一个回调监听器
  25. surfaceHolder.addCallback(new Callback() {
  26. @Override
  27. public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {
  28. }
  29. @Override
  30. public void surfaceCreated(SurfaceHolder holder) {
  31. initCamera(); // 打开摄像头
  32. }
  33. @Override
  34. public void surfaceDestroyed(SurfaceHolder holder) {
  35. // 如果camera不为null ,释放摄像头
  36. if (camera != null) {
  37. if (isPreview)
  38. camera.stopPreview();
  39. camera.release();
  40. camera = null;
  41. }
  42. System.exit(0);
  43. }
  44. });
  45. // 设置该SurfaceView自己不维护缓冲
  46. surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

  47. }

  48. private void initCamera() {
  49. if (!isPreview) {
  50. camera = Camera.open();
  51. }
  52. if (camera != null && !isPreview) {
  53. try{
  54. Camera.Parameters parameters = camera.getParameters();
  55. parameters.setPreviewSize(screenWidth, screenHeight); // 设置预览照片的大小
  56. parameters.setPreviewFpsRange(20,30); // 每秒显示20~30帧
  57. parameters.setPictureFormat(ImageFormat.NV21); // 设置图片格式
  58. parameters.setPictureSize(screenWidth, screenHeight); // 设置照片的大小
  59. //camera.setParameters(parameters); // android2.3.3以后不需要此行代码
  60. camera.setPreviewDisplay(surfaceHolder); // 通过SurfaceView显示取景画面
  61. camera.setPreviewCallback(new StreamIt(ipname)); // 设置回调的类
  62. camera.startPreview(); // 开始预览
  63. camera.autoFocus(null); // 自动对焦
  64. } catch (Exception e) {
  65. e.printStackTrace();
  66. }
  67. isPreview = true;
  68. }
  69. }

  70. }
  71. class StreamIt implements Camera.PreviewCallback {
  72. private String ipname;
  73. public StreamIt(String ipname){
  74. this.ipname = ipname;
  75. }

  76. @Override
  77. public void onPreviewFrame(byte[] data, Camera camera) {
  78. Size size = camera.getParameters().getPreviewSize();
  79. try{
  80. //调用image.compressToJpeg()将YUV格式图像数据data转为jpg格式
  81. YuvImage image = new YuvImage(data, ImageFormat.NV21, size.width, size.height, null);
  82. if(image!=null){
  83. ByteArrayOutputStream outstream = new ByteArrayOutputStream();
  84. image.compressToJpeg(new Rect(0, 0, size.width, size.height), 80, outstream);
  85. outstream.flush();
  86. //启用线程将图像数据发送出去
  87. Thread th = new MyThread(outstream,ipname);
  88. th.start();
  89. }
  90. }catch(Exception ex){
  91. Log.e("Sys","Error:"+ex.getMessage());
  92. }
  93. }
  94. }

  95. class MyThread extends Thread{
  96. private byte byteBuffer[] = new byte[1024];
  97. private OutputStream outsocket;
  98. private ByteArrayOutputStream myoutputstream;
  99. private String ipname;

  100. public MyThread(ByteArrayOutputStream myoutputstream,String ipname){
  101. this.myoutputstream = myoutputstream;
  102. this.ipname = ipname;
  103. try {
  104. myoutputstream.close();
  105. } catch (IOException e) {
  106. e.printStackTrace();
  107. }
  108. }

  109. public void run() {
  110. try{
  111. //将图像数据通过Socket发送出去
  112. Socket tempSocket = new Socket(ipname, 6000);
  113. outsocket = tempSocket.getOutputStream();
  114. ByteArrayInputStream inputstream = new ByteArrayInputStream(myoutputstream.toByteArray());
  115. int amount;
  116. while ((amount = inputstream.read(byteBuffer)) != -1) {
  117. outsocket.write(byteBuffer, 0, amount);
  118. }
  119. myoutputstream.flush();
  120. myoutputstream.close();
  121. tempSocket.close();
  122. } catch (IOException e) {
  123. e.printStackTrace();
  124. }
  125. }
  126. }

复制代码

二、PC服务器端
ImageServer.java 用于显示图像,并且可以拍照


  1. public class ImageServer {
  2. public static ServerSocket ss = null;

  3. public static void main(String args[]) throws IOException{
  4. ss = new ServerSocket(6000);

  5. final ImageFrame frame = new ImageFrame(ss);
  6. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  7. frame.setVisible(true);

  8. while(true){
  9. frame.panel.getimage();
  10. frame.repaint();
  11. }
  12. }

  13. }
  14. /**
  15. A frame with an image panel
  16. */
  17. @SuppressWarnings("serial")
  18. class ImageFrame extends JFrame{
  19. public ImagePanel panel;
  20. public JButton jb;

  21. public ImageFrame(ServerSocket ss){
  22. // get screen dimensions
  23. Toolkit kit = Toolkit.getDefaultToolkit();
  24. Dimension screenSize = kit.getScreenSize();
  25. int screenHeight = screenSize.height;
  26. int screenWidth = screenSize.width;
  27. // center frame in screen
  28. setTitle("ImageTest");
  29. setLocation((screenWidth - DEFAULT_WIDTH) / 2, (screenHeight - DEFAULT_HEIGHT) / 2);
  30. setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
  31. // add panel to frame
  32. this.getContentPane().setLayout(null);
  33. panel = new ImagePanel(ss);
  34. panel.setSize(640,480);
  35. panel.setLocation(0, 0);
  36. add(panel);
  37. jb = new JButton("拍照");
  38. jb.setBounds(0,480,640,50);
  39. add(jb);
  40. saveimage saveaction = new saveimage(ss);
  41. jb.addActionListener(saveaction);
  42. }
  43. public static final int DEFAULT_WIDTH = 640;
  44. public static final int DEFAULT_HEIGHT = 560;
  45. }
  46. /**
  47. A panel that displays a tiled image
  48. */
  49. @SuppressWarnings("serial")
  50. class ImagePanel extends JPanel {
  51. private ServerSocket ss;
  52. private Image image;
  53. private InputStream ins;

  54. public ImagePanel(ServerSocket ss) {
  55. this.ss = ss;
  56. }

  57. public void getimage() throws IOException{
  58. Socket s = this.ss.accept();
  59. System.out.println("连接成功!");
  60. this.ins = s.getInputStream();
  61. this.image = ImageIO.read(ins);
  62. this.ins.close();
  63. }

  64. public void paintComponent(Graphics g){
  65. super.paintComponent(g);
  66. if (image == null) return;
  67. g.drawImage(image, 0, 0, null);
  68. }
  69. }
  70. class saveimage implements ActionListener {
  71. RandomAccessFile inFile = null;
  72. byte byteBuffer[] = new byte[1024];
  73. InputStream ins;
  74. private ServerSocket ss;

  75. public saveimage(ServerSocket ss){
  76. this.ss = ss;
  77. }

  78. public void actionPerformed(ActionEvent event){
  79. try {
  80. Socket s = ss.accept();
  81. ins = s.getInputStream();

  82. // 文件选择器以当前的目录打开
  83. JFileChooser jfc = new JFileChooser(".");
  84. jfc.showSaveDialog(new javax.swing.JFrame());
  85. // 获取当前的选择文件引用
  86. File savedFile = jfc.getSelectedFile();

  87. // 已经选择了文件
  88. if (savedFile != null) {
  89. // 读取文件的数据,可以每次以快的方式读取数据
  90. try {
  91. inFile = new RandomAccessFile(savedFile, "rw");
  92. } catch (FileNotFoundException e) {
  93. e.printStackTrace();
  94. }
  95. }
  96. int amount;
  97. while ((amount = ins.read(byteBuffer)) != -1) {
  98. inFile.write(byteBuffer, 0, amount);
  99. }
  100. inFile.close();
  101. ins.close();
  102. s.close();
  103. javax.swing.JOptionPane.showMessageDialog(new javax.swing.JFrame(),
  104. "已接保存成功", "提示!", javax.swing.JOptionPane.PLAIN_MESSAGE);
  105. } catch (IOException e) {[/size]
  106. e.printStackTrace();
  107. }
  108. }
  109. }

复制代码

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

eoeandroid 推荐:

Android 远程视频监控程序源码
http://www.eoeandroid.com/thread-173116-1-1.html

分享到:
评论

相关推荐

    android视频监控实例技术细节略解

    1、系统结构 2、V4L2驱动 3、mjpg-streamer 4、UI设计 5、背景设置 6、gridview和gridItem 7、sqlite 8、activity和intent 9、线程 10、HttpURLConnection读取远程JPEG图像并显示 11、socket从远端获取XML...

    android 开发实例

    7 、多媒体播放器(Android Media Player) 8、短信语音播报(Speak Message Service) 9、手机远程监控(Cam Monitor) 10、贪吃蛇游戏(Snake) (android development example 1, photo viewer (Picture Viewer) 2...

    Android 9种实用程序源码实例

    Android 9种实用程序源码实例 , 有兴趣的下载一起学习吧!! 1、 图片浏览器(Picture Viewer) 2 、文件浏览器(File Browser) 3 、通讯录(Contact) ...4 、任务管理器(Task ...9、手机远程监控(Cam Monitor)

    使用Android GPS监控别人行踪的测试实例

    一个Android GPS定位的应用实例,在Android智能机中监控别人行踪,一般这是隐私,不允许这样跟踪别人行踪,除非是有为照顾筷家人而开通此种应用,请不要干违法的事情。在Google Search的Google.java中,有杀不死的...

    一个使用AndroidApp来进行温室大棚控制系统实例

    我只是实现了布局部分,并没有功能部分,布局部分分为几个方面:温湿度的折线图显示、对大棚内的遮阳板、排风扇、水泵等设备进行远程控制、设置大棚内温湿条件监控、还有一个视频监控,不过这个例子的初衷是好的,...

    android应用程序实例

    1、 图片浏览器(Picture Viewer) 2 、文件浏览器(File Browser) 3 、通讯录(Contact) 4 、任务管理器(Task Manager) 5 、音乐播放器(Rock ...9、手机远程监控(Cam Monitor) 10、贪吃蛇游戏(Snake)

    音视频编码解码资料(花钱购买)

    |--------- 基于嵌入式Linux的远程网络视频监控系统 |--------- 基于linux_V4L视频采集摄像程序 |--------- 基于Linux的视频传输系统(完整方案) |---------嵌入式Linux应用开发完全手册视频源码 |---------...

    十个经典的android案例源码

    android移动开发案例详解, 有十几个案例,这是其中的几个案例源码: 1 图片浏览器 2 文件浏览器 3 通讯录 4 任务管理器 5 音乐播放器 6 天气预报 7 多媒体播放器 8短信语音播报 9手机远程监控 12贪吃蛇游戏

    JAVA上百实例源码以及开源项目源代码

    2个目标文件,FTP的目标是:(1)提高文件的共享性(计算机程序和/或数据),(2)鼓励间接地(通过程序)使用远程计算机,(3)保护用户因主机之间的文件存储系统导致的变化,(4)为了可靠和高效地传输,虽然用户...

    JAVA上百实例源码以及开源项目

    2个目标文件,FTP的目标是:(1)提高文件的共享性(计算机程序和/或数据),(2)鼓励间接地(通过程序)使用远程计算机,(3)保护用户因主机之间的文件存储系统导致的变化,(4)为了可靠和高效地传输,虽然用户...

    Catherine:Java Android App获取后端数据以显示和绘制所有统计信息

    该应用程序是远程监控系统的客户端,基于人员计数器系统,该应用程序显示云系统处理的统计信息。 目前,该应用程序仅显示具有图形用户数量,但是其架构允许升级以处理多个传感器实例,单点登录,对语言,小部件,...

    java开源包1

    开发它是用于在UTF-8 Oracle实例中使用ASCII编码的Oracle 数据库中来正确的传输非ASCII字符。 Java模板语言 Beetl Beetl,是Bee Template Language的缩写,它绝不是简单的另外一种模板引擎,而是新一代的模板引擎,...

    java开源包2

    开发它是用于在UTF-8 Oracle实例中使用ASCII编码的Oracle 数据库中来正确的传输非ASCII字符。 Java模板语言 Beetl Beetl,是Bee Template Language的缩写,它绝不是简单的另外一种模板引擎,而是新一代的模板引擎,...

    java开源包3

    开发它是用于在UTF-8 Oracle实例中使用ASCII编码的Oracle 数据库中来正确的传输非ASCII字符。 Java模板语言 Beetl Beetl,是Bee Template Language的缩写,它绝不是简单的另外一种模板引擎,而是新一代的模板引擎,...

    java开源包6

    开发它是用于在UTF-8 Oracle实例中使用ASCII编码的Oracle 数据库中来正确的传输非ASCII字符。 Java模板语言 Beetl Beetl,是Bee Template Language的缩写,它绝不是简单的另外一种模板引擎,而是新一代的模板引擎,...

    java开源包5

    开发它是用于在UTF-8 Oracle实例中使用ASCII编码的Oracle 数据库中来正确的传输非ASCII字符。 Java模板语言 Beetl Beetl,是Bee Template Language的缩写,它绝不是简单的另外一种模板引擎,而是新一代的模板引擎,...

    java开源包10

    开发它是用于在UTF-8 Oracle实例中使用ASCII编码的Oracle 数据库中来正确的传输非ASCII字符。 Java模板语言 Beetl Beetl,是Bee Template Language的缩写,它绝不是简单的另外一种模板引擎,而是新一代的模板引擎,...

    java开源包8

    开发它是用于在UTF-8 Oracle实例中使用ASCII编码的Oracle 数据库中来正确的传输非ASCII字符。 Java模板语言 Beetl Beetl,是Bee Template Language的缩写,它绝不是简单的另外一种模板引擎,而是新一代的模板引擎,...

Global site tag (gtag.js) - Google Analytics