2015-09-29 61 views
3

我試圖實現android.hardware.camera2,但我有點困惑。Android Camera2錯誤旋轉

câmera隨着fone旋轉!

拍攝前,如果旋轉手機,相機將旋轉而不是保持相同的位置。

示例圖像。

http://imgur.com/fE1EqXv

我不知道爲什麼會發生。

我沒有持有人的兩種佈局。

相機XML

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:fab="http://schemas.android.com/apk/res-auto" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    tools:context=".Camera" > 

    <TextureView 
     android:id="@+id/texture" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:layout_alignParentTop="true" /> 

    <com.getbase.floatingactionbutton.FloatingActionButton 
     android:id="@+id/btn_takepicture" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     fab:fab_icon="@drawable/ic_fab_foto" 
     fab:fab_colorNormal="#FFFF56B9" 
     fab:fab_colorPressed="#FFD5379B" 
     android:layout_alignParentBottom="true" 
     android:layout_centerHorizontal="true" 
     android:layout_marginBottom="16dp" /> 

    <com.getbase.floatingactionbutton.FloatingActionButton 
     android:id="@+id/btn_switchcam" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     fab:fab_icon="@drawable/ic_fab_switch" 
     fab:fab_colorNormal="#267300" 
     fab:fab_colorPressed="#1e5b00" 
     fab:fab_size="mini" 
     android:layout_alignParentTop="true" 
     android:layout_alignParentRight="true" 
     android:layout_marginTop="16dp" 
     android:layout_marginRight="16dp" /> 

</RelativeLayout> 

相機活動

public class AppCamera extends AppCompatActivity { 
    private Size mPreviewSize; 

    private TextureView mTextureView; 
    private CameraDevice mCameraDevice; 
    private CaptureRequest.Builder mPreviewBuilder; 
    private CameraCaptureSession mPreviewSession; 
    private static int cam = 0; 

    private FloatingActionButton mBtnShot; 
    private FloatingActionButton mBtnSwitch; 

    private static final SparseIntArray ORIENTATIONS = new SparseIntArray(); 

