2014-09-01 72 views
6

到现在为止,我有一个完整的工作代码,可以插入相机来查看前置相机的预览。安卓相机预览片段

我现在要做的是让摄像机在Fragment内工作。

全码:

MainActivity.java

public class MainActivity extends Activity { 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    setContentView(R.layout.fragment_main); 

    getFragmentManager().beginTransaction().add(R.id.mainLayout, new CameraExtractionFragment()).commit(); 
} 
} 

CameraExtractionFragment.java

public class CameraExtractionFragment extends Fragment { 

private CameraExtraction mCameraExtraction; 
Camera mCamera; 
int mNumberOfCameras; 
int cameraId; 
int rotation; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    mCameraExtraction = new CameraExtraction(
      this.getActivity().getBaseContext(), 
      this.getActivity().getWindowManager().getDefaultDisplay().getRotation() 
      ); 

    // Find the total number of cameras available 
    mNumberOfCameras = Camera.getNumberOfCameras(); 

    // Find the ID of the rear-facing ("default") camera 
    CameraInfo cameraInfo = new CameraInfo(); 
    for (int i = 0; i < mNumberOfCameras; i++) { 
     Camera.getCameraInfo(i, cameraInfo); 
     if (cameraInfo.facing == CameraInfo.CAMERA_FACING_FRONT) { 
      cameraId = i; 
     } 
    } 
} 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)    { 
    return mCameraExtraction; 
} 

@Override 
public void onResume() { 
    super.onResume(); 

    // Use mCurrentCamera to select the camera desired to safely restore 
    // the fragment after the camera has been changed 
    mCamera = Camera.open(cameraId); 
    mCameraExtraction.setCamera(mCamera); 
} 

@Override 
public void onPause() { 
    super.onPause(); 

    if (mCamera != null) 
    { 
     mCamera.release(); 
    } 
} 


// Modo en el que se pinta la cámara: encajada por dentro o saliendo los bordes por fuera. 
public enum CameraViewMode { 

    /** 
    * Inner mode 
    */ 
    Inner, 
    /** 
    * Outer mode 
    */ 
    Outer 
} 
} 

CameraExtraction.java

public class CameraExtraction extends ViewGroup implements SurfaceHolder.Callback { 

private final String TAG = "CameraExtraction"; 

Camera mCamera; 
SurfaceHolder mHolder; 
SurfaceView mSurfaceView; 
int mNumberOfCameras; 
int cameraId; 
Rect desiredSize; 
CameraViewMode cameraViewMode; 
boolean mSurfaceCreated = false; 
List<Size> mSupportedPreviewSizes; 
int rotation; 
Size mPreviewSize; 

public CameraExtraction(Context context, int rotation) { 
    super(context); 

    this.rotation = rotation; 

    mSurfaceView = new SurfaceView(context); 

    addView(mSurfaceView); 

    // Install a SurfaceHolder.Callback so we get notified when the 
    mHolder = mSurfaceView.getHolder(); 
    mHolder.addCallback(this); 
    mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 

    cameraViewMode = CameraViewMode.Inner; 
} 

public void setCamera(Camera camera) { 
    mCamera = camera; 
    if (mCamera != null) { 
     mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes(); 
     if (mSurfaceCreated) requestLayout(); 
    } 
} 

public void switchCamera(Camera camera) { 
    setCamera(camera); 
    try { 
     camera.setPreviewDisplay(mHolder); 
    } catch (IOException exception) { 
     Log.e(TAG, "IOException caused by setPreviewDisplay()", exception); 
    } 
} 

@SuppressLint("DrawAllocation") 
@Override 
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
    if (mSurfaceView == null ||mSurfaceView.getHolder() == null) return; 

    if (mSurfaceView.getHolder().getSurface() == null) { 
     // preview surface does not exist 
     return; 
    } 

    final int width = resolveSize(getSuggestedMinimumWidth(), 
      widthMeasureSpec); 
    final int height = resolveSize(getSuggestedMinimumHeight(), 
      heightMeasureSpec); 
    setMeasuredDimension(width, height); 

