android:定期在任务或线程中拍照?

时间:2015-04-26 13:13:13

标签: java android multithreading android-asynctask camera

我正在编写一个Android应用程序,它应该在用户定义的时间间隔内拍摄照片(20秒-1分钟)。即使在后台运行或设备正在睡眠时,它也应该拍摄照片。该应用程序将运行很长一段时间。如果需要唤醒设备,应尽快恢复睡眠以节省电池寿命。拍照后,该应用程序将处理一些额外的工作(比较两张图片)。

我读了一些关于调度警报(http://developer.android.com/training/scheduling/alarms.htm),创建服务(也是@android培训)和Android AsyncTasks,Java线程(http://www.mergeconflict.net/2012/05/java-threads-vs-android-asynctask-which.html

的内容

...但我仍然不确定实现这一目标的最佳方法是什么。

我的问题是:

  1. 我应该使用线程还是任务在后台拍摄照片? (这两张照片的比较可能需要更长的时间 毫秒,但我不知道有关此CPU的CPU负载 操作)
  2. 我应该使用闹钟唤醒设备还是有其他替代解决方案?
  3. 两者(警报和线程/任务)如何协同工作? (在任务/线程中包含警报?)
  4. 非常感谢您的帮助。

2 个答案:

答案 0 :(得分:0)

关于我们的问题,我知道我可以帮助开始在用户定义的时间间隔重复拍照任务的方面。对于此类任务,您可以使用Timer来实现此目的。代码看起来像这样:

mTmr = new Timer();
    mTsk = new TimerTask() {
        @Override
        public void run() {
            //Take picture or do whatever you want
        }
    };
    mTmr.schedule(mTsk, 0, USER_DEFINED_EXECUTION_INTERVAL);

schedule开始计时器。此处使用的schedule的第一个参数是要运行的任务mTsk。第二个参数是第一次执行之前的延迟(以毫秒为单位),在这种情况下没有延迟。第三个参数是您想要操作的参数,即执行的间隔。参数是执行之间的时间,所以如果它是20秒,你就会超过20,000。如果是一分钟,它将是60,000。您可以使用您喜欢的任何方法从用户处获取此值。

为了让计时器继续运行,请确保您不要在mTmr.cancel中拨打onPause,因为在您的情况下,您希望在用户不在应用内时保持计时器正常运行。不调用cancel表示计时器将保留其资源,直到用户关闭该应用程序。

或者您可以查看此How to schedule a periodic task in Java?如果您想使用ScheduledExecutorService而不是Timer

答案 1 :(得分:0)

我已经制作了这个应用程序 - Lenx。它广泛使用相机,我在后台处理图像。我使用AsyncTask来处理图像,它从未给出任何问题。该应用程序还有一个计时器,在一定的时间间隔后启动该过程。我使用的逻辑非常简单。

我还没有使用过Camera2 API,因此代码可能已被弃用。我创建了CameraPreview类来实现Camera.PreivewCallback

@Override
public void onPreviewFrame(byte[] data, Camera camera) {
    if (data == null) {
        return;
    }

    int expectedBytes = previewWidth * previewHeight *
            ImageFormat.getBitsPerPixel(ImageFormat.NV21) / 8;

    if (expectedBytes != data.length) {
        Log.e(TAG, "Mismatched size of buffer! Expected ");

        mState = STATE_NO_CALLBACKS;
        mCamera.setPreviewCallbackWithBuffer(null);
        return;
    }

   if (mProcessInProgress || mState == STATE_PROCESS_IN_PROGRESS) {
        mCamera.addCallbackBuffer(data);
        return;
    }

   if (mState == STATE_PROCESS) {
        mProcessInProgress = true;
        processDataTask = new ProcessDataTask();
        processDataTask.execute(data);

        }
}

public void startProcessing() {
    mState = STATE_PROCESS;
}

我的AsyncTask就是这样的

private class ProcessDataTask
        extends
            AsyncTask<byte[], Void, Boolean> {

    @Override
    protected Boolean doInBackground(byte[]... datas) {
        mState = STATE_PROCESS_IN_PROGRESS;
        Log.i(TAG, "background process started");
        byte[] data = datas[0];

        long t1 = java.lang.System.currentTimeMillis();

        // process your data

        long t2 = java.lang.System.currentTimeMillis();
        Log.i(TAG, "processing time = " + String.valueOf(t2 - t1));

        mCamera.addCallbackBuffer(data);
        mProcessInProgress = false;
        return true;
    }

    @Override
    protected void onPostExecute(Boolean result) {
        mState = STATE_PROCESS_WAIT;
    }

}
只要相机预览正在运行,

onPreviewFrame()将始终被调用。您需要获取数据并仅在触发某些内容时对其进行处理。因此,只需更改变量的状态,在本例中为mState,并根据状态调用AsyncTask