三星 S9(18:9) 相机预览拉长

Posted

技术标签:

【中文标题】三星 S9(18:9) 相机预览拉长【英文标题】:Samsung S9(18:9) camera preview stretched 【发布时间】:2019-04-10 13:25:52 【问题描述】:

我正在使用 android Camera API,它在纵向和横向模式下都适用于 16:9 比例的设备。但在三星 S9 18:9 比例设备中,在横向模式下,预览看起来会拉长。在三星 S9 上,我得到了以下支持的预览尺寸 1920X1080,1440X1080, 1088X1088,1280X720,1056X704, 1024X768, 960X720,800X450,720X720,720X480,640X480,352X288,320X240,256X144,176X144,因此最佳预览尺寸为 1920X1080,但设备的实际分辨率为 2,220 x 1,080。所以它看起来被拉伸了。但我需要全屏预览。默认相机预览如何全屏显示?

@SuppressLint("ClickableViewAccessibility")
    @SuppressWarnings("deprecation")
    public CameraPreview(Context context, Camera.PreviewCallback previewCallback) 
        super(context);
        this.previewCallback = previewCallback;
        mContext = context;
        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        mHolder = getHolder();
        mHolder.addCallback(this);
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    

    public void setCameraDisplayOrientation(Context activity,
                                            int cameraId, Camera camera) 
        Camera.CameraInfo info =
                new Camera.CameraInfo();
        Camera.getCameraInfo(cameraId, info);
        int rotation = ((AppCompatActivity) activity).getWindowManager().getDefaultDisplay()
                .getRotation();
        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;
        


        mDisplayOrientation = result;

        Log.d(TAG, "setCameraDisplayOrientation: "+mDisplayOrientation);

        camera.setDisplayOrientation(result);

    



    public void takePhoto(final PictureCallback pCalback) 
        mCamera.takePicture(null, null, pCalback);
    

    public void surfaceCreated(SurfaceHolder holder) 
        // The Surface has been created, acquire the camera and tell it where
        // to draw.
        if (mCamera != null) 
            mCamera.stopPreview();
            mCamera.setPreviewCallback(null);
            mCamera.release();
            mCamera = null;
            //previewCount = 0;
        

        try 
            mCamera = Camera.open();


            //setCameraDisplayOrientation(mContext, 0, mCamera);
            /*mParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
            DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics();
            int screenWidth = displayMetrics.widthPixels;
            int screenHeight = displayMetrics.heightPixels;
            optimalPreviewSize = getBestAspectPreviewSize(mParameters.getSupportedPreviewSizes(), screenWidth, screenHeight);//Bug Fix for Samsung A8
            mParameters.setPreviewSize(optimalPreviewSize.width, optimalPreviewSize.height);
            mParameters.setPictureSize(optimalPreviewSize.width, optimalPreviewSize.height);
            mParameters.setPreviewFpsRange(30000, 30000);
            mCamera.setParameters(mParameters);*/
            /*mCamera.setPreviewDisplay(holder);
            mCamera.setPreviewCallback(previewCallback);*/


            mCamera.setPreviewDisplay(holder);
         catch (IOException exception) 
            mCamera.release();
            mCamera = null;
            //previewCount = 0;
         catch (Exception exception) 
            mCamera = null;
            //previewCount = 0;
        

        if (mCameraPreviewListener != null) 
            mCameraPreviewListener.onCameraSurfaceCreated();
        
    



    public void surfaceDestroyed(SurfaceHolder holder) 
        if (mCamera != null) 
            mCamera.stopPreview();
            mCamera.setPreviewCallback(null);
            mCamera.release();
            mCamera = null;
            //previewCount = 0;
        
        if (mCameraPreviewListener != null) 
            mCameraPreviewListener.onCameraSurfaceDestroyed();
        
    

    public void stopCamera() 
        if (mCamera != null) 
            mCamera.stopPreview();
            mCamera.setPreviewCallback(null);
            mCamera.release();
            mCamera = null;
            //previewCount = 0;
        
    

    @SuppressWarnings("null")
    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) 
        try 
            // Now that the size is known, set up the camera parameters and begin
            // the preview.
            mParameters = mCamera.getParameters();

            Log.d("CameraFix", "parameters -> " + mParameters.flatten());

            setCameraDisplayOrientation(mContext, 0, mCamera);


            mParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);

            //Size optimalPreviewSize = getOptimalPreviewSize(mParameters.getSupportedPreviewSizes(), getWidth(), getHeight());
            DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics();
            int screenWidth = displayMetrics.widthPixels;
            int screenHeight = displayMetrics.heightPixels;

            //Size optimalPreviewSize = getOptimalPreviewSize(mParameters.getSupportedPreviewSizes(), screenWidth, screenHeight, getHeight());
            mSupportedPreviewSizes = mParameters.getSupportedPreviewSizes();
            optimalPreviewSize = getBestAspectPreviewSize(mParameters.getSupportedPreviewSizes(), screenWidth, screenHeight);//Bug Fix for Samsung A8

            Log.d("CameraFix", "optimalPreviewSize.width -> " + optimalPreviewSize.width);
            Log.d("CameraFix", "optimalPreviewSize.height -> " + optimalPreviewSize.height);

            mParameters.setPreviewSize(optimalPreviewSize.width, optimalPreviewSize.height);
            mParameters.setPictureSize(optimalPreviewSize.width, optimalPreviewSize.height);
            mParameters.setPreviewFpsRange(30000, 30000);

            /*if (mDisplayOrientation == 0 || mDisplayOrientation == 180) 
                setLayoutParams(new FrameLayout.LayoutParams(optimalPreviewSize.width, optimalPreviewSize.height,Gravity.CENTER));
            */


            Log.d("CameraFix", "setPreviewFpsRange");

            mCamera.setParameters(mParameters);

            mCamera.setPreviewDisplay(holder);

            //SurfaceTexture st = new SurfaceTexture(10);
            //mCamera.setPreviewTexture(st);
            mCamera.setPreviewCallback(previewCallback);
            mCamera.startPreview();
            Log.d("CameraFix", "start preview");
            if (mCameraPreviewListener != null) 
                mCameraPreviewListener.onCameraSurfaceChanged();
            

         catch (Exception e) 
            e.printStackTrace();
            Log.d("CameraFix", e.toString());
        

    