    static { 
     ORIENTATIONS.append(Surface.ROTATION_0, 90); 
     ORIENTATIONS.append(Surface.ROTATION_90, 0); 
     ORIENTATIONS.append(Surface.ROTATION_180, 270); 
     ORIENTATIONS.append(Surface.ROTATION_270, 180); 
    } 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); 
     setContentView(R.layout.camera); 

     mTextureView = (TextureView)findViewById(R.id.texture); 
     mTextureView.setSurfaceTextureListener(mSurfaceTextureListener); 

     mBtnShot = (FloatingActionButton)findViewById(R.id.btn_takepicture); 
     mBtnSwitch = (FloatingActionButton)findViewById(R.id.btn_switchcam); 

     mBtnShot.setOnClickListener(new OnClickListener(){ 

      @Override 
      public void onClick(View v) { 
       takePicture(); 
      } 

     }); 

     mBtnSwitch.setOnClickListener(new OnClickListener(){ 

      @Override 
      public void onClick(View v) { 
       if (cam == 0) { 
        cam = 1; 
       } else { 
        cam = 0; 
       } 
       if (null != mCameraDevice) { 
        mCameraDevice.close(); 
        mCameraDevice = null; 
       } 
       openCamera(); 
      } 

     }); 

    } 

    protected void takePicture() { 
     if(null == mCameraDevice) { 
      return; 
     } 

     CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); 
     try { 
      CameraCharacteristics characteristics = manager.getCameraCharacteristics(mCameraDevice.getId()); 

      Size[] jpegSizes = null; 
      if (characteristics != null) { 
       jpegSizes = characteristics 
         .get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP) 
         .getOutputSizes(ImageFormat.JPEG); 
      } 
      int width = 640; 
      int height = 480; 
      if (jpegSizes != null && 0 < jpegSizes.length) { 
       width = jpegSizes[0].getWidth(); 
       height = jpegSizes[0].getHeight(); 
      } 

      ImageReader reader = ImageReader.newInstance(width, height, ImageFormat.JPEG, 1); 
      List<Surface> outputSurfaces = new ArrayList<Surface>(2); 
      outputSurfaces.add(reader.getSurface()); 
      outputSurfaces.add(new Surface(mTextureView.getSurfaceTexture())); 

      final CaptureRequest.Builder captureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); 
      captureBuilder.addTarget(reader.getSurface()); 
      captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH); 

      // Orientation 
      int rotation = getWindowManager().getDefaultDisplay().getRotation(); 
      captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation)); 

      final File file = new File(Environment.getExternalStorageDirectory()+"/DCIM", "teste.jpg"); 

      ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() { 

       @Override 
       public void onImageAvailable(ImageReader reader) { 

        Image image = null; 
        try { 
         image = reader.acquireLatestImage(); 
         ByteBuffer buffer = image.getPlanes()[0].getBuffer(); 
         byte[] bytes = new byte[buffer.capacity()]; 
         buffer.get(bytes); 
         save(bytes); 
        } catch (FileNotFoundException e) { 
         e.printStackTrace(); 
        } catch (IOException e) { 
         e.printStackTrace(); 
        } finally { 
         if (image != null) { 
          image.close(); 
         } 
        } 
       } 

       private void save(byte[] bytes) throws IOException { 
        OutputStream output = null; 
        try { 
         output = new FileOutputStream(file); 
         output.write(bytes); 
        } finally { 
         if (null != output) { 
          output.close(); 
         } 
        } 
       } 

      }; 

      HandlerThread thread = new HandlerThread("CameraPicture"); 
      thread.start(); 
      final Handler backgroudHandler = new Handler(thread.getLooper()); 
      reader.setOnImageAvailableListener(readerListener, backgroudHandler); 

      final CameraCaptureSession.CaptureCallback captureListener = new CameraCaptureSession.CaptureCallback() { 

       @Override 
       public void onCaptureCompleted(CameraCaptureSession session, 
               CaptureRequest request, TotalCaptureResult result) { 

        super.onCaptureCompleted(session, request, result); 
        Toast.makeText(AppCamera.this, "Saved:"+file, Toast.LENGTH_SHORT).show(); 
        startPreview(); 
       } 

      }; 

      mCameraDevice.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback() { 

       @Override 
       public void onConfigured(CameraCaptureSession session) { 

        try { 
         session.capture(captureBuilder.build(), captureListener, backgroudHandler); 
        } catch (CameraAccessException e) { 

         e.printStackTrace(); 
        } 
       } 

       @Override 
       public void onConfigureFailed(CameraCaptureSession session) { 

       } 
      }, backgroudHandler); 

     } catch (CameraAccessException e) { 
      e.printStackTrace(); 
     } 

    } 

    @Override 
    protected void onResume() { 
     super.onResume(); 
    } 

    private void openCamera() { 

     CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); 
     try { 
      String cameraId = manager.getCameraIdList()[cam]; 
      CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId); 
      StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); 
      mPreviewSize = map.getOutputSizes(SurfaceTexture.class)[0]; 

      manager.openCamera(cameraId, mStateCallback, null); 
     } catch (CameraAccessException e) { 
      e.printStackTrace(); 
     } 
    } 

    private TextureView.SurfaceTextureListener mSurfaceTextureListener = new TextureView.SurfaceTextureListener(){ 

     @Override 
     public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { 
      openCamera(); 
     } 

     @Override 
     public void onSurfaceTextureSizeChanged(SurfaceTexture surface, 
               int width, int height) { 
     } 

     @Override 
     public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { 
      return false; 
     } 

     @Override 
     public void onSurfaceTextureUpdated(SurfaceTexture surface) { 
      //Log.e(TAG, "onSurfaceTextureUpdated"); 
     } 

    }; 

    private CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() { 

     @Override 
     public void onOpened(CameraDevice camera) { 

      mCameraDevice = camera; 
      startPreview(); 
     } 

     @Override 
     public void onDisconnected(CameraDevice camera) { 

     } 

     @Override 
     public void onError(CameraDevice camera, int error) { 

     } 

    }; 

    @Override 
    protected void onPause() { 

     super.onPause(); 
     if (null != mCameraDevice) { 
      mCameraDevice.close(); 
      mCameraDevice = null; 
     } 
    } 

    protected void startPreview() { 

     if(null == mCameraDevice || !mTextureView.isAvailable() || null == mPreviewSize) { 
      return; 
     } 

     SurfaceTexture texture = mTextureView.getSurfaceTexture(); 
     if(null == texture) { 
      return; 
     } 

     texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight()); 
     Surface surface = new Surface(texture); 

     try { 
      mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 
     } catch (CameraAccessException e) { 

      e.printStackTrace(); 
     } 
     mPreviewBuilder.addTarget(surface); 

     try { 
      mCameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback() { 

       @Override 
       public void onConfigured(CameraCaptureSession session) { 

        mPreviewSession = session; 
        updatePreview(); 
       } 

       @Override 
       public void onConfigureFailed(CameraCaptureSession session) { 

        Toast.makeText(AppCamera.this, "onConfigureFailed", Toast.LENGTH_LONG).show(); 
       } 
      }, null); 
     } catch (CameraAccessException e) { 

      e.printStackTrace(); 
     } 
    } 

    protected void updatePreview() { 

     if(null == mCameraDevice) { 
     } 

     mPreviewBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO); 
     HandlerThread thread = new HandlerThread("CameraPreview"); 
     thread.start(); 
     Handler backgroundHandler = new Handler(thread.getLooper()); 

     try { 
      mPreviewSession.setRepeatingRequest(mPreviewBuilder.build(), null, backgroundHandler); 
     } catch (CameraAccessException e) { 

      e.printStackTrace(); 
     } 
    } 
} 
+0

