还记得上篇提到的setPreviewCallback(Camera.PreviewCallback cb)函数吗?我们在开始预览帧视频之前,调用的它,这里要注意其内部的Camera.PreviewCallback类型的参数,我们需要写一个类继承Camera.PreviewCallback的类,在该类中覆写public
void onPreviewFrame(byte[] data, Camera camera)方法,这里的data参数保存的即是预览帧是视频数据,一旦程序调用Camera.PreviewCallback接口,便会自动调用发方法,因此当我们在开始预览帧视频之前调用setPreviewCallback(Camera.PreviewCallback
cb)函数时,便会回调该方法,理论上来说我们在这个方法中写发送帧视频的代码就行了,但实际上我们并不能这么做,因为发送视频数据是一个很耗时的操作,为了防止UI线程阻塞,我们需要另外开启一个线程,在该线程中实现视频的发送操作。
这里我们采用AsyncTask<Void, Void, Void>后台线程,因此我们需要再写一个类,继承AsyncTask<Void,
Void, Void>抽象类,并覆写其中的protected Void doInBackground(Void... params)方法,在该方法中编写发送视频数据的程序即可,这里要注意形参的含义,因为的项目中不需要用到这三个参数,因此全部传入Void,关于AsyncTask的详细使用,可以参见这两篇博客:http://blog.csdn.net/ns_code/article/details/12889455和http://blog.csdn.net/liuhe688/article/details/6532519,我在该方法中写的代码如下:
//该方法运行在后台线程中,主要负责执行耗时的后台计算传输等工作,
//实际的后台操作被UI Thread调用时,该方法被回调
@Override
protected Void doInBackground(Void... params) {
//cam = (CameraActivity)context;
Size size = cam.getCamera().getParameters().getPreviewSize();
int wide = size.width;
int high = size.height;
YuvImage image = new YuvImage(data, ImageFormat.NV21, wide, high, null);
//因为要实时处理视频流,因此用内存操作流比较合适
ByteArrayOutputStream os = new ByteArrayOutputStream(data.length);
if(!image.compressToJpeg(new Rect(0, 0, wide, high), 100, os)){
return null;
}
send(os);
return null;
}
这里倒数第三行的send(os)记为发送视频的操作,当然,如果你是做其他的操作,而不是传输视频数据,你也可以将其改为其他的函数,比如做街景检测、人脸车牌识别等,而其他代码基本不用修改,发送视频的send方法基本就是按照TCP协议编写,在JAVA中是用Socket类编写客户端的代码:
//发送视频流到PC端,这里传递过来的参数os中保存的是视频输出流数据
private void send(ByteArrayOutputStream os) {
//定义用来保存从输入流中读取的视频流数据的byte数组
byte[] buffer = new byte[1024];
try {
Socket client = new Socket(ipName,30000);
OutputStream outSocket = client.getOutputStream();
//实例化内存输入流,将视频流数据写入到内存中
ByteArrayInputStream inputFromOs = new ByteArrayInputStream(os.toByteArray());
//不断从内存中读取数据到buffer中,不断再从buffer中将视频数据发送到outSocket流中
int amount;
while((amount =inputFromOs.read(buffer) ) != -1)
outSocket.write(buffer, 0, amount);
//这里需要刷新用到缓冲区的输出流
os.flush();
inputFromOs.close();
os.close();
outSocket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
System.out.println("无法找到要连接的服务器");
} catch (IOException e) {
e.printStackTrace();
System.out.println("IO错误");
}
}
最后,什么时候调用protected
Void doInBackground(Void... params)方法呢?看了上面那两篇博客,应该也会明白了,当调用execute(Params... params)方法时,便会自动回调该方法,从而执行其内部代码。
至此,整个项目的Android客户端代码已经编写完毕,下篇将讲述PC端(亦即服务端)代码的实现
分享到:
相关推荐
在本项目中,“安卓Android源码——基于手机的远程视频监控系统”是一个使用Android平台开发的应用,它允许用户通过智能手机实现远程视频监控。这个系统的关键在于整合了图像处理、网络通信以及Android应用开发技术...
该Android远程视频监控程序源码是一个典型的移动应用开发案例,主要展示了如何在Android平台上实现远程视频的实时监控功能。这个项目对于计算机科学和技术、软件工程等专业的学生进行毕业设计或论文研究具有很高的...
8.2.3 将Earthquake Service移动到后台线程 262 8.3 创建一个Toast 263 8.3.1 定制Toast 263 8.3.2 在工作(worker)线程中使用Toast 265 8.4 Notification简介 266 8.4.1 Notification Manager简介 267 8.4.2 ...
4. **多线程与异步处理**:视频聊天需要处理大量的数据传输,必须在后台线程中进行,以免阻塞UI线程。Android中的AsyncTask或Handler/Looper机制可以实现这一目标。 5. **媒体流处理**:视频聊天涉及到音视频编码与...
- Handler/Looper/Messenger:理解Android消息机制,实现UI线程与后台线程间的通信。 - AsyncTask:轻量级的异步任务执行框架,但注意避免内存泄漏。 - RxJava:强大的响应式编程库,简化异步操作,处理复杂的...
"WiFi Camera"项目是一个基于Android平台的远程监控应用,提供了通过WiFi网络连接摄像头进行实时监控的功能。这个项目包含了Android源码、JNI(Java Native Interface)代码,开发者可以通过编译JNI部分生成SO...
8.2.3 将Earthquake Service移动到后台线程 8.3 创建一个Toast 8.3.1 定制Toast 8.3.2 在工作(worker)线程中使用Toast 8.4 Notification简介 8.4.1 Notification Manager简介 8.4.2 创建Notification 8.4.3 触发...
SurfaceView是一个特殊的视图,能够创建一个独立的渲染表面,适合实时视频预览。TextureView则提供了一个可以被其他OpenGL图形操作使用的纹理,适合对画面有复杂需求的应用。 4. **权限管理**:在Android系统中,...
- **实时跟踪状态**:实时监控下载任务的状态,包括进度、错误信息和文件完整性。 - **状态查询接口**:提供接口供用户查询下载任务的实时信息。 - **自动执行后续操作**:根据任务状态自动执行相应的操作,如重...
4. **Services**:在后台执行长时间任务的服务,如播放音乐或网络通信,是Android应用不可或缺的一部分。本章可能详细介绍了Service的创建、启动和绑定方式。 5. **Broadcast Receivers**:广播接收器用于监听系统...
2. **异步处理**:对于裁剪或上传等耗时操作,应尽可能放在后台线程执行,保证UI的流畅性。 3. **性能监控**:关注图片加载和选择过程中的性能问题,及时进行优化。 总结,PictureSelector以其强大的功能和灵活性,...
- **异步处理**:客户端上传操作应在后台线程进行,避免阻塞UI。 - **断点续传**:对于大文件,可以实现断点续传功能,提高上传稳定性。 - **压缩上传**:在上传前对文件进行压缩,减少网络传输的数据量。 5. **...
此外,Android Profiler可以实时监控内存、CPU和网络使用情况。 十、发布与分发 完成应用开发后,可以通过Google Play Store或其他第三方市场发布应用。在发布前,需要进行签名和优化,确保应用的兼容性和安全性。...