Android之网络摄像头

时间:2022-12-24 16:24:05

实现的功能就是两个手机在一个局域网内可以互相观看对方的摄像头图像,当然如果都是连接公网那么就能远程互看了,,,,和视频聊天差不多,,不过没有声音,,,,,,,,

源码是在网上找的(具体地址忘了,如有侵犯请告知),亲测能用,,其实一开始想直接用到自己现在做的东西上 ,不过直接加到自己现在的软件上,调试了一下发现,,我想多了Android之网络摄像头,老天总是不让自己那么轻易的.......................

因为自己手头上只有一个手机,所以就自己发给自己了,本想像写其它文章似得详细叙述一番,看了一下表,,感觉还是算了吧,,昨天把程序加到自己的软件上然后修改,测试一直熬到了1点,然后下午上班的时候头疼,困,然后就睡了1个小时.............年轻人不要老熬夜,,对身体不好,Android之网络摄像头

Android之网络摄像头

上面的是自己的摄像头预览的,

下面的是通过TCP传输过来的

源码如下

Android之网络摄像头

package com.example.realtimevideo;

import java.io.ByteArrayOutputStream;

import com.example.threadConnect.ClientThread;
import com.example.threadConnect.RevImageThread; import android.graphics.Bitmap;
import android.graphics.ImageFormat;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.hardware.Camera.PreviewCallback;
import android.hardware.Camera.Size;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Menu;
import android.view.SurfaceHolder;
import android.view.Window;
import android.view.WindowManager;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.widget.ImageView;
import android.widget.RelativeLayout; public class MainVideoActivity extends Activity{
RevImageThread revImageThread;
public static ImageView image;
private static Bitmap bitmap;
private static final int COMPLETED = 0x222; MyHandler handler;
ClientThread clientThread;
ByteArrayOutputStream outstream; SurfaceView surfaceView;
SurfaceHolder sfh;
Camera camera;
boolean isPreview = false; //是否在浏览中
static int screenWidth=300;
static int screenHeight=300; @Override
protected 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.activity_main_video);
surfaceView = (SurfaceView)findViewById(R.id.surfaceView);
image=(ImageView)findViewById(R.id.imageView1); handler = new MyHandler();
clientThread = new ClientThread();
new Thread(clientThread).start(); revImageThread = new RevImageThread(handler);
new Thread(revImageThread).start(); DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
screenWidth = dm.widthPixels;// 获取屏幕分辨率宽度
screenHeight = dm.heightPixels; image.setLayoutParams(new RelativeLayout.LayoutParams(screenWidth,screenHeight));
//image.setMaxHeight(screenHeight);
//image.setMaxWidth(screenWidth); image.setMaxHeight(screenHeight/2);
sfh = surfaceView.getHolder();
sfh.setFixedSize(screenWidth, screenHeight/2); sfh.addCallback(new Callback(){ @Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2,
int arg3) {
// TODO Auto-generated method stub } @Override
public void surfaceCreated(SurfaceHolder arg0) {
// TODO Auto-generated method stub
initCamera();
} @Override
public void surfaceDestroyed(SurfaceHolder arg0) {
if (camera != null) {
if (isPreview) camera.stopPreview();
camera.release();
camera = null;
} } }); } @Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main_video, menu);
return true;
} @SuppressWarnings("deprecation")
private void initCamera() {
if (!isPreview) {
int k = 0;
if((k=FindBackCamera())!=-1){
camera = Camera.open(k);
}else{
camera = Camera.open();
}
ClientThread.size = camera.getParameters().getPreviewSize();
}
if (camera != null && !isPreview) {
try{
camera.setPreviewDisplay(sfh); // 通过SurfaceView显示取景画面
Camera.Parameters parameters = camera.getParameters();
parameters.setPreviewSize(screenWidth, screenHeight/4*3);
/* 每秒从摄像头捕获5帧画面, */
parameters.setPreviewFrameRate(5);
parameters.setPictureFormat(ImageFormat.NV21); // 设置图片格式
parameters.setPictureSize(screenWidth, screenHeight/4*3); // 设置照片的大小
camera.setDisplayOrientation(90);
camera.setPreviewCallback(new PreviewCallback(){
@Override
public void onPreviewFrame(byte[] data, Camera c) {
// TODO Auto-generated method stub
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){
Message msg = clientThread.revHandler.obtainMessage();
msg.what=0x111;
msg.obj=image;
clientThread.revHandler.sendMessage(msg);
}
}catch(Exception ex){
Log.e("Sys","Error:"+ex.getMessage());
}
} });
camera.startPreview(); // 开始预览
camera.autoFocus(null); // 自动对焦
} catch (Exception e) {
e.printStackTrace();
}
isPreview = true;
}
} static class MyHandler extends Handler{
@Override
public void handleMessage(Message msg){
if (msg.what == COMPLETED) {
bitmap = (Bitmap)msg.obj; //image.setPivotX(image.getWidth()/2);
//image.setPivotX(image.getHeight()/2); //image.setImageBitmap(bitmap);
image.setLayoutParams(new RelativeLayout.LayoutParams(screenWidth,screenHeight));
image.setImageBitmap(bitmap);
image.setRotation(90);
super.handleMessage(msg);
}
}
} //调用前置摄像头
private int FindFrontCamera(){
int cameraCount = 0;
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
cameraCount = Camera.getNumberOfCameras(); // get cameras number for ( int camIdx = 0; camIdx < cameraCount;camIdx++ ) {
Camera.getCameraInfo( camIdx, cameraInfo ); // get camerainfo
if ( cameraInfo.facing ==Camera.CameraInfo.CAMERA_FACING_FRONT ) {
// 代表摄像头的方位,目前有定义值两个分别为CAMERA_FACING_FRONT前置和CAMERA_FACING_BACK后置
return camIdx;
}
}
return -1;
} //调用后置摄像头
private int FindBackCamera(){
int cameraCount = 0;
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
cameraCount = Camera.getNumberOfCameras(); // get cameras number for ( int camIdx = 0; camIdx < cameraCount;camIdx++ ) {
Camera.getCameraInfo( camIdx, cameraInfo ); // get camerainfo
if ( cameraInfo.facing ==Camera.CameraInfo.CAMERA_FACING_BACK ) {
// 代表摄像头的方位,目前有定义值两个分别为CAMERA_FACING_FRONT前置和CAMERA_FACING_BACK后置
return camIdx;
}
}
return -1;
}
}

