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

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="org.wanghai.CameraTest"
    android:versionCode="1"
    android:versionName="1.0" >
  
    <uses-sdk android:minSdkVersion="15" />
      
    <!-- 授予程序使用摄像头的权限 -->
        <uses-permission android:name="android.permission.CAMERA" />
        <uses-feature android:name="android.hardware.camera" />
        <uses-feature android:name="android.hardware.camera.autofocus" />
        <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/>
    <uses-permission android:name="android.permission.RESTART_PACKAGES"/>
  
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
                  
        <activity
            android:name=".GetIP"
            android:screenOrientation="landscape"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".CameraTest"
            android:screenOrientation="landscape"
            android:label="@string/app_name" >
  
        </activity>
          
    </application>
  
</manifest>
        (2)main.xml 设置surfaceview用于摄像头采集图像的预览
?
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
  
   <SurfaceView
        android:id="@+id/sView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:scaleType="fitCenter"/>
  
</LinearLayout>
        (3)login.xml 登录界面,用于输入服务器IP
?
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/loginForm"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        >
  
<TableRow>          
<TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="IP:"
        android:textSize="10pt"
        />
<!-- 输入用户名的文本框 -->
<EditText
    android:id="@+id/ipedittext"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:digits="0123456789."
        android:hint="请填写服务器IP"
        android:selectAllOnFocus="true"
        />
</TableRow>
  
</TableLayout>

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
        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(00, 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(00);
        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 == nullreturn;
        g.drawImage(image, 00null);
    }
  
}
  
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系统的手机上运行成功哦。

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


 android_video.rar

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

把Android手机变成远程监控摄像头相关推荐

  1. Android手机文件远程管理

    当你启动远程连接服务后,只要您的手机与电脑同处一个WLAN,也就是连接相同的wifi时,无论wifi能不能提供上网功能,都可以在电脑端远程管理手机中的文件. 当网速不好的时候,通过这种方式就能很方便地 ...

  2. android手机远程控制_如何远程查看和控制您的Android手机

    android手机远程控制 If you've ever wished you could see your Android phone's screen on your desktop or rem ...

  3. 基于Android智能终端的远程控制系统

    摘  要: 提出了基于Android 手机的远程控制系统设计方案,该系统基于Openmobster开源手机云计算平台.介绍了整个系统结构框架,详细分析了各个模块的具体实现.通过应用实例在设备上进行了测 ...

  4. 使用TeamViewer远程连接Android手机并控制

    前言 程序员在家或者在外出差喜欢使用TeamViewer控制公司电脑及时处理问题. 而作为一名Android开发者过程中使用电脑远程控制Android手机也是必备的技能,这样我们就可以远程查Bug,远 ...

  5. 用Android手机远程桌面连接登陆Windows10(用微软账号登陆),Microsoft账户登陆的计算机远程桌面连接问题

    如果目标计算机是只有微软账号怎么办? 用户名: 用 微软账号(微软账号是一个邮箱:xxxxxxxx@qq.com ,得写全名) 密码 :用 微软账号的密码(注意:不是PIN 码,而是登陆微软官网是输入 ...

  6. android 远程代码,如何通过代码远程解锁Android手机

    如何通过代码远程解锁Android手机 我写了一个可以远程锁定android手机的应用程序. 也就是说,从服务器发送特殊代码后,应用程序将根据特殊代码锁定电话. 这是我正在使用的代码. if (!mD ...

  7. [附源码]计算机毕业设计Python+uniapp基于android手机设计并实现在线点单系统APPo682z(程序+源码+LW+远程部署)

    [附源码]计算机毕业设计Python+uniapp基于android手机设计并实现在线点单系统APPo682z(程序+源码+LW+远程部署) 该项目含有源码.文档.程序.数据库.配套开发软件.软件安装 ...

  8. android手机远程windows10,微软推出适用于Windows 10的Android远程控制

    微软为你的手机应用程序添加了一些改进和功能,将Windows 10 20H1 Build 18932推出到快速响铃中的内部人员,从支持触摸的PC添加Android设备的遥控器是该版本的亮点. &quo ...

  9. 安卓linux远程桌面连接,用SSH连接你的android手机

    首先当然是你的手机得有root权限,有了busybox,里面包含了一大堆的linux命令,现在大多的Rom都是从CM改过来的,现在CM的最新版已经是6.1了. 1.准备 rom为基于Cyanogen ...

最新文章

  1. 极光API推送 (v3 版本)
  2. opc ua_UA Web挑战会议:针对初创公司的SpringIO
  3. CF 529B Group Photo 2 (online mirror version)
  4. 二维码原理--开胃小知识
  5. laravel 判断字符串包含_laravel 字符串操作大全
  6. graphpad数据小数点_GraphPad Prism 统计指南 | 关于异常值(Outlier),你真的了解吗?...
  7. 没有找到站点_为了在家Coding,我搜集了海量的远程站点,然而...
  8. VB 二进制文件的操作
  9. android graphic(15)—fence
  10. Springboot使用FastJson后,接口返回中文乱码的问题解决。
  11. C++_public、private、protected权限介绍
  12. 在IMX6Q的linux4.1.15版本上默认支持docker
  13. CAD中插入外部参照字体会变繁体_打开CAD图纸发现图形丢失,原来是大意了,四招解决...
  14. 2寸的照片长宽各是多少_标准的2寸照片尺寸是多大?
  15. 蓝桥杯试题——随意组合
  16. いくつかの愛に心が飛作者が恋しい
  17. 单片C语言程序设计,用C语言编程操作SPMC75系列单片 - 控制/MCU - 电子发烧友网
  18. 什么是C++ __builtin_popcount()函数
  19. 在vue3中使用jsx语法
  20. java scanner 教程,Java Scanner 类 - Java 入门教程

热门文章

  1. .NET接入UnionPay银联支付(一)手机wap支付
  2. 程序员的十层楼,你属于哪一层?
  3. 怎么绕过付费验证获取作文网站上的内容
  4. iOS-AppStore审核指南(2017最新版)
  5. Mixly第三方库开发的两种方法——U8g2库二次开发
  6. 深入理解面向对象,面向对象3个特性7个原则6种关系
  7. 10、晶体三极管的符号和结构
  8. java批量文件打包成压缩成zip下载和大量数据导出excel时的处理方法
  9. 两寸标准证件照大小是多少?分享两种调整尺寸的方法
  10. [CS15] Fast and Accurate Recurrent Neural Network Acoustic Models for Speech Recognition-Has¸im Sak