android - 如何在 fragment 中再次初始化相机?

标签 android android-fragments camera onresume onpause

我正在使用这个条形码阅读器代码,当应用程序进入 onPause() 阶段然后返回到 onResume() 时,它会卡住。当应用程序进入 onPause() 阶段时,相机会被释放,这就是它卡住的原因。我尝试在 onResume() 中再次初始化相机,但在首次调用 fragment 时也会调用它,所以我如何再次初始化相机?我还建议使用 onPostResume() 但我不能在 fragment 中使用它。那么你能指导我吗?

这是 fragment :

public class BarcodeReaderFragment extends Fragment {

    private Camera mCamera;
    private CameraPreview mPreview;
    private Handler autoFocusHandler;

    TextView scanText, refreshbarcode;
    Button scanButton, homeButton;
    ImageScanner scanner;

    private boolean barcodeScanned = false;
    private boolean previewing = true;

    static {
        System.loadLibrary("iconv");
    }
    FragmentManager fragmentManager;
    FrameLayout preview;
    Typeface font;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        font = Typeface.createFromAsset(getActivity().getAssets(),
                "fontello.ttf");
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.barcodereader_fragment,
                container, false);
        getActivity().setRequestedOrientation(
                ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

        ((MainActivity) getActivity()).getMenuListView()
                .setItemChecked(0, true);
        ((MainActivity) getActivity()).getMenuListView().setSelection(0);

        refreshbarcode = (TextView) view.findViewById(R.id.refreshbarcode);
        refreshbarcode.setTypeface(font);
        refreshbarcode.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                fragmentManager = getActivity().getSupportFragmentManager();
                FragmentTransaction fragmentTransaction = fragmentManager
                        .beginTransaction();
                fragmentTransaction.replace(R.id.frame_container,
                        new BarcodeReaderFragment());
                fragmentTransaction.commit();
            }
        });

        homeButton = (Button) view.findViewById(R.id.homebutton);
        homeButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                fragmentManager = getActivity().getSupportFragmentManager();
                FragmentTransaction fragmentTransaction = fragmentManager
                        .beginTransaction();
                fragmentTransaction.replace(R.id.frame_container,
                        HomeFragment.newInstance());
                fragmentTransaction.commit();
            }
        });

        autoFocusHandler = new Handler();
        mCamera = getCameraInstance();

        /* Instance barcode scanner */
        scanner = new ImageScanner();
        scanner.setConfig(0, Config.X_DENSITY, 3);
        scanner.setConfig(0, Config.Y_DENSITY, 3);

        mPreview = new CameraPreview(getActivity(), mCamera, previewCb,
                autoFocusCB);
        preview = (FrameLayout) view.findViewById(R.id.cameraPreview);
        preview.addView(mPreview);

        scanText = (TextView) view.findViewById(R.id.scanText);

        fragmentManager = getActivity().getSupportFragmentManager();

        return view;
    }

    @Override
    public void onPause() {
        super.onPause();
        releaseCamera();
    }

    @Override
    public void onResume() {
        Log.i("DEBUG", "onResume of HomeFragment");
        getActivity().setRequestedOrientation(
                ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        autoFocusHandler = new Handler();
        mCamera = getCameraInstance();

        /* Instance barcode scanner */
        scanner = new ImageScanner();
        scanner.setConfig(0, Config.X_DENSITY, 3);
        scanner.setConfig(0, Config.Y_DENSITY, 3);

        mPreview = new CameraPreview(getActivity(), mCamera, previewCb,
                autoFocusCB);
        preview.removeAllViews();
        preview.addView(mPreview);

        super.onResume();
    }

    /** A safe way to get an instance of the Camera object. */
    public static Camera getCameraInstance() {
        Camera c = null;
        try {
            c = Camera.open();
        } catch (Exception e) {
        }
        return c;
    }

    private void releaseCamera() {
        if (mCamera != null) {
            previewing = false;
            mCamera.setPreviewCallback(null);
            mCamera.release();
            mCamera = null;
        }
    }

    private Runnable doAutoFocus = new Runnable() {
        public void run() {
            if (previewing)
                mCamera.autoFocus(autoFocusCB);
        }
    };

    PreviewCallback previewCb = new PreviewCallback() {
        public void onPreviewFrame(byte[] data, Camera camera) {
            Camera.Parameters parameters = camera.getParameters();
            Size size = parameters.getPreviewSize();

            Image barcode = new Image(size.width, size.height, "Y800");
            barcode.setData(data);

            int result = scanner.scanImage(barcode);

            if (result != 0) {

                SymbolSet syms = scanner.getResults();
                for (Symbol sym : syms) {
                    scanText.setText("Barkod Sonucu: " + sym.getData());
                    scanText.setTextColor(Color.parseColor("#00AF03"));
                    barcodeScanned = true;
                    releaseCamera();
                    Intent intent = new Intent();
                    intent.putExtra("SCAN_RESULT", sym.getData());
                    getActivity().setResult(getActivity().RESULT_OK, intent);
                }
            }
        }
    };

    // Mimic continuous auto-focusing
    AutoFocusCallback autoFocusCB = new AutoFocusCallback() {
        public void onAutoFocus(boolean success, Camera camera) {
            autoFocusHandler.postDelayed(doAutoFocus, 1000);
        }
    };

}

