如何解决“android.view.SurfaceView.getHolder()在空对象引用上”的问题?

3
public class CameraFragment extends Fragment implements SurfaceHolder.Callback,View.OnClickListener {
    // Defined All Field
    private SurfaceView surfaceView;
    private SurfaceHolder surfaceHolder;
    private Camera camera;
    private ImageView ImgThumbnail;
    private Button btnFlash, btnFrontCamera, btnCapture;
    private int cameraId;
    private boolean flashmode = false;
    private int rotation;
    private String SavedImagePath;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_camera, container,false);
        // Camera surface view created
        cameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
        btnFlash = (Button) container.findViewById(R.id.btnFlash);
        btnFrontCamera = (Button) container.findViewById(R.id.btnFrontCamera);
        btnCapture = (Button) container.findViewById(R.id.btnCapture);
        surfaceView = (SurfaceView) container.findViewById(R.id.surfaceView);
        surfaceHolder = surfaceView.getHolder();
        surfaceHolder.addCallback(this);
        ImgThumbnail = (ImageView) container.findViewById(R.id.ImgThumbnail);
        btnFrontCamera.setOnClickListener(this);
        btnCapture.setOnClickListener(this);
        btnFlash.setOnClickListener(this);        getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        if (Camera.getNumberOfCameras() > 1) {
            btnFrontCamera.setVisibility(View.VISIBLE);
        }
        if (!getActivity().getBaseContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)) {
            btnFlash.setVisibility(View.GONE);
        }
        return view;
    }
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        if (!openCamera(Camera.CameraInfo.CAMERA_FACING_BACK)) {
            alertCameraDialog();
        }
    }
    private boolean openCamera(int id) {
        boolean result = false;
        cameraId = id;
        releaseCamera();
        try {
            camera = Camera.open(cameraId);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (camera != null) {
            try {
                setUpCamera(camera);
                camera.setErrorCallback(new Camera.ErrorCallback() {

                    @Override
                    public void onError(int error, Camera camera) {
                    }
                });
                camera.setPreviewDisplay(surfaceHolder);
                camera.startPreview();
                result = true;
            } catch (IOException e) {
                e.printStackTrace();
                result = false;
                releaseCamera();
            }
        }
        return result;
    }
    private void setUpCamera(Camera c) {
        Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
        Camera.getCameraInfo(cameraId, cameraInfo);

        rotation = getActivity().getWindowManager().getDefaultDisplay().getRotation();
        int degree = 0;
        switch (rotation) {
            case Surface.ROTATION_0:
                degree = 0;
                break;
            case Surface.ROTATION_90:
                degree = 90;
                break;
            case Surface.ROTATION_180:
                degree = 180;
                break;
            case Surface.ROTATION_270:
                degree = 270;
                break;
            default:
                break;
        }
        if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            // Front Facing
            rotation = (cameraInfo.orientation + degree) % 330;
            rotation = (360 - rotation) % 360;
        } else {
            // Back Facing
            rotation = (cameraInfo.orientation - degree + 360) % 360;
        }
        c.setDisplayOrientation(rotation);
        Camera.Parameters params = c.getParameters();
        showFlashButton(params);
        List<String> focusModes = params.getSupportedFlashModes();
        if (focusModes != null) {            if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {                params.setFlashMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
            }
        }
        params.setRotation(rotation);
    }
    private void showFlashButton(Camera.Parameters params) {
        boolean showFlash = (getActivity().getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_CAMERA_FLASH) && params.getFlashMode() != null)
                && params.getSupportedFlashModes() != null
                && params.getSupportedFocusModes().size() > 1;
        btnFlash.setVisibility(showFlash ? View.VISIBLE : View.INVISIBLE);
    }
    private void releaseCamera() {
        try {
            if (camera != null) {
                camera.setPreviewCallback(null);
                camera.setErrorCallback(null);
                camera.stopPreview();
                camera.release();
                camera = null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            Log.e("error", e.toString());
            camera = null;
        }
    }
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    }
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btnFlash:
                flashOnButton();
                break;
            case R.id.btnFrontCamera:
                flipCamera();
                break;
            case R.id.btnCapture:
                takeImage();
                break;
            default:
                break;
        }
    }
    private void flashOnButton() {
        if (camera != null) {
            try {
                Camera.Parameters param = camera.getParameters();
                param.setFlashMode(!flashmode ? Camera.Parameters.FLASH_MODE_TORCH : Camera.Parameters.FLASH_MODE_OFF);
                camera.setParameters(param);
                flashmode = !flashmode;
                Toast.makeText(getActivity(), "Flash Touch", Toast.LENGTH_SHORT).show();
            } catch (Exception e) {
                // TODO: handle exception
            }
        }
    }
    private void takeImage() {
        camera.takePicture(null, null, new Camera.PictureCallback() {
            private File imageFile;
            @Override
            public void onPictureTaken(byte[] data, Camera camera) {
                try {
                    // Convert byte array into bitmap
                    Bitmap loadedImage = BitmapFactory.decodeByteArray(data, 0, data.length);
                    // rotate Image
                    Matrix rotateMatrix = new Matrix();
                    rotateMatrix.postRotate(rotation);
                    Bitmap rotatedBitmap = Bitmap.createBitmap(loadedImage, 0, 0, loadedImage.getWidth(), loadedImage.getHeight(), rotateMatrix, false);
                    final File folder;
                    if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                        folder = new File(Environment.getExternalStorageDirectory() + "/CameraApp");
                    } else {
                        folder = new File(Environment.getExternalStorageDirectory() + "/CameraApp");
                    }
                    boolean success = true;
                    if (!folder.exists()) {
                        success = folder.mkdirs();
                    }
                    if (success) {
                        java.util.Date date = new java.util.Date();
                        imageFile = new File(folder.getAbsolutePath() + File.separator + new Timestamp(date.getTime()).toString() + " " + "Image.jpg");
                        SavedImagePath = new Timestamp(date.getTime()).toString() + " " + "Image.jpg";
                        imageFile.createNewFile();
                    } else {
                        Toast.makeText(getActivity().getBaseContext(), "Image Not saved", Toast.LENGTH_SHORT).show();
                        return;
                    }
                    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                    // Save image into gallery
                    rotatedBitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
                    FileOutputStream file_out = new FileOutputStream(imageFile);
                    file_out.write(outputStream.toByteArray());
                    file_out.close();
                    ContentValues values = new ContentValues();
                    values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis());
                    values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
                    values.put(MediaStore.MediaColumns.DATA, imageFile.getAbsolutePath());                    getActivity().getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
                    Toast.makeText(getActivity(), "Photo Captured", Toast.LENGTH_SHORT).show();
                    // Code For Captured Image Save in a ImageView.
                    getActivity().runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            String imagePath = folder.getAbsolutePath() + File.separator + SavedImagePath;
                            Uri myURI = Uri.parse(imagePath);
                            ImgThumbnail.setImageURI(myURI);
                            Toast.makeText(getActivity(), "Photo Saved on ImageView", Toast.LENGTH_SHORT).show();
                        }
                    });
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
    private void flipCamera() {
        int id = (cameraId == Camera.CameraInfo.CAMERA_FACING_BACK ? Camera.CameraInfo.CAMERA_FACING_FRONT : Camera.CameraInfo.CAMERA_FACING_BACK);
        Toast.makeText(getActivity(), "Camera Mode Changing", Toast.LENGTH_SHORT).show();
        if (!openCamera(id)) {
            alertCameraDialog();
        }
    }
    private void alertCameraDialog() {
        AlertDialog.Builder dialog = createAlert(getActivity(), "Camera info", "Error to open camera");
        dialog.setNegativeButton("OK", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.cancel();
            }
        });
        dialog.show();
    }
    private AlertDialog.Builder createAlert(Context context, String Title, String Message) {
        AlertDialog.Builder dialog = new AlertDialog.Builder(new ContextThemeWrapper(context, android.R.style.Theme_Holo_Light_Dialog));
        dialog.setIcon(R.drawable.info_for_camera);
        if (Title != null)
            dialog.setTitle(Title);
        else
            dialog.setTitle("Information");
        dialog.setMessage(Message);
        dialog.setCancelable(false);
        return dialog;
    }

