在片段Android相机preVIEW [英] Android Camera preview in a fragment

查看:350
本文介绍了在片段Android相机preVIEW的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

到现在为止我有一个完整的工作code,在摄像头插头看到了前置摄像头的preVIEW。

Until now I have a full working code that plugs in a camera to see the preview of the front camera.

我试图现在要做的就是获得一个相机片段里面工作。

What I'm trying to do now is to get that camera working inside a Fragment.

全部code:

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:这里你可以下载我的code和测试。

PS: Here you can download my code and test it.

推荐答案

起初 - 使用的FrameLayout 为您的相机preVIEW

At first - use FrameLayout for your camera preview.

<?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);
    }
}

第三 - 无需释放相机两次。您可以在片段做到了,刚刚从<$ ​​C $ C> 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我看到你的相机preVIEW。祝你好运!

And you will see your camera preview in a fragmentas I see. Good luck!

这篇关于在片段Android相机preVIEW的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