Android之网络摄像头

package com.example.threadConnect;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.Socket; import android.graphics.Rect;
import android.graphics.YuvImage;
import android.hardware.Camera.Size;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log; public class ClientThread implements Runnable {
private static Socket socket ;
private static ByteArrayOutputStream outputstream;
private static byte byteBuffer[] = new byte[1024];
public static Size size; //接受UI线程消息
public MyHandler revHandler; BufferedReader br= null;
static OutputStream os = null; @Override
public void run() {
Looper.prepare();
//接受UI发来的信息
revHandler = new MyHandler();
Looper.loop();
} public static class MyHandler extends Handler{
@Override
public void handleMessage(Message msg){
if(msg.what==0x111){
try {
socket = new Socket("192.168.3.10",8081);
os = socket.getOutputStream();
YuvImage image = (YuvImage) msg.obj;
if(socket.isOutputShutdown()){
Log.e("output is down","ljq");
}else{
os = socket.getOutputStream();
outputstream = new ByteArrayOutputStream();
image.compressToJpeg(new Rect(0, 0, size.width, size.height), 80, outputstream);
ByteArrayInputStream inputstream = new ByteArrayInputStream(outputstream.toByteArray());
int amount;
while ((amount = inputstream.read(byteBuffer)) != -1) {
os.write(byteBuffer, 0, amount);
}
os.write("\n".getBytes());
outputstream.flush();
outputstream.close();
os.flush();
os.close();
socket.close();
}
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}

Android之网络摄像头

package com.example.threadConnect;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket; import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message; public class RevImageThread implements Runnable { public Socket s;
public ServerSocket ss; //向UI线程发送消息
private Handler handler; private Bitmap bitmap;
private static final int COMPLETED = 0x222; public RevImageThread(Handler handler){
this.handler = handler;
} public void run()
{
byte [] buffer = new byte[1024];
int len = 0; try {
ss = new ServerSocket(8080);
} catch (IOException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
} InputStream ins = null;
while(true){ try {
s = ss.accept();
ins = s.getInputStream(); ByteArrayOutputStream outStream = new ByteArrayOutputStream();
while( (len=ins.read(buffer)) != -1){
outStream.write(buffer, 0, len);
}
ins.close(); byte data[] = outStream.toByteArray();
bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); Message msg =handler.obtainMessage();
msg.what = COMPLETED;
msg.obj = bitmap;
handler.sendMessage(msg); outStream.flush();
outStream.close();
if(!s.isClosed()){
s.close();
} } catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//Bitmap bitmap = BitmapFactory.decodeStream(ins); }
} }

布局

Android之网络摄像头

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context=".MainVideoActivity" > <SurfaceView
android:id="@+id/surfaceView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="fitCenter"
/>
<ImageView
android:id="@+id/imageView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent" android:src="@drawable/ic_launcher"/>
</RelativeLayout>

权限

Android之网络摄像头

对了关于如何使用

这个程序把发送图像和接收图像做在了一块了

其实只有知道TCP通信应该就会用,,不对源程序没提供地址输入框,,,,,,,后期自己加上了,不过现在感觉需要修改,因为源程序是不停的申请不停的释放,,,,,,

Android之网络摄像头

Android之网络摄像头

未完,,待续,,改好了就把自己完善的代码奉上, 加详细解释,一步一步的写出来Android之网络摄像头..................

Android之网络摄像头的更多相关文章

  1. Android IOS WebRTC 音视频开发总结(八十五)-- 使用WebRTC广播网络摄像头视频(下)

    本文主要介绍WebRTC (我们翻译和整理的,译者:weizhenwei,校验:blacker),最早发表在[编风网] 支持原创,转载必须注明出处,欢迎关注我的微信公众号blacker(微信ID:bl ...

  2. Android IOS WebRTC 音视频开发总结(八十三)-- 使用WebRTC广播网络摄像头视频(上)

    本文主要介绍WebRTC (我们翻译和整理的,译者:weizhenwei,校验:blacker),最早发表在[编风网] 支持原创,转载必须注明出处,欢迎关注我的微信公众号blacker(微信ID:bl ...

  3. 抓住&OpenCurlyDoubleQuote;新代码”的影子 —— 基于GoAhead系列网络摄像头多个漏洞分析

    PDF 版本下载:抓住“新代码”的影子 —— 基于GoAhead系列网络摄像头多个漏洞分析 Author:知道创宇404实验室 Date:2017/03/19 一.漏洞背景 GoAhead作为世界上最 ...

  4. Android okHttp网络请求之Json解析

    前言: 前面两篇文章介绍了基于okHttp的post.get请求,以及文件的上传下载,今天主要介绍一下如何和Json解析一起使用?如何才能提高开发效率? okHttp相关文章地址: Android o ...

  5. Android okHttp网络请求之Get&sol;Post请求

    前言: 之前项目中一直使用的Xutils开源框架,从xutils 2.1.5版本使用到最近的xutils 3.0,使用起来也是蛮方便的,只不过最近想着完善一下app中使用的开源框架,由于Xutils里 ...

  6. Android okHttp网络请求之文件上传下载

    前言: 前面介绍了基于okHttp的get.post基本使用(http://www.cnblogs.com/whoislcj/p/5526431.html),今天来实现一下基于okHttp的文件上传. ...

  7. Android okHttp网络请求之缓存控制Cache-Control

    前言: 前面的学习基本上已经可以完成开发需求了,但是在项目中有时会遇到对请求做个缓存,当没网络的时候优先加载本地缓存,基于这个需求我们来学习一直okHttp的Cache-Control. okHttp ...

  8. Android okHttp网络请求之Retrofit&plus;Okhttp&plus;RxJava组合

    前言: 通过上面的学习,我们不难发现单纯使用okHttp来作为网络库还是多多少少有那么一点点不太方便,而且还需自己来管理接口,对于接口的使用的是哪种请求方式也不能一目了然,出于这个目的接下来学习一下R ...

  9. Android检测网络是否正常代码!

    在Android开发中,如果该应用程序需要连接网络请求,那么最好我们先做一个检测网络是否在线的判断,否则程序容易出现卡死或FC等Bug,应该判断如果手机离线则弹出提示让用户检查网络,如果正常则继续执行 ...

随机推荐

  1. Windows下PowerShell监控Keepalived

    一.背景 某数据库服务器为CentOS,想要监控Keepalived的VIP是否有问题,通过邮件进行报警,但这台机器不能上外网,现在只能在Windows下通过PowerShell来完成发邮件预警. 二 ...

  2. Android笔记——关于Cursor类的介绍

    使用过 SQLite数据库的童鞋对 Cursor 应该不陌生,加深自己和大家对Android 中使用 Cursor 的理解. 关于 Cursor 在你理解和使用 Android Cursor 的时候你 ...

  3. eclipse &plus;maven&plus;ssm搭建矿建

    记录一下搭建框架的过程1.下载最新的eclipse   https://www.eclipse.org/downloads/download.php?file=/oomph/epp/neon/R/ec ...

  4. python基础——枚举类

    python基础——枚举类 当我们需要定义常量时,一个办法是用大写变量通过整数来定义,例如月份: JAN = 1 FEB = 2 MAR = 3 ... NOV = 11 DEC = 12 好处是简单 ...

  5. c&plus;&plus;取小数整数部分

    #include<math.h> double ceil(double x) //向上取整 double floor(double x) //向下取整 向上取整,取比x大的第一个整数值向下 ...

  6. hdu 4300 Clairewd’s message KMP应用

    Clairewd’s message 题意:先一个转换表S,表示第i个拉丁字母转换为s[i],即a -> s[1];(a为明文,s[i]为密文).之后给你一串长度为n<= 100000的前 ...

  7. Codeforces Round &num;343 &lpar;Div&period; 2&rpar; D - Babaei and Birthday Cake 线段树&plus;DP

    题意:做蛋糕,给出N个半径,和高的圆柱,要求后面的体积比前面大的可以堆在前一个的上面,求最大的体积和. 思路:首先离散化蛋糕体积,以蛋糕数量建树建树,每个节点维护最大值,也就是假如节点i放在最上层情况 ...

  8. poj 2054 Color a Tree&lpar;贪婪&rpar;

    # include <stdio.h> # include <algorithm> # include <string.h> using namespace std ...

  9. iwebshop两表联查

    $tb_goods = new IQuery('goods as g'); $tb_goods->join='left join miao as m on m.goods_id=g.id'; $ ...

  10. Java方法参数的传递方式

    程序设计语言中,将参数传递给方法(或函数)有两种方法.按值传递(call by value)表示方法接受的是调用者提供的值:按引用调用(call by reference)表示方法接受的是调用者提供的 ...