这里没有太多细节,而且只有代码(没有解释或上下文)的问题往往会在这里被关闭。你想做什么?你能把堆栈跟踪编辑到你的问题中,并使用代码工具进行格式化吗?你是否已经将问题追踪到特定的代码区域? - halfer
我的问题是...我忘记把所有的onCreateView()代码放到onCreatedView()里面了。 - Sagar Aghara
看到了,Halfer,我按照你说的做了。 对不起,因为我是Stackoverflow上的新手,所以有些错误。 - Sagar Aghara
谢谢@Sagar,感激不尽。不用担心新手,你很快就能掌握它。 - halfer
1个回答

4
每当您发现与我的问题相似时,请执行以下操作。只需将您的 OnCreateView() 代码替换为 onViewCreated(),因为 OnCreateView() 方法仅有助于填充视图。
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
    // Inflate the layout for this fragment
    return inflater.inflate(R.layout.fragment_camera, container, false);
}

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    // Camera surface view created
    mCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
    btnFlash = (Button) view.findViewById(R.id.btnFlash);
    btnFrontCamera = (Button) view.findViewById(R.id.btnFrontCamera);
    btnCapture = (Button) view.findViewById(R.id.btnCapture);

    surfaceView = (SurfaceView) view.findViewById(R.id.surfaceView);
    surfaceHolder = surfaceView.getHolder();
    surfaceHolder.addCallback(this);

    ImgThumbnail = (ImageView) view.findViewById(R.id.ImgThumbnail);

    btnFrontCamera.setOnClickListener(this);
    btnCapture.setOnClickListener(this);
    btnFlash.setOnClickListener(this);
    getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    if (Camera.getNumberOfCameras() > 1) {
        btnFrontCamera.setVisibility(View.VISIBLE);
    }
    if (!getActivity().getBaseContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)) {
        btnFlash.setVisibility(View.GONE);
    }
}

不偏不倚,两种方法都是正确的,没有错误。第一种方法onCreateView()仅用于填充ViewGroup,而onViewCreated()则用于获取填充视图的参数。 - Sagar Aghara
你可以在这里找到两种方法的区别:https://dev59.com/wF8f5IYBdhLWcg3wB-wU - Sagar Aghara

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接