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
    关注
    不知道你这个问题是否已经解决, 如果还没有解决的话:

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

报告相同问题?

悬赏问题

  • ¥20 求数据集和代码#有偿答复
  • ¥15 关于下拉菜单选项关联的问题
  • ¥15 如何修改pca中的feature函数
  • ¥20 java-OJ-健康体检
  • ¥15 rs485的上拉下拉,不会对a-b<-200mv有影响吗,就是接受时,对判断逻辑0有影响吗
  • ¥15 使用phpstudy在云服务器上搭建个人网站
  • ¥15 应该如何判断含间隙的曲柄摇杆机构,轴与轴承是否发生了碰撞?
  • ¥15 vue3+express部署到nginx
  • ¥20 搭建pt1000三线制高精度测温电路
  • ¥15 使用Jdk8自带的算法,和Jdk11自带的加密结果会一样吗,不一样的话有什么解决方案,Jdk不能升级的情况