public void toggleFlash(boolean flashModeOn) 
        if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)) 
            Parameters parameters = mCamera.getParameters();
            if (flashModeOn) 
                //parameters.setFlashMode(Parameters.FLASH_MODE_TORCH);
                parameters.setFlashMode(Parameters.FLASH_MODE_ON);
                mCamera.setParameters(parameters);
                mCamera.startPreview();
                //Toast.makeText(mContext, R.string.flash_mode_on, Toast.LENGTH_SHORT).show();
             else 
                parameters.setFlashMode(Parameters.FLASH_MODE_OFF);
                mCamera.setParameters(parameters);
                //Toast.makeText(mContext, R.string.flash_mode_off, Toast.LENGTH_SHORT).show();
            

         else 
            Toast.makeText(mContext, R.string.flash_not_available, Toast.LENGTH_SHORT).show();
        
    

/**
     * Source for this solution - https://***.com/questions/21354313/camera-preview-quality-in-android-is-poor/21354442#21354442
     *
     * @param supportedPreviewSizes
     * @param screenWidth
     * @param screenHeight
     * @return
     */
    private Size getBestAspectPreviewSize(List<Size> supportedPreviewSizes, int screenWidth, int screenHeight) 
        double targetRatio = (double) screenWidth / screenHeight;
        Camera.Size optimalSize = null;
        double minDiff = Double.MAX_VALUE;

        for (int i = 0; i < supportedPreviewSizes.size(); i++) 
            Size size = supportedPreviewSizes.get(i);
            Log.d(TAG, "getBestAspectPreviewSize: supportedPreviewSizes -> "+size.width +"X"+size.height);
        

        Log.d(TAG, "getBestAspectPreviewSize: supportedPreviewSizes -> "+supportedPreviewSizes.toString());
        Log.d(TAG, "getBestAspectPreviewSize: mDisplayOrientation -> "+mDisplayOrientation);

        if (mDisplayOrientation == 90 || mDisplayOrientation == 270) 
            Log.d(TAG, "getBestAspectPreviewSize: inside 90 - 270 ");
            targetRatio = (double) screenHeight / screenWidth;
        


        Log.d(TAG, "getBestAspectPreviewSize: targetRatio -> "+targetRatio);

        Collections.sort(supportedPreviewSizes,
                Collections.reverseOrder(new SizeComparator()));

        for (Size size : supportedPreviewSizes) 
            double ratio = (double) size.width / size.height;

            if (Math.abs(ratio - targetRatio) < minDiff) 
                optimalSize = size;
                minDiff = Math.abs(ratio - targetRatio);
            

            if (minDiff < 0.0d) 
                break;
            
        
        return (optimalSize);

        /*if (mDisplayOrientation == 0 || mDisplayOrientation == 180) 
            if (optimalSize != null) 
                return mCamera.new Size(optimalSize.height, optimalSize.width);
             else 
                return null;
            
        
        else
            return (optimalSize);
        */

        //return mCamera.new Size(2220,1080);
    

    public int getDisplayOrientation() 
        return mDisplayOrientation;
    

    public void setDisplayOrientation(int displayOrientation) 
        this.mDisplayOrientation = displayOrientation;
    

    public Parameters getCameraParameters() 
        return mCamera.getParameters();
    

