Android 定时间隔相机触发
Android timed interval Camera triggering
我正在尝试编写一个应用程序以在给定的固定时间间隔触发 Android 相机。我正在使用 TimerTask 对其进行测试,但是我读到我不应该在 JPEG 准备好之前再次触发相机。有没有一种方法可以以固定的时间间隔触发相机,让 JPEG 在准备就绪时出现,然后再次触发它,让下一个 JPEG 在读取时出现,等等,而不会导致某种堆溢出?有没有办法做这个camera2?
以下是我目前掌握的相关方法:
PictureCallback onPicTake=new PictureCallback() {
@Override
public void onPictureTaken ( byte[] bytes, Camera camera){
Log.d("data size",""+bytes.length);
Log.d("taken", "taken");
new SaveImageTask(getStorage()).execute(bytes);
resetCam();
}
};
Camera.ShutterCallback onShutter=new Camera.ShutterCallback()
{
@Override
public void onShutter () {
AudioManager mgr = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
mgr.playSoundEffect(AudioManager.FLAG_PLAY_SOUND);
}
};
private class CameraTrigger extends TimerTask{
public void run(){
mCamera.takePicture(onShutter, null, onPicTake);
}
}
preview.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
timer = new Timer();
timer.schedule(new CameraTrigger(), 0, 1000);
}
});
private void resetCam() {
mCamera.startPreview();
preview.setCamera(mCamera);
}
只要您确定 onPictureTaken()
不会超过 1000 毫秒,您的代码就没有什么大错。
我建议的一个优化是违反直觉的不是将图片保存在后台任务中,而是在回调线程中进行。
原因是 bytes 的巨大内存块无法通过这种方式轻松回收。从 JVM 的角度来看,以下模式不会给垃圾收集器带来负担:
- 字节[] 字节 = 新字节[1Mb];
- 用
填充字节
- onPreviewFrame(字节);
- 没有人再次需要 字节
- 字节内存回收
但是如果有对 bytes 的未完成引用,GC 可能很难决定,您会看到 CPU 使用率的峰值,应用程序没有响应,最终,甚至 TimeTask 回调也延迟了。
请注意,在主 (UI) 线程上使用 onPictureTaken() 是不健康的。要在后台保留相机回调,您需要在辅助 Looper 线程上打开相机(请参阅此 example)。
我正在尝试编写一个应用程序以在给定的固定时间间隔触发 Android 相机。我正在使用 TimerTask 对其进行测试,但是我读到我不应该在 JPEG 准备好之前再次触发相机。有没有一种方法可以以固定的时间间隔触发相机,让 JPEG 在准备就绪时出现,然后再次触发它,让下一个 JPEG 在读取时出现,等等,而不会导致某种堆溢出?有没有办法做这个camera2?
以下是我目前掌握的相关方法:
PictureCallback onPicTake=new PictureCallback() {
@Override
public void onPictureTaken ( byte[] bytes, Camera camera){
Log.d("data size",""+bytes.length);
Log.d("taken", "taken");
new SaveImageTask(getStorage()).execute(bytes);
resetCam();
}
};
Camera.ShutterCallback onShutter=new Camera.ShutterCallback()
{
@Override
public void onShutter () {
AudioManager mgr = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
mgr.playSoundEffect(AudioManager.FLAG_PLAY_SOUND);
}
};
private class CameraTrigger extends TimerTask{
public void run(){
mCamera.takePicture(onShutter, null, onPicTake);
}
}
preview.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
timer = new Timer();
timer.schedule(new CameraTrigger(), 0, 1000);
}
});
private void resetCam() {
mCamera.startPreview();
preview.setCamera(mCamera);
}
只要您确定 onPictureTaken()
不会超过 1000 毫秒,您的代码就没有什么大错。
我建议的一个优化是违反直觉的不是将图片保存在后台任务中,而是在回调线程中进行。
原因是 bytes 的巨大内存块无法通过这种方式轻松回收。从 JVM 的角度来看,以下模式不会给垃圾收集器带来负担:
- 字节[] 字节 = 新字节[1Mb];
- 用 填充字节
- onPreviewFrame(字节);
- 没有人再次需要 字节
- 字节内存回收
但是如果有对 bytes 的未完成引用,GC 可能很难决定,您会看到 CPU 使用率的峰值,应用程序没有响应,最终,甚至 TimeTask 回调也延迟了。
请注意,在主 (UI) 线程上使用 onPictureTaken() 是不健康的。要在后台保留相机回调,您需要在辅助 Looper 线程上打开相机(请参阅此 example)。