Android HTTP Camera Live Preview Tutorial
The Android SDK includes a Camera class that is used to set image capture settings, start/stop preview, snap pictures, and retrieve frames for encoding for video. It is a handy abstraction of the real hardware device. However, the SDK doesn't provide any camera emulation, something that makes testing camera enabled applications quite difficult. In this tutorial, I am going to show you how to use a web camera in order to obtain a live camera preview.
What we are essentially going to do is setup a web camera to publish static images in a predefined URL and then grab these images from our application and present them as motion pictures. Note that this tutorial was inspired by a post named “Live Camera Previews in Android”.
Let's start by creating an Eclipse project under the name “AndroidHttpCameraProject” and an Activity named “MyCamAppActivity”. As a first step, I am going to show you how to use the SDK camera. You can find many resources on how to manipulate the camera, one of them being the CameraPreview class that is included in the SDK's samples. In short, we are going to extend the SurfaceView class and provide our implementation using the device's camera. Then, we use the setContentView method of our Activity in order to set the activity content to that specific View. Let's see what the two classes look like:
MyCamAppActivity
package com.javacodegeeks.android.camera;
import android.app.Activity;
import android.os.Bundle;
import android.view.SurfaceView;
import android.view.Window;
public class MyCamAppActivity extends Activity {
private SurfaceView cameraPreview;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
cameraPreview = new CameraPreview(this);
setContentView(cameraPreview);
}
}
CameraPreview
package com.javacodegeeks.android.camera;
import android.content.Context;
import android.hardware.Camera;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder holder;
private Camera camera;
public CameraPreview(Context context) {
super(context);
holder = getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
@Override
public void surfaceChanged(SurfaceHolder holder2, int format, int w, int h) {
Camera.Parameters parameters = camera.getParameters();
parameters.setPreviewSize(w, h);
camera.setParameters(parameters);
camera.startPreview();
}
@Override
public void surfaceCreated(SurfaceHolder holder1) {
try {
camera = Camera.open();
camera.setPreviewDisplay(holder1);
}
catch (Exception e) {
Log.i("Exception surfaceCreated()", "e=" + e);
camera.release();
camera = null;
}
}
@Override
public void surfaceDestroyed(SurfaceHolder arg0) {
camera.stopPreview();
camera.release();
camera = null;
}
}
In our “CameraPreview” class, we implement the SurfaceHolder.Callback interface so that we receive information about changes to the underlying surface. The methods that have to be implemented are the following:
* surfaceCreated: Called immediately after the surface is first created.
* surfaceChanged: Called immediately after any structural changes (format or size) have been made to the surface.
* surfaceDestroyed: Called immediately before a surface is being destroyed.
To use the Camera class, no constructor is available, but we rather use the open method which creates a new Camera object to access the first back-facing camera on the device. Then, we use the setPreviewDisplay method to set the Surface to be used for the live preview. Whenever a change occurs, we call the startPreview method in order to start capturing and drawing preview frames to the screen, after we have set the appropriate preview size (setPreviewSize) at the Camera.Parameters.
If we now launch the Eclipse configuration, we will come across a totally not-helpful image, as follows:
Now we are going to replace that surface view with a custom one that use static images from a web camera. First, let's see the changes to our activity. The new version is the following:
MyCamAppActivity
package com.javacodegeeks.android.camera;
import android.app.Activity;
import android.os.Bundle;
import android.view.Display;
import android.view.SurfaceView;
import android.view.Window;
public class MyCamAppActivity extends Activity {
private int viewWidth;
private int viewHeight;
private SurfaceView cameraPreview;
private static final boolean useHttpCamera = true;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
calculateDisplayDimensions();
if (useHttpCamera) {
cameraPreview = new HttpCameraPreview(this, viewWidth, viewHeight);
}
else {
cameraPreview = new CameraPreview(this);
}
setContentView(cameraPreview);
}
private void calculateDisplayDimensions() {
Display display = getWindowManager().getDefaultDisplay();
viewWidth = display.getWidth();
viewHeight = display.getHeight();
}
}
We have added a boolean variable to define which version we want to use, the one with the “real” camera or the one that uses the web cam. The latter, uses a new class named “HttpCameraPreview” which also extends the SurfaceView class. This one requires to know the width and the height of the enclosed view, thus we use the WindowManager class to get the default Display and from that we calculate the dimensions.
Here is what the new class looks like:
HttpCameraPreview
package com.javacodegeeks.android.camera;
import android.content.Context;
import android.graphics.Canvas;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class HttpCameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private static final String url = "http://10.0.2.2:8080";
private CanvasThread canvasThread;
private SurfaceHolder holder;
private HttpCamera camera;
private int viewWidth;
private int viewHeight;
public HttpCameraPreview(Context context, int viewWidth, int viewHeight) {
super(context);
holder = getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_NORMAL);
this.viewWidth = viewWidth;
this.viewHeight = viewHeight;
canvasThread = new CanvasThread();
}
@Override
public void surfaceChanged(SurfaceHolder holder2, int format, int w, int h) {
try {
Canvas c = holder.lockCanvas(null);
camera.captureAndDraw(c);
if (c != null) {
holder.unlockCanvasAndPost(c);
}
}
catch (Exception e) {
Log.e(getClass().getSimpleName(), "Error when surface changed", e);
camera = null;
}
}
@Override
public void surfaceCreated(SurfaceHolder arg0) {
try {
camera = new HttpCamera(url, viewWidth, viewHeight, true);
canvasThread.setRunning(true);
canvasThread.start();
}
catch (Exception e) {
Log.e(getClass().getSimpleName(), "Error while creating surface", e);
camera = null;
}
}
@Override
public void surfaceDestroyed(SurfaceHolder arg0) {
camera = null;
boolean retry = true;
canvasThread.setRunning(false);
while (retry) {
try {
canvasThread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
private class CanvasThread extends Thread {
private boolean running;
public void setRunning(boolean running){
this.running = running;
}
public void run() {
while (running) {
Canvas c = null;
try {
c = holder.lockCanvas(null);
synchronized (holder) {
camera.captureAndDraw(c);
}
}
catch (Exception e) {
Log.e(getClass().getSimpleName(), "Error while drawing canvas", e);
}
finally {
if (c != null) {
holder.unlockCanvasAndPost(c);
}
}
}
}
}
}
In the constructor, we start a thread that will be responsible for updating the Canvas of the surface view, which we will describe in a while. We implement again the SurfaceHolder.Callback interface and the three methods describer above. Note that a custom “HttpCamera” object is used, which captures the still images and draws them to the Canvas. The lockCanvas method of the SurfaceHolder is used in order draw into the surface's bitmap and the unlockCanvasAndPost method is invoked after the drawing has completed. The “HttpCamera” object uses a URL which is where the images get published. Note that the IP address is the 10.0.2.2, which actually is the machine hosting the Android emulator. We can not use the classic localhost address (127.0.0.1), since this points to the emulator itself. In the thread class, we have a loop in which we continuously draw on the underlying canvas. We use a boolean variable as a flag to indicate whether the process should continue or not.
Let's now see what this “HttpCamera” class is all about:
HttpCamera
package com.javacodegeeks.android.camera;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
public class HttpCamera {
private static final int CONNECT_TIMEOUT = 1000;
private static final int SOCKET_TIMEOUT = 1000;
private final String url;
private final Rect bounds;
private final boolean preserveAspectRatio;
private final Paint paint = new Paint();
public HttpCamera(String url, int width, int height, boolean preserveAspectRatio) {
this.url = url;
bounds = new Rect(0, 0, width, height);
this.preserveAspectRatio = preserveAspectRatio;
paint.setFilterBitmap(true);
paint.setAntiAlias(true);
}
private Bitmap retrieveBitmap() throws IOException {
Bitmap bitmap = null;
InputStream in = null;
int response = -1;
try {
URL url = new URL(this.url);
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
httpConn.setConnectTimeout(CONNECT_TIMEOUT);
httpConn.setReadTimeout(SOCKET_TIMEOUT);
httpConn.setRequestMethod("GET");
httpConn.connect();
response = httpConn.getResponseCode();
if (response == HttpURLConnection.HTTP_OK) {
in = httpConn.getInputStream();
bitmap = BitmapFactory.decodeStream(in);
}
return bitmap;
}
catch (Exception e) {
return null;
}
finally {
if (in != null) try {
in.close();
} catch (IOException e) {
/* ignore */
}
}
}
public boolean captureAndDraw(Canvas canvas) throws IOException {
Bitmap bitmap = retrieveBitmap();
if (bitmap == null) throw new IOException("Response Code: ");
//render it to canvas, scaling if necessary
if (bounds.right == bitmap.getWidth() && bounds.bottom == bitmap.getHeight()) {
canvas.drawBitmap(bitmap, 0, 0, null);
} else {
Rect dest;
if (preserveAspectRatio) {
dest = new Rect(bounds);
dest.bottom = bitmap.getHeight() * bounds.right / bitmap.getWidth();
dest.offset(0, (bounds.bottom - dest.bottom)/2);
}
else {
dest = bounds;
}
canvas.drawBitmap(bitmap, null, dest, paint);
}
return true;
}
}
In the constructor, we pass the URL to where the images from the camera should be found. This could be any web camera HTTP server. Additionally, we pass the view's dimensions and whether the aspect ratio should be preserved (this should be true in most cases). In the “captureAndDraw” method, which is the public method invoked by the custom surface class, we perform HTTP GET requests to the provided URL and retrieve the images as Bitmap objects. We then adjust the dimensions of the image accordingly and draw it on the Canvas using the drawBitmap method.
Let's now see the manifest file:
AndroidManifest
package="com.javacodegeeks.android.camera"
android:versionCode="1"
android:versionName="1.0">
android:label="@string/app_name">
The usual stuff here, just remember to add permissions for using the camera (android.permission.CAMERA) and creating internet connections (android.permission.INTERNET).
Before we test the application, we need to have images published on a web server. Some web cameras already provide that functionality, but in case yours does not, you can accomplish that using a pretty cool application named WebCam2000. Unfortunately, this is only for Windows machines. After you execute the program, it should automatically find your camera. If not, play a little with the options and make sure that in the “Video” menu, the “Microsoft WDM Image Capture” option is enabled. Then, make sure the “Enable Web Server” box is ticked and check that the server is working by pointing your browser to the corresponding URL:
http://localhost:8080/
If you now launch the Eclipse configuration, you will get a camera input to your emulator with the images periodically updated.
You can use this approach in order to provide a “mock camera” to your application and make it easier to test it. The Eclipse project created for this tutorial can be found here.
Enjoy and don't forget to share!
Related Articles :
* “Android Full Application Tutorial” series
* Android Location Based Services Application – GPS location
* Android Reverse Geocoding with Yahoo API - PlaceFinder
* Boost your Android XML parsing with XML Pull
* Android Text-To-Speech Application
* Install Android OS on your PC with VirtualBox
相关推荐
触摸屏蓝牙控制
使用杰理芯片通过蓝牙实现触摸屏功能,需要结合触摸屏数据采集、蓝牙数据传输以及移动端应用的实现。
继承案例 sex 没有调出来,什么原因?
package com.lianxi; /* * * 这是一个父类 * */ public class ManKind { private int sex;//性别 private int salary;//薪资 public void manOrWoman() { if(sex == 1) { System.out.println("man"); }else if (sex == 0) { ...
企业级AI项目落地实战指南
企业级 AI 项目落地需构建“分阶段实施 + 多维度风控”的双轮驱动体系:实施端通过 POC 验证技术可行性、试点建立评估标准、规模化实现价值复制,各阶段需结合行业案例(如东阳光药、旺盈集团)提炼可复用经验;风险端则需覆盖技术(数据安全、模型稳定性)、合规(全球监管动态)、组织(人才与文化)维度,通过工具化框架(AI TRISM)与案例策略(邮储银行可解释性设计、拓斯达培训体系)实现风险可控。最终通过“场景聚焦 - 合规嵌入 - 持续优化”的循环机制,实现 AI 技术从“试点成功”到“全面价值创造”的跨越。
android.hardware.camera2详解
看到有些读者对博客提出的疑问,在此真诚说一句实在抱歉,本人是一名在校非科班出身大学生,之前 由于是期末季,所以非常忙,没有空更新,一月二十几号才放假,非常抱歉,评论所诉内容应该都已解决,只是我没有更新,近期将会更新!再次致歉! 前言:原有的android.hardware.camera已经被google废除,改用功能更强大的camera2,camera2的复杂度远远超过camera,所以写
GPU架构-SIMT
本文深度剖析了GPU的SIMT架构,从硬件实现层面解析其与SIMD的本质差异。SIMT通过将32个线程捆绑为warp执行,在标量编程模型下实现数据并行。文章对比了SIMD和SIMT的执行模型、分支处理机制及存储层次,指出SIMT是对SIMD的虚拟化抽象。重点分析了Volta架构引入的独立线程调度技术,以及访存合并对性能的关键影响。通过定量数据展示了各代GPU架构的寄存器文件规模和线程调度机制,为开发者优化GPU程序提供了硬件层面的理论基础。
数字IC设计实现之hierarchical flow系列(一)
数字IC设计实现之hierarchical flow系列(一) 最近这段时间小编又比较忙起来了,今天抽空来咖啡厅码字来了,刚到时脑子一片空白,不知道要分享些什么(项目结束后将会在知识星球上分享数字 IC 设计实现 Tapeout 前要review的那些 checklist)。突然间想起来有个星友希望小编分享些数字 IC 设计实现 hierarchical flow 的相关内容。考虑到现在大都采用这种方式来做 design 和实现,那就选这个 topic 了。限于篇幅和时间限制,今天只分享逻辑综合部分和布局布
---WebCam网络摄像头8 usb--v4l2 , Format............:V4L2_PIX_FMT_MJPEG
[root@localhost input_uvc]# pwd /opt/FriendlyArm/mini2440/WebCam/mjpg-streamer/mjpg-streamer/plugins/input_uvc [root@localhost input_uvc]# tree . |-- Makefile |-- dynctrl.c |-- dynctrl.h |-- dy...
AI赋能数字人:打造与语音节奏完美匹配的高质量手势动画
想象一个场景:当你与一位数字人交谈时,它不仅能理解你的言语,还能恰到好处地挥动手臂、比划手势,就像真实的人类交流一样自然流畅。这正是当前AI技术致力于实现的目标——通过分析语音内容,自动生成与之相匹配的手势动作,为数字人赋予更加丰富的情感表达和非言语沟通能力。AI手势生成技术的出现,标志着数字人在模仿人类自然交流方式上迈出了重要一步。随着技术的不断成熟与应用场景的拓宽,未来我们可以期待更多富有表现力和情感互动的数字人出现在我们的日常生活中,开启人机交互的新篇章。
索尼wifi控制相机开发总结(三):HttpCamera的说明和CameraFactory自动生成已测试的相机实例
现在, 对操控用Http协议控制的相机的封装类HttpCamera的结构进行一下整理, 同时, 整理一下CameraFactory类, 实现对根据相机的名字, 来生成相应的HttpCamera子类并返回给外部, 工厂只负责生产, 不负责对实例化的HttpCamera的子类的回收, 因此, 外部在获取实例化对象以后, 应该持有并负责其回收工作. HttpCamera类的整理 ...
YOLOv11模型剪枝实战:让检测速度翻倍,精度仅降1%的终极优化教程
模型剪枝是YOLOv11落地边缘场景的“关键一步”——它让模型在“瘦身”的同时,几乎不损失精度。从稀疏化训练到通道剪枝,再到工程部署,本教程已为你打通全流程。现在就动手尝试,让你的YOLOv11模型在嵌入式设备、移动端上也能“飞起来”——相信我,当你看到剪枝后的模型在资源受限设备上仍能精准检测时,你会明白这份技术的价值。
GEE:随机森林分类教程(样本制作、特征添加、训练、精度、参数优化、贡献度、统计面积)
本文将介绍在Google Earth Engine (GEE)平台上进行随机森林分类的方法和代码,其中包括制作样本点教程(本地、在线和本地在线混合制作样本点,合并样本点等),加入特征变量,运行随机森林分类器教程,计算随机森林分类结果的精度,优化随机森林分类算法的参数,打印各个变量特征的贡献度等步骤的方法和代码。本教程可以应用于多种分类场景,包括土地利用分类、种植区提取(大蒜、小麦、玉米等)、局部气候区分类、植被分类等多种场景。
HTTP远程camera视频流传输的一个方案
GitHub - jacksonliam/mjpg-streamer: Fork of http://sourceforge.net/projects/mjpg-streamer/
第三篇:NVIDIA cuOpt Python API 详解:LP、QP、MILP 建模与求解,附核心术语名词解释
NVIDIA cuOpt是一款GPU加速的优化求解库,支持LP、QP、MILP和路径优化问题。本文详细介绍了其Python API使用方法,包括核心类Problem的变量定义、约束添加、目标设置和求解配置,并提供了术语解释。cuOpt通过GPU并行计算大幅提升大规模优化问题的求解效率,支持多种求解算法和参数配置,适用于需要高性能计算的优化场景。安装方式包含pip和Docker两种,验证安装后即可快速开始建模求解。
HTTP协议调用摄像头拍照上传更新头像前后端
4. 后端处理,以及修改当前用户头像的操作可以通过以下链接进行查看。1. 下载 Webcam 实现调用摄像头功能。3. 处理拍出来的图片并进行格式处理。2. 调用摄像头进行拍照。
计算机控制技术及应用
《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。
NTscan扫描工具
ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。
浏览器访问网络摄像机 (Internet Protocol camera,IP camera)
浏览器访问网络摄像机 (Internet Protocol camera,IP camera)
LinePhone3.2.7(android端最新版本) sip客户端
SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/
CAM350 导出DXF文件
CAM350 导出DXF文件 本文摘录于:https://wenku.baidu.com/view/b38d10aed0d233d4b14e6945.html 这里只是为了摘录备份,补充知识,绝无抄袭之意,请原作者谅解! CAM350 用 GerBer 导出 DXF 注意事项 下面我说一下用 GerBer 导出 DXF 注意事项。 需要软件如下: CAM
精雕软件(JDpaint) 5.5 绿色版
精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版
索尼wifi控制相机开发总结(四):HttpSonyCamera的说明及实现
终于又抽出时间来继续写总结了,上一次把抽象类总结以后,这次总结一下具体封装的索尼相机类的结构和实现。突然发现好像应该一开始先总结一下相机的控制流程来的,写完这一章立刻补上。HttpSonyCamera的结构 HttpSonyCamera类图: 索尼相机类持有两个线程类,一个负责不断的获取相机返回的预览帧二进制流数据的线程类GetLiveV...
手机 camera
1. 目标[52RD.com] 手机摄像头模组用ISP功能模块的市场走向及研发方向。为能够正确认识手机摄像模组行业提供技术及市场依据。[52RD.com] 2. ISP在模组上的应用原理[52RD.com] 2.1 功能区域[52RD.com] 无论数码相机、摄像
HttpCanary最新版——最强Android抓包工具(v3.3.4)
HttpCanary3.3.4,截止2020年5月23日,HttpCanary最新版本。 HttpCanary是一款功能强大的HTTP/HTTPS/HTTP2网络包抓取和分析工具,你可以把他看成是移动端的Fiddler或者Charles,但是HttpCanary使用起来更加地简单容易,因为它是专门为移动端设计的! 有需要的,自行下载即可。 下载地址:点击访问 ...
HTML5实现IP Camera网页输出 分类: HTML5 ...
HTML5实现IP Camera网页输出 分类: HTML5 2015-07-06 10:56 262人阅读 评论(0) 收藏 ...
具身智能 2026:启元人形机器人开发者生态的“安卓时刻”来了吗
一个贯穿全文的问题:人形机器人开发者生态,是否正从「封闭垂直」走向「开源平台化」?本文以开源底座的公开数据为标尺,盘点 SDK、URDF、仿真与技能分发的开放程度,并落回启元机器人的开源路径。所有关键数据均标注来源,文末附社区与学堂链接。
android-ad-cleaner:android免 Root 批量关闭系统开屏与营销推送
橘子,计算机视觉方向工程师,深耕 AIGC 与多媒体处理领域,专注技术实用化落地。本文为原创内容,转载请注明来源与作者。优快云 首发 | 版权所有 © 2026。
Android 14 SELinux策略深度解析
init 的全局公开约束(如 neverallow init execute_no_trans,放 public 才能约束所有分区的规则)这就是"哪些可见"的强制机制。alps_s0(MTK 工程)的 device/mediatek/sepolicy/basic/ 提供。所有分区(system/system_ext/product/vendor)都可引用。init的公开约束、跨分区共用的 type/attribute/neverallow。——vendor 的 .cil 只能引用 plat 的。
Android 开发入门实践(二):Kotlin 空安全,从可空类型到安全访问
延续 NewsApp 项目中的新闻标题练习,记录 Kotlin 安全调用。
Android 模块化收口:能力组合框架、手写 LifecycleOwner 与热修复共存
二十多个模块业务高度相似却各有差异,核心矛盾在于“统一与灵活”的平衡。通过角色接口组合(如IProjectAware、IVoiceAware)实现能力按需注入,新增功能零侵入;用模板方法锁定生命周期流程,确保顺序一致;结合@CallSuper与工厂方法,既约束关键逻辑,又保留子类自由。最终实现:骨架统一、填空自由,管得住业务,又不侵入业务。
Android Message源码阅读
本文梳理了Android Handler机制中Message的核心设计:链表结构、消息复用池(sPool)及回收机制,重点解析了异步消息与同步屏障(SyncBarrier)的协同机制。当主线程需优先处理UI绘制等高优先级任务时,系统通过postSyncBarrier插入屏障,使Looper跳过普通同步消息,优先执行标记为异步的UI渲染任务,确保帧率流畅。该机制是保障Android界面响应性的关键技术之一。
1109



被折叠的 条评论
为什么被折叠?



