public class MainActivity extends ActionBarActivity {
private EditText edOwnPort;
private TextView tvOwnIP;
SurfaceView sView;
SurfaceHolder surfaceHolder;
int screenWidth,screenHeight;
Camera camera;
boolean isPreview=false;
private String ipname;
@Override
protected void onCreate(Bundle savedInstanceState) {
//设置全屏
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
edOwnPort=(EditText)findViewById(R.id.edOwnPort);
tvOwnIP=(TextView)findViewById(R.id.tvOwnIP);
sView=(SurfaceView)findViewById(R.id.sView);
surfaceHolder=sView.getHolder();//获得surfaceview的surfaceHolder
screenWidth=640;
screenHeight=480;
ipname=getLocalIpAddress();
tvOwnIP.setText(ipname);
//为surfaceHolder添加一个回调监听器
surfaceHolder.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
initCamera();//初始化摄像头,并打开摄像头
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
//如果camera不为null,释放摄像头
if (camera!=null){
if (isPreview)
camera.stopPreview();
camera.release();
camera=null;
}
System.exit(0);//退出程序
}
});
//设置该SurfaceView自己不维护缓冲
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
private String getLocalIpAddress() { //获取本机IP地址
try{
for (Enumeration<NetworkInterface> en=NetworkInterface.getNetworkInterfaces();en.hasMoreElements();){
NetworkInterface intf=en.nextElement();
for (Enumeration<InetAddress> enumlpAddr=intf.getInetAddresses();enumlpAddr.hasMoreElements();){
InetAddress inetAddress=enumlpAddr.nextElement();
if (!inetAddress.isLoopbackAddress()){
return inetAddress.getHostAddress().toString();
}
}
}
}catch (SocketException ex){
Log.e("WifiPreference Ip",ex.toString());
}
return null;
}
private void initCamera(){
if (!isPreview){
camera=Camera.open();//打开摄像头
}
if (camera!=null&&!isPreview){//摄像头已打开,但还没有进行预览
try{
Camera.Parameters parameters=camera.getParameters();
parameters.setPreviewSize(screenWidth, screenHeight);//设置预览照片的大小
parameters.setPreviewFpsRange(20, 30);//设置每秒显示20~30帧
parameters.setPictureFormat(ImageFormat.NV21);//设置图片格式
parameters.setPictureSize(screenWidth, screenHeight);//设置照片的大小
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);//设置对焦模式
camera.setPreviewDisplay(surfaceHolder);//通过SurfaceView显示取景画面
camera.setPreviewCallback(new StreamIt(ipname));//设置回调 的类
camera.setDisplayOrientation(90);//让预览图像旋转90°,手机camera sensor默认是横屏
camera.startPreview();//开始预览
}catch (Exception e){
e.printStackTrace();
}
isPreview=true;//开启预览后,给预览标志符true
}
}
class StreamIt implements Camera.PreviewCallback{
private String ipname;
public StreamIt(String ipname){
this.ipname=ipname;
}
@Override
public void onPreviewFrame(byte[] data,Camera camera){
Size size=camera.getParameters().getPreviewSize();
try{
YuvImage image=new YuvImage(data,ImageFormat.NV21,size.width,size.height,null);
if (image!=null){
ByteArrayOutputStream outstream=new ByteArrayOutputStream();
image.compressToJpeg(new Rect(0,0,size.width,size.height),80,outstream);
outstream.flush();
Thread th=new MyThread(outstream,ipname);
th.start();
}
}catch (Exception ex){
Log.e("Sys", "Error:" + ex.getMessage());
}
}
}
class MyThread extends Thread{
private int Port=Integer.parseInt(edOwnPort.getText().toString());
private byte byteBuffer[]=new byte[1024];
private OutputStream outsocket;
private ByteArrayOutputStream myoutputstream;
private String ipname;
private ServerSocket ss;
private Socket tempSocket;
public MyThread(ByteArrayOutputStream myoutputstream,String ipname){
this.myoutputstream=myoutputstream;
this.ipname=ipname;
try{
myoutputstream.close();
}catch (IOException e){
e.printStackTrace();
}
}
public void run(){
try{
ss=new ServerSocket(Port);
tempSocket = ss.accept();
outsocket = tempSocket.getOutputStream();//socket获得输出流
ByteArrayInputStream inputStream=new ByteArrayInputStream(myoutputstream.toByteArray());
int amount;
while ((amount=inputStream.read(byteBuffer))!=-1){ //这个方法是先规定一个数组长度,将这个流中的字节缓冲到数组byteBuffer中,返回的是这个数组中的字节个数,这个缓冲区没有满的话,则返回真实的字节个数,到未尾时都返回-1
outsocket.write(byteBuffer,0,amount); //write(byte[] b, int off, int len): 将指定 byteBuffer数组中从偏移量 off 开始的 len 个字节写入此输出流,此处是: 上面把myoutputstream->inputStream->byteBuffer,并获得长度amount->把byteBuffer写入输出流outsocket
}
myoutputstream.flush();
//myoutputstream.reset();
myoutputstream.close();
//tempSocket.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
想实现的是,一启动程序就进入一直预览的状态,并等待socket的连接请求,一旦有请求过来,server端新建立一个socket去通信,然后将获取的每一帧图像,完整的通过socket发送出去,现在是可以实现预览,但连上socket后只发一次图像数据就没动静了,这时什么原因,在run()那段代码里调试了很久还是不行,求解 ?