public void setCameraPreviewListener(CameraPreviewListener cameraPreviewListener) 
        mCameraPreviewListener = cameraPreviewListener;
    

    public interface CameraPreviewListener 
        void onCameraSurfaceCreated();

        void onCameraSurfaceChanged();

        void onCameraSurfaceDestroyed();

        void onCameraPreviewStarted();
    

    private static class SizeComparator implements
            Comparator<Size> 
        @Override
        public int compare(Size lhs, Size rhs) 
            int left = lhs.width * lhs.height;
            int right = rhs.width * rhs.height;

            if (left < right) 
                return (-1);
             else if (left > right) 
                return (1);
            

            return (0);
        
    

【问题讨论】:

从您的图片中我们可以看到,这并不是完全全屏的。右侧有导航栏,顶部有系统工具栏。为什么不添加一点黑边来保持预览窗口的纵横比为 16:9? 相机预览是全屏的,并在 Framelayout 的顶部添加了导航栏...我知道没有慢跑预览并添加一些空格是没有办法的。所以将预览大小设置为 1920X1080 并将预览居中。现在它看起来像预览框架。但是仍然不明白为什么三星不提供支持的预览尺寸,即使他们已经知道了。 我完全支持你的反问。请注意,您还有一个替代选项,即填充屏幕的所有宽度,但在顶部和底部裁剪预览框(这就像添加负大小的边距)。 @Ramprasad Hi Ram 你能看看我的代码,它发布了一个答案,让我知道。 【参考方案1】:
    您应该再次检查默认相机的可显示区域。我不认为它可以在没有拉伸的情况下完全显示该分辨率。它可能有一个黑色区域、工具栏、状态栏... 您的实施没有任何问题。我们必须找到与您要显示的表面视图相比的最佳支持预览尺寸。在这种情况下,您应该使表面视图 (1920 x 1080) 居中,然后在顶部和底部添加黑色填充区域。

【讨论】:

我将预览大小设置为 1920X1080 并将预览居中。现在它看起来像预览框架。但是仍然不明白为什么三星不提供全屏尺寸作为支持的预览尺寸,即使他们已经知道了。 我们对供应商一无所知。在开发照片共享应用程序时,我在许多设备中都遇到了这个问题。在某些设备中,您可以选择预览分辨率,它们会裁剪预览以保持比例。您必须选择处理所有这些问题的最佳方式。祝你好运。【参考方案2】:

请查看我的回答希望对您有所帮助,我通过以下代码解决了拉伸问题,方法名称可能会更改。我分享我的实现,因为我知道在Android中实现相机有多难,所以请不要犹豫,看看下面的部分。

在 ButtonAction 中调用 loadCamera 方法。

private void loadCamera() 
        if (CommonUtils.deviceHasCamera(getActivityContext)) 
            startBackgroundThread();
            mCameraTimeOut=(isPermissionGranted?2500:5000);
            if (mTextureView.isAvailable()) 
                openCamera(mTextureView.getWidth(), mTextureView.getHeight());
             else 
                mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
            
        else
            ShowToastUtils.INSTANCE.showCustomToast(getActivityContext, getString(R.string.msg_no_camera));
        
    

最初为相机调用 SurfaceListener

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

        @Override
        public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture,
                                              int width, int height) 
            mCameraTimeOut=(isPermissionGranted?2500:5000);
            Log.e(TAG1, "chooseOptimalSize"+"-SurfaceTextureListener ---=>Width---=>"+width);
            Log.e(TAG1, "chooseOptimalSize"+"-SurfaceTextureListener ---=>Height---=>"+height);
            openCamera(width, height);
        

        @Override
        public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture,
                                                int width, int height) 
            configureTransform(width, height);
        

        @Override
        public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) 
            return true;
        

        @Override
        public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) 

    ;

为纹理选择最佳预览尺寸

