基于Android的远程视频监控系统(含源码)
来源:互联网 发布:人工智能进入国考试卷 编辑:程序博客网 时间:2024/04/30 13:48
基本过程是android作为socket客户端将采集到的每一帧图像数据发送出去,PC作为服务器接收并显示每一帧图像实现远程监控。图片如下(后来PC端加了个拍照功能)。。。
(PS。刚学android和java不久很多东西还不懂,高手若是知道哪些地方可以继续优化的话还请多多指点下啊)
系统代码如下:
一、android手机客户端
(1)AndroidManifest.xml文件。添加camera和socket权限,并设置了程序开始执行的activity、
01
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
02
<
manifest
xmlns:android
=
"http://schemas.android.com/apk/res/android"
03
package
=
"org.wanghai.CameraTest"
04
android:versionCode
=
"1"
05
android:versionName
=
"1.0"
>
06
07
<
uses-sdk
android:minSdkVersion
=
"15"
/>
08
09
<!-- 授予程序使用摄像头的权限 -->
10
<
uses-permission
android:name
=
"android.permission.CAMERA"
/>
11
<
uses-feature
android:name
=
"android.hardware.camera"
/>
12
<
uses-feature
android:name
=
"android.hardware.camera.autofocus"
/>
13
<
uses-permission
android:name
=
"android.permission.INTERNET"
/>
14
<
uses-permission
android:name
=
"android.permission.KILL_BACKGROUND_PROCESSES"
/>
15
<
uses-permission
android:name
=
"android.permission.RESTART_PACKAGES"
/>
16
17
<
application
18
android:icon
=
"@drawable/ic_launcher"
19
android:label
=
"@string/app_name"
>
20
21
<
activity
22
android:name
=
".GetIP"
23
android:screenOrientation
=
"landscape"
24
android:label
=
"@string/app_name"
>
25
<
intent-filter
>
26
<
action
android:name
=
"android.intent.action.MAIN"
/>
27
<
category
android:name
=
"android.intent.category.LAUNCHER"
/>
28
</
intent-filter
>
29
</
activity
>
30
<
activity
31
android:name
=
".CameraTest"
32
android:screenOrientation
=
"landscape"
33
android:label
=
"@string/app_name"
>
34
35
</
activity
>
36
37
</
application
>
38
39
</
manifest
>
40
41
(2)main.xml 设置surfaceview用于摄像头采集图像的预览
42
?
43
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
44
<
LinearLayout
xmlns:android
=
"http://schemas.android.com/apk/res/android"
45
android:layout_width
=
"fill_parent"
46
android:layout_height
=
"fill_parent"
47
android:orientation
=
"vertical"
>
48
49
<
SurfaceView
50
android:id
=
"@+id/sView"
51
android:layout_width
=
"fill_parent"
52
android:layout_height
=
"fill_parent"
53
android:scaleType
=
"fitCenter"
/>
54
55
</
LinearLayout
>
56
57
(3)login.xml 登录界面,用于输入服务器IP
58
?
59
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
60
<
TableLayout
xmlns:android
=
"http://schemas.android.com/apk/res/android"
61
android:id
=
"@+id/loginForm"
62
android:orientation
=
"vertical"
63
android:layout_width
=
"fill_parent"
64
android:layout_height
=
"fill_parent"
65
>
66
67
<
TableRow
>
68
<
TextView
69
android:layout_width
=
"fill_parent"
70
android:layout_height
=
"wrap_content"
71
android:text
=
"IP:"
72
android:textSize
=
"10pt"
73
/>
74
<!-- 输入用户名的文本框 -->
75
<
EditText
76
android:id
=
"@+id/ipedittext"
77
android:layout_width
=
"fill_parent"
78
android:layout_height
=
"wrap_content"
79
android:digits
=
"0123456789."
80
android:hint
=
"请填写服务器IP"
81
android:selectAllOnFocus
=
"true"
82
/>
83
</
TableRow
>
84
85
</
TableLayout
>
001
(
4
)GetIP.java 获得服务器IP后,通过Intent启动CameraTest的activity,ip信息通过Bundle传递
002
?
003
public
class
GetIP
extends
Activity {
004
String ipname =
null
;
005
@Override
006
public
void
onCreate(Bundle savedInstanceState) {
007
super
.onCreate(savedInstanceState);
008
// 设置全屏
009
requestWindowFeature(Window.FEATURE_NO_TITLE);
010
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
011
setContentView(R.layout.main);
012
013
final
Builder builder =
new
AlertDialog.Builder(
this
);
//定义一个AlertDialog.Builder对象
014
builder.setTitle(
"登录服务器对话框"
);
// 设置对话框的标题
015
016
//装载/res/layout/login.xml界面布局
017
TableLayout loginForm = (TableLayout)getLayoutInflater().inflate( R.layout.login,
null
);
018
final
EditText iptext = (EditText)loginForm.findViewById(R.id.ipedittext);
019
builder.setView(loginForm);
// 设置对话框显示的View对象
020
// 为对话框设置一个“登录”按钮
021
builder.setPositiveButton(
"登录"
022
// 为按钮设置监听器
023
,
new
OnClickListener() {
024
@Override
025
public
void
onClick(DialogInterface dialog,
int
which) {
026
//此处可执行登录处理
027
ipname = iptext.getText().toString().trim();
028
Bundle data =
new
Bundle();
029
data.putString(
"ipname"
,ipname);
030
Intent intent =
new
Intent(GetIP.
this
,CameraTest.
class
);
031
intent.putExtras(data);
032
startActivity(intent);
033
}
034
});
035
// 为对话框设置一个“取消”按钮
036
builder.setNegativeButton(
"取消"
037
,
new
OnClickListener()
038
{
039
@Override
040
public
void
onClick(DialogInterface dialog,
int
which)
041
{
042
//取消登录,不做任何事情。
043
System.exit(
1
);
044
}
045
});
046
//创建、并显示对话框
047
builder.create().show();
048
}
049
}
050
051
(
5
)CameraTest.java 程序主体。设置PreviewCallback后,每当一帧图像数据采集完成后将调用PreviewCallback的onPreviewFrame函数。在这里我们将YUV格式数据转为jpg,再启用线程将数据通过socket发送出去。
052
?
053
public
class
CameraTest
extends
Activity {
054
SurfaceView sView;
055
SurfaceHolder surfaceHolder;
056
int
screenWidth, screenHeight;
057
Camera camera;
// 定义系统所用的照相机
058
boolean
isPreview =
false
;
//是否在浏览中
059
private
String ipname;
060
061
@SuppressWarnings
(
"deprecation"
)
062
@Override
063
public
void
onCreate(Bundle savedInstanceState) {
064
super
.onCreate(savedInstanceState);
065
// 设置全屏
066
requestWindowFeature(Window.FEATURE_NO_TITLE);
067
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
068
setContentView(R.layout.main);
069
070
// 获取IP地址
071
Intent intent = getIntent();
072
Bundle data = intent.getExtras();
073
ipname = data.getString(
"ipname"
);
074
075
screenWidth =
640
;
076
screenHeight =
480
;
077
sView = (SurfaceView) findViewById(R.id.sView);
// 获取界面中SurfaceView组件
078
surfaceHolder = sView.getHolder();
// 获得SurfaceView的SurfaceHolder
079
080
// 为surfaceHolder添加一个回调监听器
081
surfaceHolder.addCallback(
new
Callback() {
082
@Override
083
public
void
surfaceChanged(SurfaceHolder holder,
int
format,
int
width,
int
height) {
084
}
085
@Override
086
public
void
surfaceCreated(SurfaceHolder holder) {
087
initCamera();
// 打开摄像头
088
}
089
@Override
090
public
void
surfaceDestroyed(SurfaceHolder holder) {
091
// 如果camera不为null ,释放摄像头
092
if
(camera !=
null
) {
093
if
(isPreview)
094
camera.stopPreview();
095
camera.release();
096
camera =
null
;
097
}
098
System.exit(
0
);
099
}
100
});
101
// 设置该SurfaceView自己不维护缓冲
102
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
103
104
}
105
106
private
void
initCamera() {
107
if
(!isPreview) {
108
camera = Camera.open();
109
}
110
if
(camera !=
null
&& !isPreview) {
111
try
{
112
Camera.Parameters parameters = camera.getParameters();
113
parameters.setPreviewSize(screenWidth, screenHeight);
// 设置预览照片的大小
114
parameters.setPreviewFpsRange(
20
,
30
);
// 每秒显示20~30帧
115
parameters.setPictureFormat(ImageFormat.NV21);
// 设置图片格式
116
parameters.setPictureSize(screenWidth, screenHeight);
// 设置照片的大小
117
//camera.setParameters(parameters); // android2.3.3以后不需要此行代码
118
camera.setPreviewDisplay(surfaceHolder);
// 通过SurfaceView显示取景画面
119
camera.setPreviewCallback(
new
StreamIt(ipname));
// 设置回调的类
120
camera.startPreview();
// 开始预览
121
camera.autoFocus(
null
);
// 自动对焦
122
}
catch
(Exception e) {
123
e.printStackTrace();
124
}
125
isPreview =
true
;
126
}
127
}
128
129
}
130
131
class
StreamIt
implements
Camera.PreviewCallback {
132
private
String ipname;
133
public
StreamIt(String ipname){
134
this
.ipname = ipname;
135
}
136
137
@Override
138
public
void
onPreviewFrame(
byte
[] data, Camera camera) {
139
Size size = camera.getParameters().getPreviewSize();
140
try
{
141
//调用image.compressToJpeg()将YUV格式图像数据data转为jpg格式
142
YuvImage image =
new
YuvImage(data, ImageFormat.NV21, size.width, size.height,
null
);
143
if
(image!=
null
){
144
ByteArrayOutputStream outstream =
new
ByteArrayOutputStream();
145
image.compressToJpeg(
new
Rect(
0
,
0
, size.width, size.height),
80
, outstream);
146
outstream.flush();
147
//启用线程将图像数据发送出去
148
Thread th =
new
MyThread(outstream,ipname);
149
th.start();
150
}
151
}
catch
(Exception ex){
152
Log.e(
"Sys"
,
"Error:"
+ex.getMessage());
153
}
154
}
155
}
156
157
class
MyThread
extends
Thread{
158
private
byte
byteBuffer[] =
new
byte
[
1024
];
159
private
OutputStream outsocket;
160
private
ByteArrayOutputStream myoutputstream;
161
private
String ipname;
162
163
public
MyThread(ByteArrayOutputStream myoutputstream,String ipname){
164
this
.myoutputstream = myoutputstream;
165
this
.ipname = ipname;
166
try
{
167
myoutputstream.close();
168
}
catch
(IOException e) {
169
e.printStackTrace();
170
}
171
}
172
173
public
void
run() {
174
try
{
175
//将图像数据通过Socket发送出去
176
Socket tempSocket =
new
Socket(ipname,
6000
);
177
outsocket = tempSocket.getOutputStream();
178
ByteArrayInputStream inputstream =
new
ByteArrayInputStream(myoutputstream.toByteArray());
179
int
amount;
180
while
((amount = inputstream.read(byteBuffer)) != -
1
) {
181
outsocket.write(byteBuffer,
0
, amount);
182
}
183
myoutputstream.flush();
184
myoutputstream.close();
185
tempSocket.close();
186
}
catch
(IOException e) {
187
e.printStackTrace();
188
}
189
}
190
191
}
192
193
二、PC服务器端
194
ImageServer.java 用于显示图像,并且可以拍照
195
?
196
public
class
ImageServer {
197
public
static
ServerSocket ss =
null
;
198
199
public
static
void
main(String args[])
throws
IOException{
200
ss =
new
ServerSocket(
6000
);
201
202
final
ImageFrame frame =
new
ImageFrame(ss);
203
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
204
frame.setVisible(
true
);
205
206
while
(
true
){
207
frame.panel.getimage();
208
frame.repaint();
209
}
210
}
211
212
}
213
214
/**
215
A frame with an image panel
216
*/
217
@SuppressWarnings
(
"serial"
)
218
class
ImageFrame
extends
JFrame{
219
public
ImagePanel panel;
220
public
JButton jb;
221
222
public
ImageFrame(ServerSocket ss){
223
// get screen dimensions
224
Toolkit kit = Toolkit.getDefaultToolkit();
225
Dimension screenSize = kit.getScreenSize();
226
int
screenHeight = screenSize.height;
227
int
screenWidth = screenSize.width;
228
229
// center frame in screen
230
setTitle(
"ImageTest"
);
231
setLocation((screenWidth - DEFAULT_WIDTH) /
2
, (screenHeight - DEFAULT_HEIGHT) /
2
);
232
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
233
234
// add panel to frame
235
this
.getContentPane().setLayout(
null
);
236
panel =
new
ImagePanel(ss);
237
panel.setSize(
640
,
480
);
238
panel.setLocation(
0
,
0
);
239
add(panel);
240
jb =
new
JButton(
"拍照"
);
241
jb.setBounds(
0
,
480
,
640
,
50
);
242
add(jb);
243
saveimage saveaction =
new
saveimage(ss);
244
jb.addActionListener(saveaction);
245
}
246
247
public
static
final
int
DEFAULT_WIDTH =
640
;
248
public
static
final
int
DEFAULT_HEIGHT =
560
;
249
}
250
251
/**
252
A panel that displays a tiled image
253
*/
254
@SuppressWarnings
(
"serial"
)
255
class
ImagePanel
extends
JPanel {
256
private
ServerSocket ss;
257
private
Image image;
258
private
InputStream ins;
259
260
public
ImagePanel(ServerSocket ss) {
261
this
.ss = ss;
262
}
263
264
public
void
getimage()
throws
IOException{
265
Socket s =
this
.ss.accept();
266
System.out.println(
"连接成功!"
);
267
this
.ins = s.getInputStream();
268
this
.image = ImageIO.read(ins);
269
this
.ins.close();
270
}
271
272
public
void
paintComponent(Graphics g){
273
super
.paintComponent(g);
274
if
(image ==
null
)
return
;
275
g.drawImage(image,
0
,
0
,
null
);
276
}
277
278
}
279
280
class
saveimage
implements
ActionListener {
281
RandomAccessFile inFile =
null
;
282
byte
byteBuffer[] =
new
byte
[
1024
];
283
InputStream ins;
284
private
ServerSocket ss;
285
286
public
saveimage(ServerSocket ss){
287
this
.ss = ss;
288
}
289
290
public
void
actionPerformed(ActionEvent event){
291
try
{
292
Socket s = ss.accept();
293
ins = s.getInputStream();
294
295
// 文件选择器以当前的目录打开
296
JFileChooser jfc =
new
JFileChooser(
"."
);
297
jfc.showSaveDialog(
new
javax.swing.JFrame());
298
// 获取当前的选择文件引用
299
File savedFile = jfc.getSelectedFile();
300
301
// 已经选择了文件
302
if
(savedFile !=
null
) {
303
// 读取文件的数据,可以每次以快的方式读取数据
304
try
{
305
inFile =
new
RandomAccessFile(savedFile,
"rw"
);
306
}
catch
(FileNotFoundException e) {
307
e.printStackTrace();
308
}
309
}
310
311
int
amount;
312
while
((amount = ins.read(byteBuffer)) != -
1
) {
313
inFile.write(byteBuffer,
0
, amount);
314
}
315
inFile.close();
316
ins.close();
317
s.close();
318
javax.swing.JOptionPane.showMessageDialog(
new
javax.swing.JFrame(),
319
"已接保存成功"
,
"提示!"
, javax.swing.JOptionPane.PLAIN_MESSAGE);
320
}
catch
(IOException e) {
321
322
e.printStackTrace();
323
}
324
}
325
}
开放源码如下(android我使用的是4.03的SDK,其它版本请自行更改。2.3.3版本以下的请注意initCamera()里被注释掉的哪一行)
只能在android4.04系统的手机上运行成功哦。
下面是测试成功时的启动画面:
android_video.rar
转自:http://www.cnblogs.com/feifei1010/archive/2012/08/31/2664939.html 0 0
- 基于Android的远程视频监控系统(含源码)
- 基于android的远程视频监控系统
- 基于android的远程视频监控系统
- 基于android的远程视频监控系统
- 基于android的远程视频监控系统
- 基于android的远程视频监控系统
- 【转载】基于android的远程视频监控系统(已开放源码)_只有链接
- 基于android的远程视频监控系统(已开放源码)
- 基于android的远程视频监控系统(已开放源码)
- [Android实例] 基于android的远程视频监控系统
- 基于Android手机的远程视频监控系统
- android 远程视频监控系统
- 基于ARM平台的远程视频监控系统的研究
- 基于ARM的远程视频监控系统的设计
- #Testin杯#基于android的远程视频监控系统——学习第一步:实现Camera预览
- 基于mini2440的WEB远程视频实时监控系统
- 基于FFmpeg的远程视频监控系统编解码
- 一种基于Android智能手机的远程视频监控的设计
- android strings.xml的特殊字符
- OpenCV人脸识别深度讲解
- .net Async await Task<T>
- iOS CoreAnimation
- ORA-01843: not a valid month
- 基于Android的远程视频监控系统(含源码)
- 更新iOS应用程序教程
- java和js添加删除读取cookie
- U-boot 添加命令 U_BOOT_CMD
- 设置ubuntu登录自启动程序
- 机器学习周刊
- iOS的UDID废用以及UUID配合keychain的替换方案实现
- Activity生命周期
- HashMap实现原理