    if (mSupportedPreviewSizes != null) { 

     mPreviewSize = getNearestPreviewSize(mCamera.new Size(widthMeasureSpec,heightMeasureSpec)); 
    } 

    if (mCamera != null) { 
     Camera.Parameters parameters = mCamera.getParameters(); 
     parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height); 

     mCamera.setParameters(parameters); 
    } 
} 

@Override 
protected void onLayout(boolean changed, int l, int t, int r, int b) { 
    if (getChildCount() > 0) { 
     final View child = getChildAt(0); 

     final int width = r - l; 
     final int height = b - t; 

     int previewWidth = width; 
     int previewHeight = height; 
     if (mPreviewSize != null) { 
      previewWidth = mPreviewSize.width; 
      previewHeight = mPreviewSize.height; 
     } 

     // Center the child SurfaceView within the parent. 
     if (width * previewHeight > height * previewWidth) { 
      final int scaledChildWidth = previewWidth * height 
        /previewHeight; 
      child.layout((width - scaledChildWidth)/2, 0, 
        (width + scaledChildWidth)/2, height); 
     } else { 
      final int scaledChildHeight = previewHeight * width 
        /previewWidth; 
      child.layout(0, (height - scaledChildHeight)/2, width, 
        (height + scaledChildHeight)/2); 
     } 
    }  
} 

@Override 
public void surfaceCreated(SurfaceHolder holder) { 
    mCamera = Camera.open(cameraId);   
} 

@Override 
public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) { 
    if (mSurfaceView == null || mSurfaceView.getHolder() == null) return; 

      if (mSurfaceView.getHolder().getSurface() == null) { 
       // preview surface does not exist 
       return; 
      } 

      // set preview size and make any resize, rotate or 
      // reformatting changes here 
      Camera.Parameters param = mCamera.getParameters(); 
      Point previewSize = new Point(640,480); 

      Camera.Size size = getNearestPreviewSize(mCamera.new Size(previewSize.x,previewSize.y)); 
      param.setPreviewSize(size.width, size.height); 
      mCamera.setParameters(param); 
      rotation = setCameraDisplayOrientation(cameraId, mCamera); 

      // start preview with new settings 
      try { 
       mCamera.setPreviewCallback(new Camera.PreviewCallback() { 

        @Override 
        public void onPreviewFrame(byte[] data, Camera camera) { 
         // TODO Auto-generated method stub 

        } 
       }); 
       mCamera.setPreviewDisplay(mSurfaceView.getHolder()); 
       mCamera.startPreview(); 

      } catch (Exception e) { 
       Log.d("AndroidControlSurfaceView", 
         "Error starting camera preview: " + e.getMessage()); 
      }  
} 

@Override 
public void surfaceDestroyed(SurfaceHolder holder) { 
    if (mCamera != null) 
    { 
     mCamera.stopPreview(); 
     mCamera.release(); 
    } 
} 


protected Rect getCameraViewSizeCompensated(Camera.Size cameraPreviewSize, Point hostViewSize) { 
    Rect toReturn=null; 

    float ratioWidth = hostViewSize.x/(float)cameraPreviewSize.width; 
    float ratioHeight = hostViewSize.y/(float)cameraPreviewSize.height; 

    switch (cameraViewMode){ 
    case Inner: 
     if (ratioWidth < ratioHeight) { 
      int newHeight = (int)(cameraPreviewSize.height*ratioWidth); 
      int y = (hostViewSize.y - newHeight)/2; 
      toReturn = new Rect(0, y, hostViewSize.x, y+newHeight); 
     } else { 
      int newWidth = (int)(cameraPreviewSize.width*ratioHeight); 
      int x = (hostViewSize.x - newWidth)/2; 
      toReturn = new Rect(x, 0, x+newWidth,hostViewSize.y); 
     } 
     break; 
    case Outer: 
     if (ratioWidth < ratioHeight) { 
      int newWidth = (int)(cameraPreviewSize.width*ratioHeight); 
      int x = (hostViewSize.x - newWidth)/2; 
      toReturn = new Rect(x, 0, x+newWidth,hostViewSize.y); 
     } else { 
      int newHeight = (int)(cameraPreviewSize.height*ratioWidth); 
      int y = (hostViewSize.y - newHeight)/2; 
      toReturn = new Rect(0, y, hostViewSize.x, y+newHeight); 
     } 
     break; 
    } 
    return toReturn; 
} 

