我基本上已经实现了新的XE12 \ GDK2 cameramanager示例代码,以便在应用程序启动时捕获图像。但是,对FileObserver回调的通知需要3到30秒才能获得图像文件创建的通知。使用默认设置拍摄照片'拍照'应用程序工作正常,所以我不瘦它是一个操作系统\更新问题。 我的应用程序的行为如下: - 拍照 - 点击接受 等待3到30秒 - 获取回调,并使用捕获的图像更新imageview。
我不认为我修改了GDK 2.0相机教程中提供的单行示例代码。所以想知道我错过了什么。
我已附上以下代码的相关部分。任何提示\指针高度赞赏。
@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();
}
}
答案 0 :(得分:2)
回答我自己的问题 - 虽然我得到了Jenny Murphy和John Feig的澄清:-)。希望它有助于其他人。
第一点 - 为什么使用GDK指南中的示例代码进行图像捕获的速度如此之慢: 这是预期的行为。 Glass摄像头意图(ACTION_IMAGE_CAPTURE)对捕获的图像执行大量专有的后处理 - 自动HDR等需要时间。在“拍照”中巧妙地伪装了这一点。命令只显示预览图像(可立即使用)。作为证据,尝试找到您刚刚在时间线上拍摄的图像。几秒钟你都不会看到它(根据我的经验平均大约8秒)。 坦率地说,除非您只是抓住预览图像,否则相机意图在大多数应用中可能都不是很有用。
解决方案是使用默认的Android API直接使用相机。为方便起见,我已粘贴了此代码的片段。请原谅这对你们很多人来说是否是基本的。许多代码都是从John Feig's GIFCamera glassware on GitHub
复制而来的activity_main布局包含名为预览的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);
}
使用相机玻璃器皿,一切顺利。