如何在没有预览的背景下捕获图像

时间:2015-02-02 07:25:27

标签: android camera

我开发了一个锁屏,而用户错误的尝试相机应该自动启动并拍照,但我没有找到任何解决方案或API

此代码首先声明将作为Surface视图和activity_main.xml文件中的图像视图的句柄的变量。然后,声明一个Bitmap对象,它将用于在捕获后显示图像(第23行)。之后,声明了3个对象:一个SurfaceHolder,它将分配一部分屏幕来渲染相机预览(其宽度和高度为0);一台可以处理设备相机的相机;和一个Parameters对象,用于设置摄像机的设置(第27到31行)。

继续使用onCreate()方法,它基本上通过获取对其他现有对象的引用来初始化所有声明的对象,例如将在main.xml文件中引用SurfaceView的sv对象。此方法中有两行需要更详细的说明。第50行将Surface Holder回调设置为此,因为此类正在实现SurfaceHolder.Callback接口,其目的是控制“表面”(屏幕区域)的渲染。这是必需的,以便“预览”有效。另一个重要的是第53行,告诉Android这个表面将替换所有数据。

SurfaceChanged()方法就是这一切。初始化参数对象(第60行)。不仅如此,还设置了摄像机参数,并开始预览(第63和64行)。定义了图像回调,每次拍照时都会调用它的代码(第67到77行)。在其中,摄像机捕获的数据被解码为Bitmap对象(第73行),然后,第75行告诉ImageView显示此位图。在方法结束时,要求摄像机使用最近创建的回调拍摄照片(第79行)。

surfaceCreated()方法中的代码将相机对象挂钩到设备的相机。它还告诉摄像机应该预览其捕获的位置(第83到95行)。最后一个方法是surfaceDestroyed()方法释放相机,因此它可以被其他应用程序使用(第98到106行)。

这是一个非常标准的相机捕捉代码。隐藏预览的是Surface Holder的宽度和高度,它们设置为零。使其工作所需的最后一项要求是添加访问AndroidManifest文件的相机权限:

<uses-permission android:name="android.permission.CAMERA"></uses-permission>  

MainActivity:

    public void onCreate(Bundle savedInstanceState) {  
         super.onCreate(savedInstanceState);  
      setContentView(R.layout.activity_main);  
      display=(ImageView)findViewById(R.id.imageView1);  
      // do we have a camera?  
      if (!getPackageManager()  
        .hasSystemFeature(PackageManager.FEATURE_CAMERA)) {  
       Toast.makeText(this, "No camera on this device", Toast.LENGTH_LONG)  
         .show();  
      } else {  
       cameraId = findFrontFacingCamera();  
       if (cameraId < 0) {  
        Toast.makeText(this, "No front facing camera found.",  
          Toast.LENGTH_LONG).show();  
       } else {  
            safeCameraOpen(cameraId);   
       }  
      }         
      // THIS IS JUST A FAKE SURFACE TO TRICK THE CAMERA PREVIEW  
      // http://stackoverflow.com/questions/17859777/how-to-take-pictures-in-android-  
      // application-without-the-user-interface  
      SurfaceView view = new SurfaceView(this);  
      try {  
              camera.setPreviewDisplay(view.getHolder());  
         } catch (IOException e) {  
              // TODO Auto-generated catch block  
              e.printStackTrace();  
         }  
      camera.startPreview();  
      Camera.Parameters params = camera.getParameters();  
      params.setJpegQuality(100);  
      camera.setParameters(params);  
      // We need something to trigger periodically the capture of a  
      // picture to be processed  
      timer=new Timer(getApplicationContext(),threadHandler);  
      timer.execute();  
      }  
    ////////////////////////////////////thread Handler///////////////////////////////////////  
    private Handler threadHandler = new Handler() {  
         public void handleMessage(android.os.Message msg) {       
               switch(msg.what){  
               case DONE:  
                   // Trigger camera callback to take pic  
                    camera.takePicture(null, null, mCall);  
                    break;  
               case NEXT:  
                    timer=new Timer(getApplicationContext(),threadHandler);  
                    timer.execute();  
                    break;  
               }  
               }  
          };  
     Camera.PictureCallback mCall = new Camera.PictureCallback() {  
          public void onPictureTaken(byte[] data, Camera camera) {  
             //decode the data obtained by the camera into a Bitmap  
                //display.setImageBitmap(photo);  
                Bitmap bitmapPicture  
                = BitmapFactory.decodeByteArray(data, 0, data.length);  
                display.setImageBitmap(bitmapPicture);  
                Message.obtain(threadHandler, MainActivity.NEXT, "").sendToTarget();   
                //Log.v("MyActivity","Length: "+data.length);  
           }        
     };  
    private int findFrontFacingCamera() {  
         int cameraId = -1;  
         // Search for the front facing camera  
         int numberOfCameras = Camera.getNumberOfCameras();  
         for (int i = 0; i < numberOfCameras; i++) {  
              CameraInfo info = new CameraInfo();  
              Camera.getCameraInfo(i, info);  
              if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {  
                   Log.v("MyActivity", "Camera found");  
             cameraId = i;  
             break;  
            }  
           }  
           return cameraId;  
          }  
    @Override  
    protected void onPause() {  
         if (timer!=null){  
              timer.cancel(true);  
         }  
      releaseCamera();  
      super.onPause();  
     }       
    // I think Android Documentation recommends doing this in a separate  
    // task to avoid blocking main UI  
    private boolean safeCameraOpen(int id) {  
      boolean qOpened = false;  
      try {  
        releaseCamera();  
        camera = Camera.open(id);  
        qOpened = (camera != null);  
      } catch (Exception e) {  
        Log.e(getString(R.string.app_name), "failed to open Camera");  
        e.printStackTrace();  
      }  
      return qOpened;    
    }  
    private void releaseCamera() {  
      if (camera != null) {  
           camera.stopPreview();  
        camera.release();  
        camera = null;  
      }  
    }  
}  