//Samsung-S6-choices[0]
//Samsung-S7-edge-choices[6]
//OnePlus-5T-choices[15]
/*Following is used for Camera Preview in TextureView,  based on device camera resolution*/
    /*
     * Given @code choices of @code Sizes supported by a camera, chooses the smallest one whose
     * width and height are at least as large as the respective requested values, and whose aspect
     * ratio matches with the specified value.
     *
     * @param choices     The list of sizes that the camera supports for the intended output class
     * @param width       The minimum desired width
     * @param height      The minimum desired height
     * @param aspectRatio The aspect ratio
     * @return The optimal @code Size, or an arbitrary one if none were big enough
     */

     private  Size chooseOptimalSize(Size[] choices, int width, int height, Size aspectRatio) 
        // Collect the supported resolutions that are at least as big as the preview Surface

        int loopCounter=0;
        Log.e(TAG1, "Screen-->Width x Height="+screenWidth+" x "+screenHeight);
        for (Size size : choices) 
            Log.e(TAG1, "chooseOptimalSize:"+size);
        
        for (Size size : choices) 
            int orientation = getActivityContext.getResources().getConfiguration().orientation;
            if (orientation == Configuration.ORIENTATION_LANDSCAPE) 
                if((size.getWidth()/16) == (size.getHeight()/9) && size.getWidth() <=7680 ) //8K UHDTV Super Hi-Vision
                    Log.e(TAG1, "chooseOptimalSize:"+size.getWidth()+"x"+size.getHeight()+"--LoopPosition---==>"+loopCounter);
                    return size;
                
             else 
                Log.e(TAG1, "chooseOptimalSize:--given--"+size);
                if((size.getWidth()/16) == (size.getHeight()/9) && ((size.getWidth() <=1280)||(size.getHeight()<=1920))) 
                    mCameraRatio=RATIO_16_9;
                    Log.e(TAG1, "chooseOptimalSize:"+size.getWidth()+"x"+size.getHeight()+"-16:9"+"--LoopPosition---==>"+loopCounter);
                    return size;
                else if((size.getWidth()/18) == (size.getHeight()/9) && ((size.getWidth() <=2160)||(size.getHeight()<=3840))) 
                    mCameraRatio=RATIO_18_9;
                    Log.e(TAG1, "chooseOptimalSize:"+size.getWidth()+"x"+size.getHeight()+"-18:9"+"--LoopPosition---==>"+loopCounter);
                    return size;
                else if((size.getWidth()/18.5) == (size.getHeight()/9) && ((size.getWidth() <=2160)||(size.getHeight()<=3840))) 
                    mCameraRatio=RATIO_18_9;
                    Log.e(TAG1, "chooseOptimalSize:"+size.getWidth()+"x"+size.getHeight()+"-18.5:9"+"--LoopPosition---==>"+loopCounter);
                    return size;
                else if((width/19) == (height/9) && ((width <=2208)||(height<=3216))) 
                    mCameraRatio=RATIO_19_9;
                    Log.e(TAG1, "chooseOptimalSize:"+size.getWidth()+"x"+size.getHeight()+"-19:9"+"--LoopPosition---==>"+loopCounter);
                    return size;
                else if((size.getWidth()/19.5) == (size.getHeight()/9) && ((size.getWidth() <=3840)||(size.getHeight()<=2160))) 
                    mCameraRatio=RATIO_19_9;
                    Log.e(TAG1, "chooseOptimalSize:"+size.getWidth()+"x"+size.getHeight()+"-19.5:9"+"--LoopPosition---==>"+loopCounter);
                    return size;
                else
                    Log.e(TAG1, "chooseOptimalSize"+" not proper aspect resolution");
                
            
                  loopCounter++;
        

打开相机

    private void openCamera(int width, int height) 
                CameraManager manager = (CameraManager) getActivityContext.getSystemService(Context.CAMERA_SERVICE);
                try 
                    Log.e(TAG, "tryAcquire");
                    if (!mCameraOpenCloseLock.tryAcquire(mCameraTimeOut, TimeUnit.MILLISECONDS)) 
                        throw new RuntimeException("Time out waiting to lock camera opening.");
                    
                    String mCameraId = manager.getCameraIdList()[cameraId];
                    // Choose the sizes for camera preview and video recording
                    characteristics = manager.getCameraCharacteristics(mCameraId);
                    StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
                    try 
                        mSensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
                        maximumZoomLevel = characteristics.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM);
                        if (map == null) 
                            throw new RuntimeException("Cannot get available preview/video sizes");
                        
                        mVideoSize = chooseVideoSize(map.getOutputSizes(MediaRecorder.class));
    /*This Line will configure the Texture size*/
                        mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class), width, height, mVideoSize);


