在Android中设置相机预览

时间:2017-05-10 09:31:19

标签: android

我正在开发相机应用程序。我写了一些代码来显示预览,但它不起作用。没有错误,但屏幕始终是黑色的。我想我错过了什么。这是代码。

预览

public class Preview extends SurfaceView implements SurfaceHolder.Callback {

    private static final String TAG = "com.azeem.Debug";

    private Context context;
    private SurfaceView mSurfaceView;
    public Camera mCamera;
    private static final Camera.CameraInfo mCameraInfo = new Camera.CameraInfo();
    private Display mDisplay;
    private List<Camera.Size> mSupportedPreviewSizes;
    Camera.Size mPreviewSize;
    private static final int NO_CAMERA = -1;
    private boolean mIsFrontCamera = false;
    private boolean mIsFlashOn = false;
    private int mFrontCameraId, mBackCameraId;

    public Preview(Context ctx) {
        super(ctx);
        context = ctx;
        Log.i(TAG, "First Constructor");
        init();
    }

    public Preview(Context ctx, AttributeSet attrs) {
        super(ctx, attrs);
        context = ctx;
        Log.i(TAG, "Second Constructor");
        init();
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        Log.i(TAG, "surfaceCreated");
        this.start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        Log.i(TAG, "surfaceChanged");
        if(mPreviewSize != null) {
            Log.i(TAG, "Activate Optimal Preview");
            Camera.Parameters parameters = mCamera.getParameters();
            parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
            mCamera.setParameters(parameters);
            mCamera.startPreview();
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        Log.i(TAG, "surfaceDestroyed");
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        Log.i(TAG, "onMeasure");
        final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        setMeasuredDimension(width, height);

        if (mSupportedPreviewSizes != null) {
            mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
        }
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        Log.i(TAG, "onLayout");
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.i(TAG, "onTouchEvent");
        return super.onTouchEvent(event);
    }

    private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
        final double ASPECT_TOLERANCE = 0.1;
        double targetRatio=(double)h / w;

        if (sizes == null) return null;

        Camera.Size optimalSize = null;
        double minDiff = Double.MAX_VALUE;

        int targetHeight = h;

        for (Camera.Size size : sizes) {
            double ratio = (double) size.width / size.height;
            if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }

        if (optimalSize == null) {
            minDiff = Double.MAX_VALUE;
            for (Camera.Size size : sizes) {
                if (Math.abs(size.height - targetHeight) < minDiff) {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - targetHeight);
                }
            }
        }
        return optimalSize;
    }

    private void init(){
        Log.i(TAG, "init");
        if(hasCamera()) {
            final SurfaceHolder surfaceHolder = this.getHolder();
            surfaceHolder.addCallback(this);

            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB)
                surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

            mBackCameraId = findCameraId(false);

            if(hasFrontCamera()){
                mFrontCameraId = findCameraId(true);
            }else{
                mFrontCameraId = NO_CAMERA; // Front Face Camera Not found on device
            }

            final WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
            mDisplay = windowManager.getDefaultDisplay();

        } // Else Camera not found on device
    }

    public void setCamera(){
        Log.i(TAG, "setCamera");
        //if(mSurfaceView != null && hasCamera()){
        if(hasCamera()){
            mCamera = Camera.open(mBackCameraId);
        }
    }

    public void start(){
        Log.i(TAG, "start");
        if(mCamera != null){
            try {
                mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
                //mCamera.setPreviewDisplay(mSurfaceView.getHolder());
                mCamera.setPreviewDisplay(this.getHolder());
                mCamera.startPreview();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void stop(){
        Log.i(TAG, "stop");
        if(mCamera != null){
            mCamera.stopPreview();
            mCamera.release();
            mCamera = null;
        }
    }

    private boolean hasCamera() {
        final PackageManager packageManager = context.getPackageManager();
        return packageManager != null
                && packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA);
    }

    private boolean hasFrontCamera() {
        final PackageManager packageManager = context.getPackageManager();
        return packageManager != null
                && packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT);
    }

    private int findCameraId(boolean front) {
        final int cameraCount = Camera.getNumberOfCameras();
        for (int i = 0; i < cameraCount; i++) {
            Camera.getCameraInfo(i, mCameraInfo);
            if ((front && mCameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT)
                    || (!front && mCameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK)) {
                return i;
            }
        }
        return NO_CAMERA;
    }

}

MainActivity

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        preview = new Preview(this);


    capturePicture.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                preview.mCamera.takePicture(null, null, jpegCallback);
            }
        });
    }       
    @Override
    protected void onResume() {
        super.onResume();
        preview.setCamera();
        preview.start();
    }

    @Override
    protected void onPause() {
        super.onPause();
        preview.stop();
    }       
    // Other Code....
}   

activity_main.xml中

<com.azeem.mycamera.Preview
    android:id="@+id/surfaceView"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

<!-- Other Codes Buttons etc -->

这是我正在使用的代码,但预览没有显示。你能不能让我知道我错过了什么。

更新

还有清单文件,我提到所有必需的uses-premissions

预览在我setCamera课程内preview时工作,但是当我从MainActivity设置时,它无法正常工作。

这是有效的代码。 预览课程

// other code 
@Override
public void surfaceCreated(SurfaceHolder holder) {
    Log.i(TAG, "surfaceCreated");
    this.setCamera();
    this.start();
}
// other code

MainActivity

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

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

@Override
protected void onPause() {
    super.onPause();
}       
// Other Code....

这是有效的,但是当我从MainActivity进行设置时我无法正常工作,因为我在更新之前显示代码有什么问题我不能告诉我。

2 个答案:

答案 0 :(得分:0)

您是否已在Android Manifest中声明了权限,并且还检查了使用Android最新版本的运行时权限。

答案 1 :(得分:0)

在创建曲面之前,无法开始预览。因此,在您的工作代码中使用onSurfaceCreated启动相机似乎是有意义的。如果你真的想在onResume中强制执行此行为,那么你可能做的最好的事情就是保持两个标志:resumed和surfaceCreated。

这样的东西(注意:psuedocode)......

onResume(... ){
   resumed = true;
   if (surfaceCreated){
       startCam();
   }
}

onSurfaceCreated(){
   surfaceCreated = true;
   if (resumed){
       startCam();
   }
}

onPause(){
   resumed = false;
}

onSurfaceDestroyed(){
   surfaceCreated = false;
}

这将确保在设置相机时满足您的所有条件。