Делать снимки в андроиде каждые 5 секунд

Используя API камеры, я могу успешно сделать снимок и сохранить его в папку. Вот код, который я использую:

Основной.xml:

<FrameLayout
        android:id="@+id/camera_preview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_weight="1" />

    <Button
        android:id="@+id/button_capture"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="Capture" />

Вспомогательный класс:

import java.io.IOException;

import android.content.Context;
import android.hardware.Camera;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class CameraPreview extends SurfaceView implements
        SurfaceHolder.Callback {
    private SurfaceHolder mSurfaceHolder;
    private Camera mCamera;

    // Constructor that obtains context and camera
    @SuppressWarnings("deprecation")
    public CameraPreview(Context context, Camera camera) {
        super(context);
        this.mCamera = camera;
        this.mSurfaceHolder = this.getHolder();
        this.mSurfaceHolder.addCallback(this);
        this.mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {
        try {
            mCamera.setPreviewDisplay(surfaceHolder);
            mCamera.setDisplayOrientation(90);
            mCamera.startPreview();
        } catch (IOException e) {
            // left blank for now
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
        mCamera.stopPreview();
        mCamera.release();
    }

    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int format,
            int width, int height) {
        // start preview with new settings
        try {
            mCamera.setPreviewDisplay(surfaceHolder);
            mCamera.startPreview();
        } catch (Exception e) {
            // intentionally left blank for a test
        }
    }

}

Класс активности:

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;

public class MyCamera extends Activity {
    private Camera mCamera;
    private CameraPreview mCameraPreview;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mCamera = getCameraInstance();
        mCameraPreview = new CameraPreview(this, mCamera);
        FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
        preview.addView(mCameraPreview);

        Button captureButton = (Button) findViewById(R.id.button_capture);
        captureButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mCamera.takePicture(null, null, mPicture);
            }
        });
    }

    /**
     * Helper method to access the camera returns null if it cannot get the
     * camera or does not exist
     * 
     * @return
     */
    private Camera getCameraInstance() {
        Camera camera = null;
        try {
            camera = Camera.open();
        } catch (Exception e) {
            // cannot get camera or does not exist
        }
        return camera;
    }

    PictureCallback mPicture = new PictureCallback() {
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            File pictureFile = getOutputMediaFile();
            if (pictureFile == null) {
                return;
            }
            try {
                FileOutputStream fos = new FileOutputStream(pictureFile);
                fos.write(data);
                fos.close();
            } catch (FileNotFoundException e) {

            } catch (IOException e) {
            }
        }

    };

    private static File getOutputMediaFile() {
        File mediaStorageDir = new File(
                Environment
                        .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
                "MyCameraApp");
        if (!mediaStorageDir.exists()) {
            if (!mediaStorageDir.mkdirs()) {
                Log.d("MyCameraApp", "failed to create directory");
                return null;
            }
        }
        // Create a media file name
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
                .format(new Date());
        File mediaFile;
        mediaFile = new File(mediaStorageDir.getPath() + File.separator
                + "IMG_" + timeStamp + ".jpg");

        return mediaFile;
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.my_camera, menu);
        return true;
    }

}

Я также добавил в файл манифеста следующее:

<uses-feature android:name="android.hardware.camera" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

У меня есть следующие проблемы:

Я хочу сделать следующее:

  1. После нажатия кнопки захвата я хочу, чтобы камера автоматически продолжала делать снимки каждые 5 секунд, используя таймер обратного отсчета. Поэтому я добавил следующее:

    while(true){
       new CountDownTimer(5000,1000){
    
                @Override
                public void onFinish() {
                    mCamera.takePicture(null, null, mPicture);
                }
    
                @Override
                public void onTick(long millisUntilFinished) {
    
                }
    
            }.start();
    }
    

Тем не менее, я больше не получаю изображение. Я добавил while(true), чтобы код не повторялся. Я пробовал это без while (true), и, как и ожидалось, захват изображения задерживается на 5 секунд.

Во-вторых: как я могу изменить качество захваченных изображений?

Любая помощь будет оценена.


person user2262955    schedule 13.04.2014    source источник
comment
Привет, пользователь 2262955, не могли бы вы выложить рабочий пример этого на github? спасибо   -  person Amir    schedule 06.05.2016


Ответы (2)


Удалите while(true), он вам не нужен, и вы создадите неограниченное количество таймеров обратного отсчета.

Измените начало обратного отсчета на это

new CountDownTimer(5000,1000){

    @Override
    public void onFinish() {

    }

    @Override
    public void onTick(long millisUntilFinished) {
        mCamera.startPreview();
        mCamera.takePicture(null, null, mPicture);
    }

}.start();

В этом случае onTick вызывается каждые 1000 мс, а onFinish вызывается по завершении обратного отсчета таймера.

Если вы хотите повторять что-то каждые 5 секунд, я не думаю, что CountDownTimer соответствует вашим потребностям... Timer было бы лучше.

Timer timer = new Timer();
timer.schedule(new TimerTask()
{
    @Override
    public void run()
    {
        mCamera.startPreview();
        mCamera.takePicture(null, null, mPicture);
    }
}, 0, 1000);

Не забудьте сохранить Timer экземпляр, чтобы остановить его!

person Marco Acierno    schedule 13.04.2014
comment
Может быть потому, что для того, чтобы сделать больше снимков, вы должны сначала вызвать startPreview(). -- См. обновленный ответ. - person Marco Acierno; 13.04.2014
comment
С таймером раньше не работал. Я получаю сообщение «Источник не найден: вложение источника не содержит источник файла Timer.class». - person user2262955; 13.04.2014
comment
Вы добавили import java.util.Timer; и java.util.TimerTask? - person Marco Acierno; 13.04.2014
comment
Ваша проблема вызвана Eclipse, я нашел ее для вас stackoverflow.com/questions/13369170/ в нем говорится о Thread.class, но должно быть то же самое для Timer. stackoverflow.com/questions/14942851/ - person Marco Acierno; 13.04.2014

while (true) {
    new CountDownTimer(5000, 1000) {
        @Override
        public void onFinish() {
            releaseCamera();
        }

        @Override
        public void onTick(long millisUntilFinished) {
            mCamera.takePicture(null, null, mPicture);
        }

        }.start();
}

Вам нужно захватить изображение, когда вызывается onTick, а не когда вызывается onFinish. onTick будет вызываться каждый раз через 10 секунд (т. е. указанный интервал), тогда как onFinish будет вызываться после завершения countDownTimer. По этой причине вы получаете только одно изображение.

person Amrita Pritam    schedule 15.12.2016