从asynctask捕获android java摄像头

从asynctask捕获android java摄像头,java,android,sockets,camera,udp,Java,Android,Sockets,Camera,Udp,我正在尝试在一个异步任务中执行一个代码,该任务从相机拍摄一张照片,并通过UDP将其发送到服务器100次。但是,PictureCallback没有被调用。有人能帮我吗 这就是我所尝试的: public class MainAsyncTask extends AsyncTask<Void, String, Void> { protected static final String TAG = null; public MainActivity mainAct; public Main

我正在尝试在一个异步任务中执行一个代码,该任务从相机拍摄一张照片,并通过UDP将其发送到服务器100次。但是,PictureCallback没有被调用。有人能帮我吗

这就是我所尝试的:

public class MainAsyncTask extends AsyncTask<Void, String, Void> {

protected static final String TAG = null;
public MainActivity mainAct;

public MainAsyncTask(MainActivity mainActivity)
{
    super();
    this.mainAct = mainActivity;
}

@Override
protected Void doInBackground(Void... params) {
    DatagramSocket clientSocket = null;
    InetAddress IPAddress = null;
    try {
        clientSocket = new DatagramSocket();
        IPAddress = InetAddress.getByName("192.168.1.15");
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    byte [] data;
    DatagramPacket sendPacket;

    try {
        for (int i=0; i < 100; i++)
        {
            publishProgress("");
            File file = new File(Environment.getExternalStorageDirectory()+ File.separator +"img.jpg");
            while (!file.exists() || file.length() == 0);
            Bitmap screen = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory()+ File.separator +"img.jpg");
            ByteArrayOutputStream bytes = new ByteArrayOutputStream();
            screen.compress(Bitmap.CompressFormat.JPEG, 15, bytes);
            data = bytes.toByteArray();
            sendPacket = new DatagramPacket(data, data.length, IPAddress, 3107);
            clientSocket.send(sendPacket);
            file.delete();
        }

        clientSocket.close();


    } catch (Exception e) {
        // TODO Auto-generated catch block
        publishProgress(e.getMessage());
    }
    return null;
}

public static void takeSnapShots(MainActivity mainAct)
{
    PictureCallback jpegCallback = new PictureCallback() {
        public void onPictureTaken(byte[] data, Camera camera) 
        {
            FileOutputStream outStream = null;
            try {
                outStream = new FileOutputStream(Environment.getExternalStorageDirectory()+File.separator+"img"+".jpg");    
                outStream.write(data);
                outStream.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally 
            {
                camera.stopPreview();
                camera.release();
                camera = null;
            }
            Log.d(TAG, "onPictureTaken - jpeg");
        }
        };
    SurfaceView surface = new SurfaceView(mainAct.getApplicationContext());
    Camera camera = Camera.open();
    try {
        camera.setPreviewDisplay(surface.getHolder());
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    camera.startPreview();
    camera.takePicture(null,null,jpegCallback);
}


protected void onProgressUpdate(String... progress) {
    takeSnapShots(mainAct);
}

@Override
protected void onPostExecute(Void result)
{
}
公共类MainAsyncTask扩展了AsyncTask{
受保护的静态最终字符串标记=null;
公共活动法;
公共MainAsyncTask(MainActivity MainActivity)
{
超级();
this.mainAct=mainActivity;
}
@凌驾
受保护的Void doInBackground(Void…参数){
DatagramSocket clientSocket=null;
InetAddress IPAddress=null;
试一试{
clientSocket=newdatagramsocket();
IPAddress=InetAddress.getByName(“192.168.1.15”);
}捕获(例外e){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
字节[]数据;
数据包发送包;
试一试{
对于(int i=0;i<100;i++)
{
出版进度(“”);
File File=新文件(Environment.getExternalStorageDirectory()+File.separator+“img.jpg”);
而(!file.exists()| | file.length()==0);
位图屏幕=位图工厂.decodeFile(Environment.getExternalStorageDirectory()+File.separator+“img.jpg”);
ByteArrayOutputStream字节=新建ByteArrayOutputStream();
screen.compress(位图.CompressFormat.JPEG,15,字节);
数据=字节。toByteArray();
sendPacket=新数据包(data,data.length,IPAddress,3107);
clientSocket.send(sendPacket);
delete();
}
clientSocket.close();
}捕获(例外e){
//TODO自动生成的捕捉块
发布进度(如getMessage());
}
返回null;
}
公共静态无效快照(MainActivity mainAct)
{
PictureCallback jpegCallback=新建PictureCallback(){
公共void onPictureTaken(字节[]数据,摄像头)
{
FileOutputStream扩展流=null;
试一试{
outStream=新文件OutputStream(Environment.getExternalStorageDirectory()+File.separator+“img”+“.jpg”);
外扩。写入(数据);
exptream.close();
}catch(filenotfounde异常){
e、 printStackTrace();
}捕获(IOE异常){
e、 printStackTrace();
}最后
{
camera.stopPreview();
相机。释放();
摄像机=零;
}
Log.d(标签“onPictureTaken-jpeg”);
}
};
SurfaceView surface=新的SurfaceView(mainAct.getApplicationContext());
Camera=Camera.open();
试一试{
camera.setPreviewDisplay(surface.getHolder());
}捕获(IOE异常){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
camera.startPreview();
拍照(空、空、JPEG);
}
受保护的void onProgressUpdate(字符串…进度){
takeSnapShots(mainAct);
}
@凌驾
受保护的void onPostExecute(void结果)
{
}

}您是否像这样调用异步任务?仅仅创建AsyncTask是不够的

new MainAsyncTask(ActivityContext).execute();
你不能这么做

camera.setPreviewDisplay(surface.getHolder());
从文档中:

调用此方法时,SurfaceHolder必须已经包含曲面。如果使用SurfaceView,则需要使用addCallback(SurfaceHolder.Callback)注册SurfaceHolder.Callback,并在调用setPreviewDisplay()或启动预览之前等待surfaceCreated(SurfaceHolder)

你必须这样做:

SurfaceHolder surfaceHolder = surface.getHolder();
surfaceHolder.addCallback(new Callback() {
        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            try {
                camera.setPreviewDisplay(holder);
                camera.startPreview();
                camera.takePicture(null,null,jpegCallback);
            } catch (IOException e) {
            }
        }
        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {}
    }
);

我不认为
AsyncTask
是做这项工作最方便的工具

您需要一个
SurfaceView
,它不是凭空创建的,而是连接到屏幕上的。您应该只初始化相机一次,并且不能在循环中调用
camera.takePicture()
。您可以从
onPictureTaken()
回调调用
takePicture()
,但还应该记住,您不能从UI线程使用套接字。幸运的是,你可以遵循谷歌的建议

如图所示,如果在新HandlerThread中打开camera,图片回调将到达beckground线程,该线程也可用于联网

此外,我建议您直接发送从相机接收的JPEG缓冲区。我认为将图像保存到文件、将文件读取到位图以及将位图压缩到另一个JPEG的开销可能太大了。要控制图像大小。请注意,应从中选择尺寸


上面的类是从几个项目编译而来的,为了简洁起见,错误检查减少到最小。它可能需要一些修复来编译。您只需将一个
添加到您的活动布局中,并在用户单击按钮或其他东西时调用它的
拍摄图片。

是的,那么我需要做什么?
public class CameraView extends SurfaceView 
    implements SurfaceHolder.Callback, Camera.PictureCallback {

    private static final String TAG = "CameraView";

    private Camera camera;
    private HandlerThread cameraThread;
    private Handler handler;
    private boolean bCameraInitialized = false;
    private int picturesToTake = 0;

    public CameraView(Context context, AttributeSet attr) {
        super(context, attr);

        // install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        getHolder().addCallback(this);
    }

    @Override public void surfaceCreated(SurfaceHolder holder) {
        cameraThread = new HandlerThread("CameraHandlerThread");
        cameraThread.start();
        handler = new Handler(cameraThread.getLooper());
        hanlder.post(new Runnable() {
            @Override public void run() {
                openRearCamera();
                bCameraInitialized = false;
            }
        });
    }

    @Override public void surfaceDestroyed(SurfaceHolder holder) {
        if (camera != null) {
            Log.d(TAG, "Camera release");
            camera.release();
            camera = null;
            bCameraInitialized = false;
        }
    }

    // finalize the camera init now that we know preview size
    @Override public void surfaceChanged(SurfaceHolder holder, int format, final int w, final int h) {
        Log.w(TAG, "surfaceChanged(" + w + ", " + h + ")");
        if (!bCameraInitialized) {
            cameraSetup(w, h);
            bCameraInitialized = true;
        }
    }

    private void openRearCamera() {
        if (camera != null) {
            Log.e(TAG, "openRearCamera(): camera is not null");
            return;
        }
        try {
            camera = Camera.open(0);
            Log.d(TAG, "Camera ready " + String.valueOf(camera));
        }
        catch (Throwable e) {
            Log.e(TAG, "openRearCamera(): Camera.open() failed", e);
        }
    }

    private void cameraSetup(int w, int h) {

        if (camera == null) {
            Log.e(TAG, "cameraSetup(): camera is null");
            return;
        }

        Log.d(TAG, "Camera setup");
        try {
            Camera.Parameters params = camera.getParameters();

            // still picture settings - be close to preview size
            Camera.Size pictureSize = params.getSupportedPictureSizes()[0];
            params.setPictureSize(pictureSize.width, optimalPictureSize.height);

            camera.setParameters(params);
            camera.setPreviewDisplay(getHolder());
            camera.startPreview();
        }
        catch (Throwable e) {
            Log.e(TAG, "Failed to finalize camera setup", e);
        }
    }

    private void sendJpeg(byte[] data) {
        DatagramSocket clientSocket = null;
        InetAddress IPAddress = null;
        try {
            clientSocket = new DatagramSocket();
            IPAddress = InetAddress.getByName("192.168.1.15");
        }
        catch (Exception e) {
            Log.e(TAG, "failed to initialize client socket", e);
        }
        DatagramPacket sendPacket;
        sendPacket = new DatagramPacket(data, data.length, IPAddress, 3107);
        clientSocket.send(sendPacket);
        Log.d(TAG, "sent image");
    }

    @Override public void onPictureTaken(byte[] data, Camera camera) {
        sendJpeg(data);
        camera.startPreview();
        takePictures(picturesToTake-1);
    }

    public void takePictures(int n) {
        if (n > 0) {
            picturesToTake = n;
            Log.d(TAG, "take " + n + " images");
            camera.takePicture(null, null, this);
        }
        else {
            Log.d(TAG, "all images captured");
        }
    }
}