http://www.cnblogs.com/feifei1010/archive/2012/08/31/2664939.html

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

(PS。刚学android和java不久很多东西还不懂,高手若是知道哪些地方可以继续优化的话还请多多指点下啊)

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

[html]view plaincopy
  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <manifestxmlns:android="http://schemas.android.com/apk/res/android"
  3. package="org.wanghai.CameraTest"
  4. android:versionCode="1"
  5. android:versionName="1.0">
  6. <uses-sdkandroid:minSdkVersion="15"/>
  7. <!--授予程序使用摄像头的权限-->
  8. <uses-permissionandroid:name="android.permission.CAMERA"/>
  9. <uses-featureandroid:name="android.hardware.camera"/>
  10. <uses-featureandroid:name="android.hardware.camera.autofocus"/>
  11. <uses-permissionandroid:name="android.permission.INTERNET"/>
  12. <uses-permissionandroid:name="android.permission.KILL_BACKGROUND_PROCESSES"/>
  13. <uses-permissionandroid: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. <actionandroid:name="android.intent.action.MAIN"/>
  23. <categoryandroid: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">
  30. </activity>
  31. </application>
  32. </manifest>

(2)main.xml 设置surfaceview用于摄像头采集图像的预览

[java]view plaincopy
  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <LinearLayoutxmlns: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

[html]view plaincopy
  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <TableLayoutxmlns: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传递

[java]view plaincopy
  1. publicclassGetIPextendsActivity{
  2. Stringipname=null;
  3. @Override
  4. publicvoidonCreate(BundlesavedInstanceState){
  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. finalBuilderbuilder=newAlertDialog.Builder(this);//定义一个AlertDialog.Builder对象
  11. builder.setTitle("登录服务器对话框");//设置对话框的标题
  12. //装载/res/layout/login.xml界面布局
  13. TableLayoutloginForm=(TableLayout)getLayoutInflater().inflate(R.layout.login,null);
  14. finalEditTextiptext=(EditText)loginForm.findViewById(R.id.ipedittext);
  15. builder.setView(loginForm);//设置对话框显示的View对象
  16. //为对话框设置一个“登录”按钮
  17. builder.setPositiveButton("登录"
  18. //为按钮设置监听器
  19. ,newOnClickListener(){
  20. @Override
  21. publicvoidonClick(DialogInterfacedialog,intwhich){
  22. //此处可执行登录处理
  23. ipname=iptext.getText().toString().trim();
  24. Bundledata=newBundle();
  25. data.putString("ipname",ipname);
  26. Intentintent=newIntent(GetIP.this,CameraTest.class);
  27. intent.putExtras(data);
  28. startActivity(intent);
  29. }
  30. });
  31. //为对话框设置一个“取消”按钮
  32. builder.setNegativeButton("取消"
  33. ,newOnClickListener()
  34. {
  35. @Override
  36. publicvoidonClick(DialogInterfacedialog,intwhich)
  37. {
  38. //取消登录,不做任何事情。
  39. System.exit(1);
  40. }
  41. });
  42. //创建、并显示对话框
  43. builder.create().show();
  44. }
  45. }

(5)CameraTest.java 程序主体。设置PreviewCallback后,每当一帧图像数据采集完成后将调用PreviewCallback的onPreviewFrame函数。在这里我们将YUV格式数据转为jpg,再启用线程将数据通过socket发送出去。