private Camera.Size getNearestPreviewSize(Camera.Size size) { 
    List<Camera.Size> availableSizes = mCamera.getParameters().getSupportedPreviewSizes(); 
    if (availableSizes == null || availableSizes.size() <= 0) return null; 

    Camera.Size toReturn = availableSizes.get(0); 
    int distance = Math.abs(size.width*size.height - toReturn.width*toReturn.height); 
    for (int a=1; a<availableSizes.size(); a++) { 
     int temp = Math.abs(size.width*size.height - availableSizes.get(a).width*availableSizes.get(a).height); 
     if (temp < distance) { 
      distance = temp; 
      toReturn = availableSizes.get(a); 
     } 
    } 
    return toReturn; 
} 


public int setCameraDisplayOrientation(int cameraId, android.hardware.Camera camera) { 

    CameraInfo info = new Camera.CameraInfo(); 
    Camera.getCameraInfo(cameraId, info); 
    int degrees = 0; 

    switch (rotation) { 
     case Surface.ROTATION_0: degrees = 0; break; 
     case Surface.ROTATION_90: degrees = 90; break; 
     case Surface.ROTATION_180: degrees = 180; break; 
     case Surface.ROTATION_270: degrees = 270; break; 
    } 

    int result; 
    if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { 
     result = (info.orientation + degrees) % 360; 
     result = (360 - result) % 360; // compensate the mirror 
    } else { // back-facing 
     result = (info.orientation - degrees + 360) % 360; 
    } 
    camera.setDisplayOrientation(result); 
    return result/90; 
} 

} 

但是,当您运行应用程序时,没有图像显示在我的设备中。只有一个白色的屏幕。请注意,正如我提到的摄像头正在从事不包含片段的活动。

那么,为什么主要活动显示为白色屏幕?

PS:Here你可以下载我的代码并测试它。

+0

你可以在这里发布你的代码吗?您的链接已停用,无法使用。 – chinmish 2017-07-29 15:45:12

回答

4

首先 - 使用FrameLayout进行相机预览。

<?xml version="1.0" encoding="utf-8"?> 
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/mainLayout" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" /> 

第二 - 无需打开相机两次。您的surfaceCreated方法。

@Override 
public void surfaceCreated(SurfaceHolder holder) { 
    try { 
     if (mCamera != null) { 
      mCamera.setPreviewDisplay(holder); 
      mCamera.setPreviewCallback(new Camera.PreviewCallback() { 
       @Override 
       public void onPreviewFrame(byte[] data, Camera camera) { 
       } 
      }); 
     } 
    } catch (IOException exception) { 
     Log.e(TAG, "IOException caused by setPreviewDisplay()", exception); 
    } 
} 

第三 - 无需释放相机两次。你在Fragment中做过,只需从surfaceDestroyed中删除。

@Override 
    public void surfaceDestroyed(SurfaceHolder holder) { 
     if (mCamera != null) 
     { 
//   mCamera.stopPreview(); 
//   mCamera.release(); 
     } 
    } 

并在你的片段。

@Override 
public void onPause() { 
    super.onPause(); 

    if (mCamera != null) 
    { 
     mCamera.stopPreview(); 
     mCamera.release(); 
    } 
} 

而且你会在我看到的fragmentas中看到你的相机预览。祝你好运!

+0

真的有帮助! – Sonhja 2014-09-02 07:15:39

0

看起来您的属性cameraIdCameraExtractionFragmentCameraExtraction中,但仅在CameraExtractionFragment中为其赋值。

您应该删除CameraExtraction.cameraId并改为使用CameraExtractionFragment.cameraId

+0

还是白色的.... – Sonhja 2014-09-01 13:24:47