botao258 2015-10-30 04:06 采纳率: 50%
浏览 1029

android采集图像并通过(Server端)socket发送时,只能发一次数据,为什么呢?

 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()那段代码里调试了很久还是不行,求解 ?

  • 写回答

1条回答

  • CSDN-Ada助手 CSDN-AI 官方账号 2022-10-25 19:55
    关注
    不知道你这个问题是否已经解决, 如果还没有解决的话:

    如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^
    评论

报告相同问题?

悬赏问题

  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?
  • ¥15 求daily translation(DT)偏差订正方法的代码
  • ¥15 js调用html页面需要隐藏某个按钮