[java]view plaincopy
  1. publicclassCameraTestextendsActivity{
  2. SurfaceViewsView;
  3. SurfaceHoldersurfaceHolder;
  4. intscreenWidth,screenHeight;
  5. Cameracamera;//定义系统所用的照相机
  6. booleanisPreview=false;//是否在浏览中
  7. privateStringipname;
  8. @SuppressWarnings("deprecation")
  9. @Override
  10. publicvoidonCreate(BundlesavedInstanceState){
  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. Intentintent=getIntent();
  18. Bundledata=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(newCallback(){
  26. @Override
  27. publicvoidsurfaceChanged(SurfaceHolderholder,intformat,intwidth,intheight){
  28. }
  29. @Override
  30. publicvoidsurfaceCreated(SurfaceHolderholder){
  31. initCamera();//打开摄像头
  32. }
  33. @Override
  34. publicvoidsurfaceDestroyed(SurfaceHolderholder){
  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. privatevoidinitCamera(){
  49. if(!isPreview){
  50. camera=Camera.open();
  51. }
  52. if(camera!=null&&!isPreview){
  53. try{
  54. Camera.Parametersparameters=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(newStreamIt(ipname));//设置回调的类
  62. camera.startPreview();//开始预览
  63. camera.autoFocus(null);//自动对焦
  64. }catch(Exceptione){
  65. e.printStackTrace();
  66. }
  67. isPreview=true;
  68. }
  69. }
  70. }
  71. classStreamItimplementsCamera.PreviewCallback{
  72. privateStringipname;
  73. publicStreamIt(Stringipname){
  74. this.ipname=ipname;
  75. }
  76. @Override
  77. publicvoidonPreviewFrame(byte[]data,Cameracamera){
  78. Sizesize=camera.getParameters().getPreviewSize();
  79. try{
  80. //调用image.compressToJpeg()将YUV格式图像数据data转为jpg格式
  81. YuvImageimage=newYuvImage(data,ImageFormat.NV21,size.width,size.height,null);
  82. if(image!=null){
  83. ByteArrayOutputStreamoutstream=newByteArrayOutputStream();
  84. image.compressToJpeg(newRect(0,0,size.width,size.height),80,outstream);
  85. outstream.flush();
  86. //启用线程将图像数据发送出去
  87. Threadth=newMyThread(outstream,ipname);
  88. th.start();
  89. }
  90. }catch(Exceptionex){
  91. Log.e("Sys","Error:"+ex.getMessage());
  92. }
  93. }
  94. }
  95. classMyThreadextendsThread{
  96. privatebytebyteBuffer[]=newbyte[1024];
  97. privateOutputStreamoutsocket;
  98. privateByteArrayOutputStreammyoutputstream;
  99. privateStringipname;
  100. publicMyThread(ByteArrayOutputStreammyoutputstream,Stringipname){
  101. this.myoutputstream=myoutputstream;
  102. this.ipname=ipname;
  103. try{
  104. myoutputstream.close();
  105. }catch(IOExceptione){
  106. e.printStackTrace();
  107. }
  108. }
  109. publicvoidrun(){
  110. try{
  111. //将图像数据通过Socket发送出去
  112. SockettempSocket=newSocket(ipname,6000);
  113. outsocket=tempSocket.getOutputStream();
  114. ByteArrayInputStreaminputstream=newByteArrayInputStream(myoutputstream.toByteArray());
  115. intamount;
  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(IOExceptione){
  123. e.printStackTrace();
  124. }
  125. }
  126. }

二、PC服务器端

ImageServer.java 用于显示图像,并且可以拍照

[java]view plaincopy
  1. publicclassImageServer{
  2. publicstaticServerSocketss=null;
  3. publicstaticvoidmain(Stringargs[])throwsIOException{
  4. ss=newServerSocket(6000);
  5. finalImageFrameframe=newImageFrame(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. Aframewithanimagepanel
  16. */
  17. @SuppressWarnings("serial")
  18. classImageFrameextendsJFrame{
  19. publicImagePanelpanel;
  20. publicJButtonjb;
  21. publicImageFrame(ServerSocketss){
  22. //getscreendimensions
  23. Toolkitkit=Toolkit.getDefaultToolkit();
  24. DimensionscreenSize=kit.getScreenSize();
  25. intscreenHeight=screenSize.height;
  26. intscreenWidth=screenSize.width;
  27. //centerframeinscreen
  28. setTitle("ImageTest");
  29. setLocation((screenWidth-DEFAULT_WIDTH)/2,(screenHeight-DEFAULT_HEIGHT)/2);
  30. setSize(DEFAULT_WIDTH,DEFAULT_HEIGHT);
  31. //addpaneltoframe
  32. this.getContentPane().setLayout(null);
  33. panel=newImagePanel(ss);
  34. panel.setSize(640,480);
  35. panel.setLocation(0,0);
  36. add(panel);
  37. jb=newJButton("拍照");
  38. jb.setBounds(0,480,640,50);
  39. add(jb);
  40. saveimagesaveaction=newsaveimage(ss);
  41. jb.addActionListener(saveaction);
  42. }
  43. publicstaticfinalintDEFAULT_WIDTH=640;
  44. publicstaticfinalintDEFAULT_HEIGHT=560;
  45. }
  46. /**
  47. Apanelthatdisplaysatiledimage
  48. */
  49. @SuppressWarnings("serial")
  50. classImagePanelextendsJPanel{
  51. privateServerSocketss;
  52. privateImageimage;
  53. privateInputStreamins;
  54. publicImagePanel(ServerSocketss){
  55. this.ss=ss;
  56. }
  57. publicvoidgetimage()throwsIOException{
  58. Sockets=this.ss.accept();
  59. System.out.println("连接成功!");
  60. this.ins=s.getInputStream();
  61. this.image=ImageIO.read(ins);
  62. this.ins.close();
  63. }
  64. publicvoidpaintComponent(Graphicsg){
  65. super.paintComponent(g);
  66. if(image==null)return;
  67. g.drawImage(image,0,0,null);
  68. }
  69. }
  70. classsaveimageimplementsActionListener{
  71. RandomAccessFileinFile=null;
  72. bytebyteBuffer[]=newbyte[1024];
  73. InputStreamins;
  74. privateServerSocketss;
  75. publicsaveimage(ServerSocketss){
  76. this.ss=ss;
  77. }
  78. publicvoidactionPerformed(ActionEventevent){
  79. try{
  80. Sockets=ss.accept();
  81. ins=s.getInputStream();
  82. //文件选择器以当前的目录打开
  83. JFileChooserjfc=newJFileChooser(".");
  84. jfc.showSaveDialog(newjavax.swing.JFrame());
  85. //获取当前的选择文件引用
  86. FilesavedFile=jfc.getSelectedFile();
  87. //已经选择了文件
  88. if(savedFile!=null){
  89. //读取文件的数据,可以每次以快的方式读取数据
  90. try{
  91. inFile=newRandomAccessFile(savedFile,"rw");
  92. }catch(FileNotFoundExceptione){
  93. e.printStackTrace();
  94. }
  95. }
  96. intamount;
  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(newjavax.swing.JFrame(),
  104. "已接保存成功","提示!",javax.swing.JOptionPane.PLAIN_MESSAGE);
  105. }catch(IOExceptione){
  106. e.printStackTrace();
  107. }
  108. }
  109. }

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

只能在android4.04系统的手机上运行成功哦。

下面是测试成功时的启动画面:

源码链接:

http://files.cnblogs.com/feifei1010/%E5%9F%BA%E4%BA%8Eandroid%E6%89%8B%E6%9C%BA%E7%9A%84%E8%B

更多相关文章

  1. 背景图像颜色检测与Android油漆。
  2. 想在android中使用node.js和socket.io发送图像
  3. Android Picasso Dropbox:如何将图像加载到gridview中
  4. OpenCV4Android中图像预览旋转90度的问题
  5. Android图形图像处理之Bitmap和BitmapFactory
  6. 使用android的加速度计移动图像
  7. 在不同状态下使用两个图像切换按钮
  8. POST json和图像到服务器android
  9. java漏洞成黑客目标微软呼吁用户更新软件

随机推荐

  1. 在PHP中将PDF文档转换为预览图像,而无需安
  2. PHP开发视频教程
  3. php CI框架nginx 配置
  4. C#,PHP对应加密函数
  5. centos7下的lnmp环境安装
  6. phpmyadmin的乱码问题
  7. 用PHP计算字符串中元音的简单方法?
  8. 我无法定义我的错误
  9. 节点js / Express替换LAMP
  10. 如何使用phpunit测试用例测试ajax调用?