CameraPreview 代码:

/*
 * Barebones implementation of displaying camera preview.
 * 
 * Created by lisah0 on 2012-02-24
 */


/** A basic Camera preview class */
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
    private SurfaceHolder mHolder;
    private Camera mCamera;
    private PreviewCallback previewCallback;
    private AutoFocusCallback autoFocusCallback;

    public CameraPreview(Context context, Camera camera,
                         PreviewCallback previewCb,
                         AutoFocusCallback autoFocusCb) {
        super(context);
        mCamera = camera;
        previewCallback = previewCb;
        autoFocusCallback = autoFocusCb;

        /* 
         * Set camera to continuous focus if supported, otherwise use
         * software auto-focus. Only works for API level >=9.
         */

        Camera.Parameters parameters = camera.getParameters();
        for (String f : parameters.getSupportedFocusModes()) {
            if (f == Parameters.FOCUS_MODE_CONTINUOUS_PICTURE) {
                mCamera.autoFocus(autoFocusCb);

                //mCamera.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
                autoFocusCallback = null;
                break;
            }
        }


        // 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);
        } catch (IOException e) {
            Log.d("DBG", "Error setting camera preview: " + e.getMessage());
        }
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        // Camera preview released in activity
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        /*
         * 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
        }

        try {
            if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
                mCamera.setDisplayOrientation(90);              
            }
            else if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
                mCamera.setDisplayOrientation(0);
            }

            mCamera.setPreviewDisplay(mHolder);
            mCamera.setPreviewCallback(previewCallback);
            mCamera.startPreview();
            mCamera.autoFocus(autoFocusCallback);
        } catch (Exception e){
            Log.d("DBG", "Error starting camera preview: " + e.getMessage());
        }
    }
}

最佳答案

您可以简单地从 onCreateView 中删除与相机相关的代码。 onResume 就足够了。

关于android - 如何在 fragment 中再次初始化相机?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27638950/

相关文章:

java - java中如何让相机朝它所面对的方向移动?

java - 尝试使用 DOM 解析 XML 文件时出现 NullPointerException

android - RecyclerView 项目的按下状态

android - 在具有嵌套 fragment 的 View 寻呼机上方显示对话框

c# - 从我的 WP8 应用程序启动外部相机应用程序

Python OpenCV cv2.VideoWriter 错误

Android ...如何确定我是否在使用 wifi 互联网?

Android Jetpack 导航 - 带抽屉项的自定义操作

java - Android - 搜索 View 中的空指针异常

android - 从后台获取 fragment