玻璃-慢速摄像头\ FileObserver通知-XE12-使用ACTION_IMAGE_CAPTURE [英] Glass - Slow camera \ FileObserver notification - XE12 - using ACTION_IMAGE_CAPTURE
问题描述
我基本上已经实现了新的XE12 \ GDK2 cameramanager示例代码,以在应用程序启动时捕获图像.但是,到FileObserver回调的通知需要3到30秒的时间来获取创建映像文件的通知.使用默认的拍照"应用程序拍照可以正常工作,因此我不认为这是操作系统\更新问题. 我的应用程序的行为类似于: -拍照 -点击接受 等待3到30秒 -获取回调,然后使用捕获的图像更新imageview.
I have basically implemented the new XE12\GDK2 cameramanager sample code to capture an image on application start. However, the notification to the FileObserver callback takes anywhere from 3 to 30 seconds to get the notification of the image file creation. Taking a picture using the default 'Take a Picture' app works just fine so I dont thin it is an OS\update issue. My app's behavior is like: - Take the picture - Tap to accept Wait 3 to 30 seconds - Get the callback and the imageview is updated with the captured image.
我认为我没有修改GDK 2.0相机教程中提供的示例代码的一行.所以想知道我在想什么.
I dont think I have modified a single line of the sample code provided in the GDK 2.0 camera tutorial. So wondering what I am missing.
我已附上以下代码的相关部分.任何提示\指针都表示赞赏.
I have attached the relevant section of the code below. Any tips\pointers highly appreciated.
@Override
protected void onStart() {
super.onStart();
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// String path = Environment.getExternalStorageDirectory().getPath();
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
private void processPictureWhenReady(final String picturePath) {
final File pictureFile = new File(picturePath);
if (pictureFile.exists()) {
// The picture is ready; process it. Takes 3-30 seconds to get here!
try {
Bitmap imageBitmap = BitmapFactory.decodeFile(picturePath);
int w = imageBitmap.getWidth();
int h = imageBitmap.getHeight();
Bitmap bm2 = Bitmap.createScaledBitmap(imageBitmap, w/2, h/2, true);
imageBitmap = bm2.copy(bm2.getConfig(), true);
//m_ImageView.setImageBitmap(bm2);
} catch (Exception e) {
Log.e("Exc", e.getMessage());
}
} else {
tm = System.currentTimeMillis();
// The file does not exist yet. Before starting the file observer, you
// can update your UI to let the user know that the application is
// waiting for the picture (for example, by displaying the thumbnail
// image and a progress indicator).
final File parentDirectory = pictureFile.getParentFile();
FileObserver observer = new FileObserver(parentDirectory.getPath()) {
// Protect against additional pending events after CLOSE_WRITE is
// handled.
private boolean isFileWritten;
@Override
public void onEvent(int event, String path) {
if (!isFileWritten) {
// For safety, make sure that the file that was created in
// the directory is actually the one that we're expecting.
File affectedFile = new File(parentDirectory, path);
isFileWritten = (event == FileObserver.CLOSE_WRITE
&& affectedFile.equals(pictureFile));
if (isFileWritten) {
stopWatching();
// Now that the file is ready, recursively call
// processPictureWhenReady again (on the UI thread).
runOnUiThread(new Runnable() {
@Override
public void run() {
processPictureWhenReady(picturePath);
}
});
}
}
}
};
observer.startWatching();
}
}
推荐答案
回答我自己的问题-尽管我得到了詹妮·墨菲(Jenny Murphy)和约翰·费格(John Feig)的澄清:-).希望它可以帮助其他人.
Answering my own question - though I got the clarifications from Jenny Murphy and John Feig :-). Hopefully it helps others.
首先,为什么使用GDK指南中的示例代码进行图像捕获如此缓慢: 这是预期的行为. Glass摄影机的意图(ACTION_IMAGE_CAPTURE)对捕获的图像执行大量专有的后处理-自动HDR等,这需要时间.通过仅显示预览图像(可立即使用),在拍摄照片"命令中巧妙地掩盖了这一点.作为证明,请尝试查找您刚刚在时间轴中拍摄的图像.几秒钟后您将看不到它(根据我的经验,平均大约是8秒钟.). 坦白说,除非您能仅获取预览图像,否则在大多数应用程序中,摄像头的意图可能不是很有用.
To the first point - why is image capture using the sample code from the GDK guide so slow: This is the expected behavior. The Glass camera intent (ACTION_IMAGE_CAPTURE) performs a ton of proprietary post-processing on the captured image - auto-HDR etc which takes time. This is cleverly disguised in the 'Take a picture' command by only displaying the preview image (which is available immediately.). As proof, try to find the image you just took in your time-line. You will not see it for several seconds (around 8 seconds on average in my experience.). Frankly, unless you are ok just grabbing the preview image, the camera intent may not be very useful in most apps.
解决方案是直接使用默认Android API来使用Camera.为了方便起见,我粘贴了这段代码的片段.如果对您中的大多数人来说是基本的话,请原谅.许多代码是从 John Feig在GitHub上的GIFCamera玻璃器皿复制的
The solution is to use the Camera directly using default Android APIs. For convenience, I have pasted a snippet of this code. Please excuse if it is kind of basic for many of you. A lot of the code is copied from John Feig's GIFCamera glassware on GitHub
activity_main布局包含一个名为Preview的SurfaceView
<SurfaceView
android:id="@+id/preview"
android:layout_width="500dp"
android:layout_height="500dp"
android:layout_alignParentTop="true"
android:layout_marginTop="20dp"
/>
MainActivity.java
public class MainActivity extends Activity implements PhotoCallback {
public byte[] m_jpg = null;
Camera cam = null;
SurfaceHolder m_sh;
private final SurfaceHolder.Callback mSurfaceHolderCallback = new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder hldr) {
m_sh = hldr;
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
myCapHandler2(); //Start Camera Preview etc.
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SurfaceView preview = (SurfaceView) findViewById(R.id.preview);
preview.getHolder().addCallback(mSurfaceHolderCallback);
}
public void myCapHandler2() {
//open camera
try {
cam = Camera.open(0);
Camera.Parameters params = cam.getParameters();
List<Size> sizes = params.getSupportedPreviewSizes();
params.setJpegQuality(90);
params.setPreviewFpsRange(30000, 30000);
params.setPictureSize(sizes.get(1).width, sizes.get(1).height);
params.setPreviewSize(sizes.get(1).width, sizes.get(1).height);
cam.setParameters(params);
try {
cam.setPreviewDisplay(m_sh);
}
catch (IOException e) {
e.printStackTrace();
}
// Important: Call startPreview() to start updating the preview
// surface. Preview must be started before you can take a picture.
cam.startPreview();
cam.takePicture(null, null,
new PhotoHandler(this));
} catch (Exception e) {
if (null != cam) {
cam.stopPreview();
cam.release();
}
}
}
@Override
public void pictureTaken(byte[] jpg) {
m_jpg = jpg;
//Picture captured - release the camera for other apps
cam.stopPreview();
cam.release();
}
@Override
public void onPause() {
if (null != cam) {
cam.stopPreview();
cam.release();
}
}
@Override
public void onDestroy() {
if (null != cam) {
cam.stopPreview();
cam.release();
}
}
}
PhotoHandler.java
import android.hardware.Camera;
import android.os.AsyncTask;
public class PhotoHandler implements Camera.PictureCallback {
private PhotoCallback photoCallback;
public PhotoHandler(PhotoCallback photoCallback) {
super();
this.photoCallback = photoCallback;
}
@Override
public void onPictureTaken(byte[] data, Camera camera) {
new ProcessCapturedImage().execute(data);
}
private class ProcessCapturedImage extends AsyncTask<byte[], Void, byte[]> {
@Override
protected byte[] doInBackground(byte[]... params) {
if (null == params || null == params[0])
return null;
return params[0];
}
@Override
protected void onPostExecute(byte[] params) {
photoCallback.pictureTaken(params);
}
}
}
PhotoCallback.java
public interface PhotoCallback {
public void pictureTaken(byte[] jpg);
}
最好用相机玻璃器皿.
这篇关于玻璃-慢速摄像头\ FileObserver通知-XE12-使用ACTION_IMAGE_CAPTURE的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!