android使用socket实现实时视频
2015-08-14 11:19
381 查看
该视频实现是基于TCP/IP协议的Socket(客户端)和ServerSocket(服务端)类,发送视频也就是不间断的发送图片。具体如下:
PC服务端:socketService类开启服务及监听,线程类TheadServer处理socket连接,并调用另外一个线程类ThreadClient发送图片到到另外一台手机上
视频发送端:MainVideoActivity为显示界面,子线程ClientThread处理图片并发送到服务器
视频接受端:MainActivity为显示界面,子线程RevImageThread为接受服务端发送过来的图片
PC端socketService类:
packagecom.socket;
importjava.io.IOException;
importjava.net.ServerSocket;
importjava.net.Socket;
publicclasssocketService{
/**
*@paramargs
*@throwsIOException
*/
publicstaticvoidmain(String[]args)throwsIOException{
ServerSocketss=newServerSocket(3000);
System.out.println("begin");
while(true){
newThread(newTheadServer(ss)).start();
}
}
}
TheadServer类:
ThreadClient类:
视频发送端:
MainVideoActivity类
ClientThread类:
布局:
视频接受端:
MainActivity:
RevImageThread类:
布局:
PC服务端:socketService类开启服务及监听,线程类TheadServer处理socket连接,并调用另外一个线程类ThreadClient发送图片到到另外一台手机上
视频发送端:MainVideoActivity为显示界面,子线程ClientThread处理图片并发送到服务器
视频接受端:MainActivity为显示界面,子线程RevImageThread为接受服务端发送过来的图片
PC端socketService类:
packagecom.socket;
importjava.io.IOException;
importjava.net.ServerSocket;
importjava.net.Socket;
publicclasssocketService{
/**
*@paramargs
*@throwsIOException
*/
publicstaticvoidmain(String[]args)throwsIOException{
ServerSocketss=newServerSocket(3000);
System.out.println("begin");
while(true){
newThread(newTheadServer(ss)).start();
}
}
}
TheadServer类:
packagecom.socket;
importjava.awt.Image;
importjava.awt.image.BufferedImage;
importjava.io.IOException;
importjava.io.InputStream;
importjava.io.InputStreamReader;
importjava.io.OutputStream;
importjava.net.ServerSocket;
importjava.net.Socket;
importjavax.imageio.ImageIO;
publicclassTheadServerimplementsRunnable{
privateSockets=null;
privateBufferedImagebufferedImage;
publicInputStreamins;
publicTheadServer(ServerSocketss)throwsIOException{
System.out.println("startthread");
this.s=ss.accept();
}
@Override
publicvoidrun(){
try{
ins=s.getInputStream();
bufferedImage=ImageIO.read(ins);
ins.close();
ThreadClienttc=newThreadClient(bufferedImage);
newThread(tc).start();
}catch(IOExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}finally{
try{
if(!s.isClosed())
s.close();
}catch(IOExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
}
}
ThreadClient类:
packagecom.socket;
importjava.awt.Image;
importjava.awt.image.BufferedImage;
importjava.awt.image.RenderedImage;
importjava.io.ByteArrayOutputStream;
importjava.io.IOException;
importjava.io.ObjectOutputStream;
importjava.io.OutputStream;
importjava.io.Serializable;
importjava.net.InetSocketAddress;
importjava.net.Socket;
importjavax.imageio.ImageIO;
publicclassThreadClientimplementsRunnable,Serializable{
privateBufferedImagebufferedImage;
publicThreadClient(BufferedImageimage){
this.bufferedImage=image;
}
@Override
publicvoidrun(){
//TODOAuto-generatedmethodstub
try{
Sockets=newSocket();
//接受视频端IP和端口
s.connect(newInetSocketAddress("10.0.56.234",40000),2000);
if(s.isConnected()&&!s.isClosed()){
System.out.println("Client:"+s.getRemoteSocketAddress().toString());
OutputStreamoos=s.getOutputStream();
ImageIO.write(bufferedImage,"JPG",oos);
oos.write("\n".getBytes());
oos.flush();
oos.close();
s.close();
}
}catch(IOExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
}
视频发送端:
MainVideoActivity类
packagecom.example.realtimevideo;
importjava.io.ByteArrayOutputStream;
importcom.example.threadConnect.ClientThread;
importandroid.graphics.ImageFormat;
importandroid.graphics.Rect;
importandroid.graphics.YuvImage;
importandroid.hardware.Camera;
importandroid.hardware.Camera.PreviewCallback;
importandroid.hardware.Camera.Size;
importandroid.os.Bundle;
importandroid.os.Handler;
importandroid.os.Message;
importandroid.app.Activity;
importandroid.util.DisplayMetrics;
importandroid.util.Log;
importandroid.view.Menu;
importandroid.view.SurfaceHolder;
importandroid.view.View;
importandroid.view.View.OnClickListener;
importandroid.view.Window;
importandroid.view.WindowManager;
importandroid.view.SurfaceHolder.Callback;
importandroid.view.SurfaceView;
importandroid.widget.Button;
publicclassMainVideoActivityextendsActivity{
MyHandlerhandler;
ClientThreadclientThread;
ByteArrayOutputStreamoutstream;
Buttonstart;
Buttonstop;
SurfaceViewsurfaceView;
SurfaceHoldersfh;
Cameracamera;
booleanisPreview=false;//是否在浏览中
intscreenWidth=300,screenHeight=300;
@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
//设置全屏
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_main_video);
handler=newMyHandler();
clientThread=newClientThread(handler);
newThread(clientThread).start();
DisplayMetricsdm=newDisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
screenWidth=dm.widthPixels;//获取屏幕分辨率宽度
screenHeight=dm.heightPixels;
start=(Button)findViewById(R.id.start);
stop=(Button)findViewById(R.id.stop);
surfaceView=(SurfaceView)findViewById(R.id.surfaceView);
sfh=surfaceView.getHolder();
sfh.setFixedSize(screenWidth,screenHeight/4*3);
sfh.addCallback(newCallback(){
@Override
publicvoidsurfaceChanged(SurfaceHolderarg0,intarg1,intarg2,
intarg3){
//TODOAuto-generatedmethodstub
}
@Override
publicvoidsurfaceCreated(SurfaceHolderarg0){
//TODOAuto-generatedmethodstub
initCamera();
}
@Override
publicvoidsurfaceDestroyed(SurfaceHolderarg0){
if(camera!=null){
if(isPreview)
camera.stopPreview();
camera.release();
camera=null;
}
}
});
//开启连接服务
start.setOnClickListener(newOnClickListener(){
@Override
publicvoidonClick(Viewarg0){
start.setEnabled(false);
}
});
}
@Override
publicbooleanonCreateOptionsMenu(Menumenu){
//Inflatethemenu;thisaddsitemstotheactionbarifitispresent.
getMenuInflater().inflate(R.menu.main_video,menu);
returntrue;
}
@SuppressWarnings("deprecation")
privatevoidinitCamera(){
if(!isPreview){
camera=Camera.open();
ClientThread.size=camera.getParameters().getPreviewSize();
}
if(camera!=null&&!isPreview){
try{
camera.setPreviewDisplay(sfh);//通过SurfaceView显示取景画面
Camera.Parametersparameters=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(newPreviewCallback(){
@Override
publicvoidonPreviewFrame(byte[]data,Camerac){
//TODOAuto-generatedmethodstub
Sizesize=camera.getParameters().getPreviewSize();
try{
//调用image.compressToJpeg()将YUV格式图像数据data转为jpg格式
YuvImageimage=newYuvImage(data,ImageFormat.NV21,size.width,size.height,null);
if(image!=null){
Messagemsg=clientThread.revHandler.obtainMessage();
msg.what=0x111;
msg.obj=image;
clientThread.revHandler.sendMessage(msg);
/*outstream=newByteArrayOutputStream();
image.compressToJpeg(newRect(0,0,size.width,size.height),80,outstream);
outstream.flush();
newThread(clientThread).start();*/
}
}catch(Exceptionex){
Log.e("Sys","Error:"+ex.getMessage());
}
}
});
camera.startPreview();//开始预览
camera.autoFocus(null);//自动对焦
}catch(Exceptione){
e.printStackTrace();
}
isPreview=true;
}
}
staticclassMyHandlerextendsHandler{
@Override
publicvoidhandleMessage(Messagemsg){
if(msg.what==0x222){
//返回信息显示代码
}
}
}
}
ClientThread类:
packagecom.example.threadConnect;
importjava.io.BufferedReader;
importjava.io.ByteArrayInputStream;
importjava.io.ByteArrayOutputStream;
importjava.io.IOException;
importjava.io.InputStreamReader;
importjava.io.OutputStream;
importjava.io.UnsupportedEncodingException;
importjava.net.Socket;
importjava.net.SocketTimeoutException;
importjava.net.UnknownHostException;
importandroid.graphics.Rect;
importandroid.graphics.YuvImage;
importandroid.hardware.Camera.Size;
importandroid.os.Handler;
importandroid.os.Looper;
importandroid.os.Message;
importandroid.util.Log;
publicclassClientThreadimplementsRunnable{
privatestaticSocketsocket;
privatestaticByteArrayOutputStreamoutputstream;
privatestaticbytebyteBuffer[]=newbyte[1024];
publicstaticSizesize;
//向UI线程发送消息
privateHandlerhandler;
//接受UI线程消息
publicMyHandlerrevHandler;
BufferedReaderbr=null;
staticOutputStreamos=null;
publicClientThread(Handlerhandler){
this.handler=handler;
}
@Override
publicvoidrun(){
Looper.prepare();
//接受UI发来的信息
revHandler=newMyHandler();
Looper.loop();
}
publicstaticclassMyHandlerextendsHandler{
@Override
publicvoidhandleMessage(Messagemsg){
if(msg.what==0x111){
try{
socket=newSocket("10.0.56.232",3000);
os=socket.getOutputStream();
YuvImageimage=(YuvImage)msg.obj;
if(socket.isOutputShutdown()){
socket.getKeepAlive();
}else{
os=socket.getOutputStream();
outputstream=newByteArrayOutputStream();
image.compressToJpeg(newRect(0,0,size.width,size.height),80,outputstream);
ByteArrayInputStreaminputstream=newByteArrayInputStream(outputstream.toByteArray());
intamount;
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(UnsupportedEncodingExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}catch(IOExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
}
}
}
布局:
<LinearLayoutxmlns: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="wrap_content"
android:layout_height="wrap_content"
android:scaleType="fitCenter"
/>
<Button
android:id="@+id/start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/start"/>
<Button
android:id="@+id/stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/stop"/>
</LinearLayout>
视频接受端:
MainActivity:
packagecom.example.socketphone;
importandroid.os.Bundle;
importandroid.os.Handler;
importandroid.os.Looper;
importandroid.os.Message;
importandroid.app.Activity;
importandroid.graphics.Bitmap;
importandroid.graphics.BitmapFactory;
importandroid.util.Log;
importandroid.view.Menu;
importandroid.widget.ImageView;
importjava.io.ByteArrayOutputStream;
importjava.io.IOException;
importjava.io.InputStream;
importjava.io.ObjectInputStream;
importjava.net.Socket;
importjava.net.ServerSocket;
importcom.example.Thread.RevImageThread;
publicclassMainActivityextendsActivity{
RevImageThreadrevImageThread;
publicstaticImageViewimage;
privatestaticBitmapbitmap;
privatestaticfinalintCOMPLETED=0x111;
privateMyHandlerhandler;
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
image=(ImageView)findViewById(R.id.imageView1);
handler=newMyHandler();
revImageThread=newRevImageThread(handler);
newThread(revImageThread).start();
}
staticclassMyHandlerextendsHandler{
@Override
publicvoidhandleMessage(Messagemsg){
if(msg.what==COMPLETED){
bitmap=(Bitmap)msg.obj;
image.setImageBitmap(bitmap);
super.handleMessage(msg);
}
}
}
publicbooleanonCreateOptionsMenu(Menumenu){
//Inflatethemenu;thisaddsitemstotheactionbarifitispresent.
getMenuInflater().inflate(R.menu.main,menu);
returntrue;
}
}
RevImageThread类:
packagecom.example.Thread;
importjava.io.ByteArrayOutputStream;
importjava.io.IOException;
importjava.io.InputStream;
importjava.net.ServerSocket;
importjava.net.Socket;
importandroid.graphics.Bitmap;
importandroid.graphics.BitmapFactory;
importandroid.os.Handler;
importandroid.os.Looper;
importandroid.os.Message;
importandroid.util.Log;
publicclassRevImageThreadimplementsRunnable{
publicSockets;
publicServerSocketss;
//向UI线程发送消息
privateHandlerhandler;
privateBitmapbitmap;
privatestaticfinalintCOMPLETED=0x111;
publicRevImageThread(Handlerhandler){
this.handler=handler;
}
publicvoidrun()
{
byte[]buffer=newbyte[1024];
intlen=0;
try{
ss=newServerSocket(40000);
}catch(IOExceptione2){
//TODOAuto-generatedcatchblock
e2.printStackTrace();
}
InputStreamins=null;
while(true){
try{
s=ss.accept();
Log.e("strat","ljq");
ins=s.getInputStream();
ByteArrayOutputStreamoutStream=newByteArrayOutputStream();
while((len=ins.read(buffer))!=-1){
outStream.write(buffer,0,len);
}
ins.close();bytedata[]=outStream.toByteArray();
bitmap=BitmapFactory.decodeByteArray(data,0,data.length);
Messagemsg=handler.obtainMessage();
msg.what=COMPLETED;
msg.obj=bitmap;
handler.sendMessage(msg);
outStream.flush();
outStream.close();
if(!s.isClosed()){
s.close();
}
}catch(IOExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
//Bitmapbitmap=BitmapFactory.decodeStream(ins);
}
}
}
布局:
<RelativeLayoutxmlns: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"
tools:context=".MainActivity">
<ImageView
android:id="@+id/imageView1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher"/>
</RelativeLayout>
相关文章推荐
- android:inputType参数类型说明
- [转]Android Studio 1.3.1环境搭建
- Android应用:Service开发实例(二)之Service的两种创建方法和其生命周期
- android VelocityTracker的简单研究
- Android四大组件-Service并非详解
- android自定义PopWindow底部显示
- android 管理ViewGroup中的触摸事件
- Android中自定义AlertDialog组件
- Android 之 Binder与进程间通信
- android:clipToPadding和android:clipChildren的解析
- android 拖拽与缩放
- Android--多线程之Handler .
- SEAndroid安全机制对Binder IPC的保护分析
- adapter
- android 处理多点触控手势
- Android性能优化Google课程翻译一:Render----OverDraw实战
- SEAndroid安全机制对Android属性访问的保护分析
- SEAndroid安全机制中的文件安全上下文关联分析
- Android应用开发原理之从源码分析看Linearlayout、Relativelayout,Framelayout的布局差别(Linearlayout分析)
- android 滚动手势动画