例外

02-02 12:44:58.941: E/AndroidRuntime(2067): FATAL EXCEPTION: main
02-02 12:44:58.941: E/AndroidRuntime(2067): java.lang.RuntimeException: takePicture failed
02-02 12:44:58.941: E/AndroidRuntime(2067):     at android.hardware.Camera.native_takePicture(Native Method)
02-02 12:44:58.941: E/AndroidRuntime(2067):     at android.hardware.Camera.takePicture(Camera.java:1146)
02-02 12:44:58.941: E/AndroidRuntime(2067):     at android.hardware.Camera.takePicture(Camera.java:1091)
02-02 12:44:58.941: E/AndroidRuntime(2067):     at com.example.capturefindmyphone.MainActivity$1.handleMessage(MainActivity.java:80)
02-02 12:44:58.941: E/AndroidRuntime(2067):     at android.os.Handler.dispatchMessage(Handler.java:99)
02-02 12:44:58.941: E/AndroidRuntime(2067):     at android.os.Looper.loop(Looper.java:137)
02-02 12:44:58.941: E/AndroidRuntime(2067):     at android.app.ActivityThread.main(ActivityThread.java:4960)
02-02 12:44:58.941: E/AndroidRuntime(2067):     at java.lang.reflect.Method.invokeNative(Native Method)
02-02 12:44:58.941: E/AndroidRuntime(2067):     at java.lang.reflect.Method.invoke(Method.java:511)
02-02 12:44:58.941: E/AndroidRuntime(2067):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038)
02-02 12:44:58.941: E/AndroidRuntime(2067):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)
02-02 12:44:58.941: E/AndroidRuntime(2067):     at dalvik.system.NativeStart.main(Native Method)

1 个答案:

答案 0 :(得分:0)

它已经有一段时间了,我对此有点生疏,而且非常暧昧&#34; takePicture失败&#34;没有帮助。但这可能是因为预览表面尚未准备好吗?参见&#34; setPreviewDisplay&#34;的第二段。文档。

http://developer.android.com/reference/android/hardware/Camera.html#setPreviewDisplay(android.view.SurfaceHolder) public final void setPreviewDisplay(SurfaceHolder holder)

在API级别1中添加 设置要用于实时预览的Surface。预览需要表面或表面纹理,拍摄时需要预览。可以重新设置相同的表面而不会造成伤害。设置预览曲面将取消设置通过setPreviewTexture(SurfaceTexture)设置的任何预览曲面纹理。

调用此方法时,SurfaceHolder必须已包含曲面。如果您使用的是SurfaceView,则需要在调用setPreviewDisplay()或开始预览之前使用addCallback(SurfaceHolder.Callback)注册SurfaceHolder.Callback并等待surfaceCreated(SurfaceHolder)。