你有沒有解決這個問題?任何解決方案 –

+0

不,剛剛刪除了該項目,並繼續xD –

回答

2

如果 「onSurfaceTextureSizeChanged(表面紋理的質感,INT寬度,INT高度)」 進行燒製,調用以下方法:

/** 
    * Configures the necessary {@link android.graphics.Matrix} transformation to `mTextureView`. 
    * This method should be called after the camera preview size is determined in 
    * setUpCameraOutputs and also the size of `mTextureView` is fixed. 
    * 
    * @param viewWidth The width of `mTextureView` 
    * @param viewHeight The height of `mTextureView` 
    */ 
    private void configureTransform(int viewWidth, int viewHeight) { 
     Activity activity = getActivity(); 
     if (null == mTextureView || null == mPreviewSize || null == activity) { 
      return; 
     } 
     int rotation = activity.getWindowManager().getDefaultDisplay().getRotation(); 
     Matrix matrix = new Matrix(); 
     RectF viewRect = new RectF(0, 0, viewWidth, viewHeight); 
     RectF bufferRect = new RectF(0, 0, mPreviewSize.getHeight(), mPreviewSize.getWidth()); 
     float centerX = viewRect.centerX(); 
     float centerY = viewRect.centerY(); 
     if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) { 
      bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY()); 
      matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL); 
      float scale = Math.max(
        (float) viewHeight/mPreviewSize.getHeight(), 
        (float) viewWidth/mPreviewSize.getWidth()); 
      matrix.postScale(scale, scale, centerX, centerY); 
      matrix.postRotate(90 * (rotation - 2), centerX, centerY); 
     } else if (Surface.ROTATION_180 == rotation) { 
      matrix.postRotate(180, centerX, centerY); 
     } 
     mTextureView.setTransform(matrix); 
    } 

欲瞭解更多信息,看看以下文件: https://github.com/googlesamples/android-Camera2Basic/blob/master/Application/src/main/java/com/example/android/camera2basic/Camera2BasicFragment.java

+0

什麼是mPreviewSize? –

+0

@ShylendraMadda我剛剛使用的大小來自於java.util –

+0

我也用過'android.util.Size' –

2

取代

static { 
     ORIENTATIONS.append(Surface.ROTATION_0, 0); 
     ORIENTATIONS.append(Surface.ROTATION_90, 90); 
     ORIENTATIONS.append(Surface.ROTATION_180, 180); 
     ORIENTATIONS.append(Surface.ROTATION_270, 270); 
    } 
+0

要去測試它,我會讓你知道的! –

+0

不起作用。上面的代碼是用於在打印後旋轉圖片,我在拍攝圖片前發生了一些情況。 –