int orientation = getResources().getConfiguration().orientation;
                    if (orientation == Configuration.ORIENTATION_LANDSCAPE) 
                        Log.e(TAG1, "Width" + mPreviewSize.getWidth() + "X Height" + mPreviewSize.getHeight());
                        mTextureView.setAspectRatio(mPreviewSize.getWidth(), mPreviewSize.getHeight());
                     else 
                        Log.e(TAG1, "Width" + mPreviewSize.getHeight() + "X Height" + mPreviewSize.getWidth());
                        mTextureView.setAspectRatio(mPreviewSize.getHeight(), mPreviewSize.getWidth());
    //S10 preview Size
                        /* mTextureView.setAspectRatio(1080, 2280);*/
                        //mTextureView.setAspectRatio(2208, 2944);
                    
                    if (orientation == Configuration.ORIENTATION_LANDSCAPE) 
                        configureTransform(width, height);
                    

                    if (isPermissionGranted) 
                        manager.openCamera(mCameraId, mStateCallback, null);
                    

                catch (Exception ex)ex.printStackTrace();finally 
                    map=null;
                    Runtime.getRuntime().gc();
                
             catch (CameraAccessException e) 
                Toast.makeText(getActivityContext, "Cannot access the camera.", Toast.LENGTH_SHORT).show();
                //getActivityContext.finish();
                e.printStackTrace();
             catch (NullPointerException e) 
                e.printStackTrace();

             catch (InterruptedException e) 
                e.printStackTrace();
                throw new RuntimeException("Interrupted while trying to lock camera opening.");
            
        

用于方向处理的ConfigureTransform方法

/*
     * Configures the necessary @link android.graphics.Matrix transformation to `mTextureView`.
     * This method should not to be called until the camera preview size is determined in
     * openCamera, or until 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) 
    if (null == mTextureView || null == mPreviewSize) 
        return;
    
    int rotation = getActivityContext.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_0 == rotation) 
        bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
        matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
        float scale=Math.max((float) viewWidth / mPreviewSize.getWidth(), (float) viewHeight / mPreviewSize.getHeight());
        matrix.postScale(scale, scale, centerX, centerY);
        matrix.postRotate(0, centerX, centerY);
    else if(Surface.ROTATION_180== rotation)
        bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
        matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
        float scale=Math.max((float) viewWidth / mPreviewSize.getWidth(), (float) viewHeight / mPreviewSize.getHeight());
        matrix.postScale(scale, scale, centerX, centerY);
        matrix.postRotate(0, centerX, centerY);
    
    try 
        mTextureView.setTransform(matrix);
    catch (Exception ex)ex.printStackTrace();finally 
        bufferRect=null;
        viewRect=null;
        matrix=null;
    

终于开始预览

private void startPreview() 
        if (null == mCameraDevice || !mTextureView.isAvailable() || null == mPreviewSize) 
            return;
        
        try 
            closePreviewSession();
            SurfaceTexture texture = mTextureView.getSurfaceTexture();
            assert texture != null;
            texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
            //texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
            mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            Surface previewSurface = new Surface(texture);
            mPreviewBuilder.addTarget(previewSurface);
            mCameraDevice.createCaptureSession(Collections.singletonList(previewSurface),
                    new CameraCaptureSession.StateCallback() 
                        @Override
                        public void onConfigured(@NonNull CameraCaptureSession session) 
                            mPreviewSession = session;
                            updatePreview();
                        
                        @Override
                        public void onConfigureFailed(@NonNull CameraCaptureSession session) 
                            Toast.makeText(getActivityContext, "Failed", Toast.LENGTH_SHORT).show();
                        
                    , mBackgroundHandler);
            //previewSurface=null;
         catch (CameraAccessException e) 
            e.printStackTrace();
        
    

【讨论】:

以上是关于三星 S9(18:9) 相机预览拉长的主要内容,如果未能解决你的问题,请参考以下文章

Android 三星 Galaxy S4 自定义相机预览失真

三星 Galaxy S3 上的 Android 相机预览不正确

GALAXY S9狂怼iPhone X,三星又拍广告黑苹果?

三星又拍广告黑苹果,这次是拿 GALAXY S9 怼 iPhone X

我无法通过三星 S9+ 的 DatagramSocket 发送 DatagramPacket(我使用的不是 UI 线程)

相机预览在少数 Android 设备上延伸