玻璃 - 慢速摄像机\ FileObserver通知 - XE12 - 使用ACTION_IMAGE_CAPTURE

时间:2014-04-15 01:33:09

标签: google-glass google-gdk

我基本上已经实现了新的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();

            }
    }

1 个答案:

答案 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);
}

使用相机玻璃器皿,一切顺利。