如何使用框架布局拍摄照片?

时间:2017-06-21 12:18:45

标签: java android xml android-fragments android-camera

在我的项目中,我试图在framelayout中显示相机。它显示完美,但我想按下按钮时捕捉图像。我在下面附上了我的代码。

这是我的MainActivity.java代码:

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

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

    Button but = (Button)findViewById(R.id.selfienext);
    but.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(MainActivity.this,DocumentCapture.class);
            startActivity(intent);
        }
    });
}
}

CameraExtractionFragment.java代码:

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
    Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
    for (int i = 0; i < mNumberOfCameras; i++) {
        Camera.getCameraInfo(i, cameraInfo);
        if (cameraInfo.facing == Camera.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.stopPreview();
        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代码:

class CameraExtraction extends ViewGroup implements SurfaceHolder.Callback {

private final String TAG = "CameraExtraction";

Camera mCamera;
SurfaceHolder mHolder;
SurfaceView mSurfaceView;
int mNumberOfCameras;
int cameraId;
Rect desiredSize;
CameraExtractionFragment.CameraViewMode cameraViewMode;
boolean mSurfaceCreated = false;
List<Camera.Size> mSupportedPreviewSizes;
int rotation;
Camera.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 = CameraExtractionFragment.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) {
    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);
    }
}

@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(480,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) {

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

DocumentCapture.java代码:

 public class DocumentCapture extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_document_capture);

    Button but = (Button)findViewById(R.id.docnext);
    but.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(DocumentCapture.this,VerificationResult.class);
            startActivity(intent);
        }
    });

}
}

这是我的捕获按钮代码:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:layout_marginTop="5dp">
         <FrameLayout
             android:id="@+id/cameraview1"
             android:layout_width="match_parent"
             android:layout_height="350dp">
         </FrameLayout>

        <Button
            android:id="@+id/selfiecapture"
            android:layout_width="100dp"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:background="@drawable/btn"
            android:text="Capture"
            android:textColor="#FFFFFF"
            android:textSize="17dp"
            android:textAllCaps="false"
            android:layout_gravity="left"/>           

</LinearLayout>

1 个答案:

答案 0 :(得分:0)

通过google官方网页Link

您可以使用此方法调用Camera API。

CameraActivity

public class CameraActivity extends Activity {

private Camera mCamera;
private CameraPreview mPreview;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    // Create an instance of Camera
    mCamera = getCameraInstance();

    // Create our Preview view and set it as the content of our activity.
    mPreview = new CameraPreview(this, mCamera);
    FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
    preview.addView(mPreview);
    // Add a listener to the Capture button
    Button captureButton = (Button) findViewById(id.button_capture);
    captureButton.setOnClickListener(
    new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // get an image from the camera
        mCamera.takePicture(null, null, mPicture);
    }
   }
  );
    }
}

 /** A safe way to get an instance of the Camera object. */
 public static Camera getCameraInstance(){
    Camera c = null;
    try {
    c = Camera.open(); // attempt to get a Camera instance
    }
    catch (Exception e){
    // Camera is not available (in use or does not exist)
    }
    return c; // returns null if camera is unavailable
}

private PictureCallback mPicture = new PictureCallback() {

@Override
public void onPictureTaken(byte[] data, Camera camera) {

    File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
    if (pictureFile == null){
        Log.d(TAG, "Error creating media file, check storage permissions: " +
            e.getMessage());
        return;
    }

    try {
        FileOutputStream fos = new FileOutputStream(pictureFile);
        fos.write(data);
        fos.close();
    } catch (FileNotFoundException e) {
        Log.d(TAG, "File not found: " + e.getMessage());
    } catch (IOException e) {
        Log.d(TAG, "Error accessing file: " + e.getMessage());
    }
  }
};

创建相机预览类

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
     private SurfaceHolder mHolder;
     private Camera mCamera;

public CameraPreview(Context context, Camera camera) {
    super(context);
    mCamera = camera;

    // Install a SurfaceHolder.Callback so we get notified when the
    // underlying surface is created and destroyed.
    mHolder = getHolder();
    mHolder.addCallback(this);
    // deprecated setting, but required on Android versions prior to 3.0
    mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}

public void surfaceCreated(SurfaceHolder holder) {
    // The Surface has been created, now tell the camera where to draw the preview.
    try {
        mCamera.setPreviewDisplay(holder);
        mCamera.startPreview();
    } catch (IOException e) {
        Log.d(TAG, "Error setting camera preview: " + e.getMessage());
    }
}

public void surfaceDestroyed(SurfaceHolder holder) {
    // empty. Take care of releasing the Camera preview in your activity.
}

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    // If your preview can change or rotate, take care of those events here.
    // Make sure to stop the preview before resizing or reformatting it.

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

    // stop preview before making changes
    try {
        mCamera.stopPreview();
    } catch (Exception e){
      // ignore: tried to stop a non-existent preview
    }

    // set preview size and make any resize, rotate or
    // reformatting changes here

    // start preview with new settings
    try {
        mCamera.setPreviewDisplay(mHolder);
        mCamera.startPreview();

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

在androidmanifest.xml文件中添加这些

 <uses-feature android:name="android.hardware.camera" />
 <uses-permission android:name="android.permission.CAMERA" />
 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />