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

 

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

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

<?xml version= "1.0"  encoding= "utf-8" ?> "http://schemas.android.com/apk/res/android"      package = "org.wanghai.CameraTest"      android:versionCode= "1"      android:versionName= "1.0"  >        "15"  />                     "android.permission.CAMERA"  />          "android.hardware.camera"  />          "android.hardware.camera.autofocus"  />          "android.permission.INTERNET" />      "android.permission.KILL_BACKGROUND_PROCESSES" />      "android.permission.RESTART_PACKAGES" />                 android:icon= "@drawable/ic_launcher"          android:label= "@string/app_name"  >                                         android:name= ".GetIP"              android:screenOrientation= "landscape"              android:label= "@string/app_name"  >                               "android.intent.action.MAIN"  />                  "android.intent.category.LAUNCHER"  />                                             android:name= ".CameraTest"              android:screenOrientation= "landscape"              android:label= "@string/app_name"  >                            

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

<?xml version= "1.0"  encoding= "utf-8" ?> "http://schemas.android.com/apk/res/android"      android:layout_width= "fill_parent"      android:layout_height= "fill_parent"      android:orientation= "vertical"  >                android:id= "@+id/sView"          android:layout_width= "fill_parent"          android:layout_height= "fill_parent"          android:scaleType= "fitCenter" />  

  (3)login.xml 登录界面,用于输入服务器IP

<?xml version= "1.0"  encoding= "utf-8" ?> "http://schemas.android.com/apk/res/android"          android:id= "@+id/loginForm"          android:orientation= "vertical"          android:layout_width= "fill_parent"          android:layout_height= "fill_parent"          >                        android:layout_width= "fill_parent"          android:layout_height= "wrap_content"          android:text= "IP:"          android:textSize= "10pt"          />      android:id= "@+id/ipedittext"          android:layout_width= "fill_parent"          android:layout_height= "wrap_content"          android:digits= "0123456789."          android:hint= "请填写服务器IP"          android:selectAllOnFocus= "true"          />  

  (4)GetIP.java 获得服务器IP后,通过Intent启动CameraTest的activity,ip信息通过Bundle传递

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.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 ,CameraTest. class );                                          intent.putExtras(data);                                          startActivity(intent);                                  }                          });                  // 为对话框设置一个“取消”按钮                  builder.setNegativeButton( "取消"                          new  OnClickListener()                          {                                  @Override                                  public  void  onClick(DialogInterface dialog, int  which)                                  {                                          //取消登录,不做任何事情。                                          System.exit( 1 );                                  }                          });                  //创建、并显示对话框                  builder.create().show();          } }

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

public  class  CameraTest extends  Activity {          SurfaceView sView;          SurfaceHolder surfaceHolder;          int  screenWidth, screenHeight;                 Camera camera;                    // 定义系统所用的照相机                 boolean  isPreview = false ;        //是否在浏览中          private  String ipname;            @SuppressWarnings ( "deprecation" )          @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.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();          }      }   }

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

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();                  }          } }

  开放源码如下(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%BF%9C%E7%A8%8B%E8%A7%86%E9%A2%91%E7%9B%91%E6%8E%A7%E7%B3%BB%E7%BB%9F.rar  

更多相关文章

  1. 【Android(安卓)初学者】开发工具介绍:studio
  2. Android开发学习之基本控件概览
  3. Android界面编程——Android基本控件
  4. Android兼容性问题 -- FrameLayout中View设置margin无效
  5. CheckBox 设置style 没有效果的原因
  6. Android(安卓)HttpClient设置User_agent的方式
  7. Android(安卓)三个按钮对话框
  8. Android之自定义对话框AlertDialog.Builder+getLayoutInflater()
  9. android设置缺省的异常捕获器

随机推荐

  1. android中获取string字符串的方法
  2. android 将程序设置为app2sd
  3. Android-View-Attribute
  4. Android 中.aar文件生成方法与用法
  5. android:configChanges问题
  6. android 类似QQ 换皮肤 实现思路 apk资源
  7. Android系统底层架构【译】
  8. Android中用Application类实现全局变量
  9. Android MediaPlayer学习笔记
  10. [置顶] Android--纠正Activity横竖屏切换