Metoda wywołana po wydaniu wyjątku podgląd kamery

Mam jedną klasę aktywności (CameraActivity), która używa mojej klasy CameraPreview. W "OnResume" kamera i podgląd są inicjowane. W "OnPause" wypuszczam zasoby aparatu. Kiedy aplikacja jest uruchomiona, wszystko działa dobrze wewnątrz "OnResume", ale kiedy rozpoczynam inną aktywność poprzez intent (np. Otwórz adres url w przeglądarce), a następnie wracam do mojej aktywności, wtedy wyjątek występuje wewnątrz" OnResume " pochodzącej klasy CamerPreview. Poniżej znajdują się kod:

//Klasa Działania Aparatu

public void onResume(){
    super.onResume();
    Log.d("inside onResume, camera==="+mCamera, "inside onResume");
    try {
        if(mCamera==null)
        {

    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);


        autoFocusHandler = new Handler();
        mCamera = getCameraInstance();
        int rotation = this.getWindowManager().getDefaultDisplay().getRotation();


        scanner = new ImageScanner();
        scanner.setConfig(0, Config.X_DENSITY, 3);
        scanner.setConfig(0, Config.Y_DENSITY, 3);

        mPreview = new CameraPreview(this, mCamera, previewCb, autoFocusCB);

        FrameLayout preview = (FrameLayout)findViewById(R.id.cameraPreview);
        preview.addView(mPreview);



    }





} catch (Exception e) {
    // TODO Auto-generated catch block
    Log.e("onResume",Log.getStackTraceString(e));
}



public void onPause{
    try {
        super.onPause();
        if (mCamera != null) {
            previewing = false;
            mCamera.stopPreview();
                mCamera.setPreviewCallback(null);
                mCamera.release();
                mCamera = null;
                mPreview=null;


    }
} catch (Exception e) {
    // TODO Auto-generated catch block
    Log.e("releaseCamera",Log.getStackTraceString(e));
}
}



 public static Camera getCameraInstance(){
        Camera c = null;
        try {
            c = Camera.open();
        } catch (Exception e){
            Log.e("getCameraInstance",Log.getStackTraceString(e));

    }
    return c;
}

// Poniżej znajduje się Klasa CameraPreview:

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
    private SurfaceHolder mHolder;
    Camera mCamera;
    PreviewCallback previewCallback;
    AutoFocusCallback autoFocusCallback;
    private int rotation;
    public int getRotation() {
        return rotation;
    }

    public void setRotation(int rotation) {
        this.rotation = rotation;
    }

    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.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 {
            if(mCamera==null){
                mCamera=Camera.open();
            }
            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{
            mCamera.setPreviewDisplay(mHolder);
            mCamera.setPreviewCallback(previewCallback);
            mCamera.startPreview();
            mCamera.autoFocus(autoFocusCallback);
        } catch (Exception e){
            Log.d("DBG", "Error starting camera preview: " + e.getMessage());
        }
    }

}

To jest z logCat:

11-05 10:14:34.585: E/AndroidRuntime(7864): FATAL EXCEPTION: main
11-05 10:14:34.585: E/AndroidRuntime(7864): java.lang.RuntimeException: Method called after release()
11-05 10:14:34.585: E/AndroidRuntime(7864):     at android.hardware.Camera.setPreviewDisplay(Native Method)
11-05 10:14:34.585: E/AndroidRuntime(7864):     at android.hardware.Camera.setPreviewDisplay(Camera.java:393)
11-05 10:14:34.585: E/AndroidRuntime(7864):     at com.intagleo.qraugmented.detection.camera.CameraPreview.surfaceCreated(CameraPreview.java:74)
11-05 10:14:34.585: E/AndroidRuntime(7864):     at android.view.SurfaceView.updateWindow(SurfaceView.java:552)
11-05 10:14:34.585: E/AndroidRuntime(7864):     at android.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.java:215)
11-05 10:14:34.585: E/AndroidRuntime(7864):     at android.view.View.dispatchWindowVisibilityChanged(View.java:4027)
11-05 10:14:34.585: E/AndroidRuntime(7864):     at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:720)
11-05 10:14:34.585: E/AndroidRuntime(7864):     at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:720)
11-05 10:14:34.585: E/AndroidRuntime(7864):     at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:720)
11-05 10:14:34.585: E/AndroidRuntime(7864):     at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:720)
11-05 10:14:34.585: E/AndroidRuntime(7864):     at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:720)
11-05 10:14:34.585: E/AndroidRuntime(7864):     at android.view.ViewRoot.performTraversals(ViewRoot.java:790)
11-05 10:14:34.585: E/AndroidRuntime(7864):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1867)
11-05 10:14:34.585: E/AndroidRuntime(7864):     at android.os.Handler.dispatchMessage(Handler.java:99)
11-05 10:14:34.585: E/AndroidRuntime(7864):     at android.os.Looper.loop(Looper.java:130)
11-05 10:14:34.585: E/AndroidRuntime(7864):     at android.app.ActivityThread.main(ActivityThread.java:3687)
11-05 10:14:34.585: E/AndroidRuntime(7864):     at java.lang.reflect.Method.invokeNative(Native Method)
11-05 10:14:34.585: E/AndroidRuntime(7864):     at java.lang.reflect.Method.invoke(Method.java:507)
11-05 10:14:34.585: E/AndroidRuntime(7864):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
11-05 10:14:34.585: E/AndroidRuntime(7864):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
11-05 10:14:34.585: E/AndroidRuntime(7864):     at dalvik.system.NativeStart.main(Native Method)

EDIT

Zaktualizowałem " surfaceDestroyed "i wstawiłem logi zgodnie z sugestią, ale teraz dostaję wyjątek w" onPause " -- > onSurfaceDestroyed. Początkowo onpauza wykonywała grzywny.

1 - instancja kamery jest tworzona w "onResume" klasy activity przy pomocy metody "getCameraInstance" i przechodzi instancja mCamera do klasy CameraPreview. Próbowałem to zmienić tak, że instancja aparatu jest tworzony tylko onside "onSurfaceCreated" i przypisane z powrotem wystąpienie mCamera do klasy activity, ale to nie działa. Zauważyłem również poprzez debugowanie, że previewCallBack członek klasy" CameraPreview "jest ważny za pierwszym razem, ale za drugim razem" previewCallBack "członek klasy" CameraPreview " jest null.

Zauważ, że po pierwszym wywołaniu "onResume" wszystko działa dobrze, ale kiedy działa drugi raz po onPause wtedy wyjątek występuje pierwotnie, chociaż kod jest taki sam w onResume.

11-06 01:25:28.375: I/onResume(4332): INITIATED
// Workinf fine till now. Now opening another intent activity
11-06 01:26:23.500: I/onPause(4332): INITIATED
11-06 01:26:23.804: "OnSurfaceDestroyed": "Initiated"
11-06 01:26:23.945: E/AndroidRuntime(4332): FATAL EXCEPTION: main
11-06 01:26:23.945: E/AndroidRuntime(4332): java.lang.RuntimeException: Method called after release()
11-06 01:26:23.945: E/AndroidRuntime(4332):     at android.hardware.Camera.stopPreview(Native Method)
11-06 01:26:23.945: E/AndroidRuntime(4332):     at com.intagleo.qraugmented.detection.camera.CameraPreview.surfaceDestroyed(CameraPreview.java:85)
11-06 01:26:23.945: E/AndroidRuntime(4332):     at android.view.SurfaceView.reportSurfaceDestroyed(SurfaceView.java:596)
11-06 01:26:23.945: E/AndroidRuntime(4332):     at android.view.SurfaceView.updateWindow(SurfaceView.java:490)
11-06 01:26:23.945: E/AndroidRuntime(4332):     at android.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.java:215)
11-06 01:26:23.945: E/AndroidRuntime(4332):     at android.view.View.dispatchWindowVisibilityChanged(View.java:4027)
11-06 01:26:23.945: E/AndroidRuntime(4332):     at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:720)
11-06 01:26:23.945: E/AndroidRuntime(4332):     at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:720)
11-06 01:26:23.945: E/AndroidRuntime(4332):     at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:720)
11-06 01:26:23.945: E/AndroidRuntime(4332):     at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:720)
11-06 01:26:23.945: E/AndroidRuntime(4332):     at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:720)
11-06 01:26:23.945: E/AndroidRuntime(4332):     at android.view.ViewRoot.performTraversals(ViewRoot.java:790)
11-06 01:26:23.945: E/AndroidRuntime(4332):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1867)
11-06 01:26:23.945: E/AndroidRuntime(4332):     at android.os.Handler.dispatchMessage(Handler.java:99)
11-06 01:26:23.945: E/AndroidRuntime(4332):     at android.os.Looper.loop(Looper.java:130)
11-06 01:26:23.945: E/AndroidRuntime(4332):     at android.app.ActivityThread.main(ActivityThread.java:3687)
11-06 01:26:23.945: E/AndroidRuntime(4332):     at java.lang.reflect.Method.invokeNative(Native Method)
11-06 01:26:23.945: E/AndroidRuntime(4332):     at java.lang.reflect.Method.invoke(Method.java:507)
11-06 01:26:23.945: E/AndroidRuntime(4332):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
11-06 01:26:23.945: E/AndroidRuntime(4332):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
11-06 01:26:23.945: E/AndroidRuntime(4332):     at dalvik.system.NativeStart.main(Native Method)
Author: Muhammad Imran Tariq, 2012-11-05

7 answers

Jak dodałeś aparat do FrameLayout, tak:

FrameLayout preview = (FrameLayout)findViewById(R.id.cameraPreview);
preview.addView(mPreview);

Metoda surfaceCreated zostanie wywołana, a więc mCamera.setPreviewDisplay(holder); zostanie wywołana.

Kiedy utworzysz / otworzysz nową kamerę, FrameLayout nadal ma Twoją poprzednią kamerę, więc jej surfaceCreated zostanie wywołana jako dodatek do nowej kamery.

Należy wyjąć poprzedni Aparat z FrameLayout Po zwolnieniu aparatu (w metodzie onPause()) w następujący sposób:

preview.removeView(mPreview);
Mam nadzieję, że to pomoże.
 40
Author: Dan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-19 11:20:26

Dan ma rację. Zobacz też Tutaj .

Próbka kodu:

public class MainActivity extends Activity {
    private FrameLayout mFlCameraPreview;
    private Camera mCamera;
    private CameraPreview mCameraPreview;

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

        mFlCameraPreview = (FrameLayout) findViewById(R.id.main_fl_camera_preview);
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (mCamera == null) {
            mCamera = getCameraInstance();
        }

        if (mCameraPreview == null) {
            mCameraPreview = new CameraPreview(this, mCamera);
            mFlCameraPreview.addView(mCameraPreview);
        }

    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mCamera != null) {
            mCamera.stopPreview();
            mCamera.release();
            mCamera = null;
        }

        if (mCameraPreview != null) {
            mFlCameraPreview.removeView(mCameraPreview);
            mCameraPreview = null;
        }
    }

    public static Camera getCameraInstance() {
        Camera camera = null;
        try {
            camera = Camera.open();
        } catch (Exception e) {

        }
        return camera;
    }
}  
 4
Author: ishitcno1,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:46:25

EDIT

Nie mogę być w 100% pewien, co powoduje twoje wyjątki. Poniżej umieściłem Mój kod aparatu, mam nadzieję, że pomoże, używam metod startCamera() i stopCamera(), które wywołuję w onPause i onResume. Ja również, tylko utworzyć nową instancję klasy CameraPreview w moim onCreate, nie re-instantiate w onResume chyba że mój cameraView == null. Jest kilka rzeczy, które robimy inaczej. Mam nadzieję, że poniższy kod pomoże, Może można grać z nim, aby uzyskać swój praca:

P. S.: u mnie Wszystko działa. tj. wchodzenie w inne zajęcia itp. Jedyną częścią cyklu życia, której nie testowałem, jest onDestroy, ale to dlatego, że moja aplikacja jest zaprojektowana tak, aby zaczynała się od początku w tym cyklu.

Główna aktywność:

boolean cameraReleased = false;

@Override
protected void onPause() {
    Log.i("onPause", "CALLED:: cameraReleased = " + cameraReleased);
    Log.i("onResume", "CALLED:: cameraView = " + cameraView.toString());
    if (cameraReleased == false) {
        image = null;
        imageResult.setImageBitmap(null);
        imageResult.setImageResource(0);
        cameraView.stopCamera();
        cameraReleased = true;
    }

    if (cameraView == null) {
        Log.i("onPause", "cameraView == null");
        cameraView = new JJCameraSurfaceView(getApplicationContext());
        imageResult = new ImageView(getApplicationContext());
    }
    super.onPause();
}

@Override
protected void onDestroy() {
    Log.e("onDestroy", "INITIATED");
    super.onDestroy();
}

@Override
protected void onResume() {
    Log.i("onResume", "CALLED:: cameraReleased = " + cameraReleased);
    Log.i("onResume", "CALLED:: cameraView = " + cameraView.toString());
    if (cameraReleased == true) {
        image = null;
        imageResult.setImageBitmap(null);
        imageResult.setImageResource(0);
        cameraView.startCamera();
    }

    if (cameraView == null) {
        Log.i("onResume", "cameraView == null");
        cameraView = new JJCameraPreview(getApplicationContext());
        imageResult = new ImageView(getApplicationContext());
    }

    super.onResume();
}

@Override
public void onBackPressed() {
    // If Statement used to get out of my camera view and back to my MainActivity - Same Class
    if (“Camera Preview or Image Result is displayed”) {
        cameraView.stopCamera();
        image = null;
        imageResult.setImageBitmap(null);
        imageResult.setImageResource(0);
        cameraView.startCamera();
        return;
    }

    Log.i("onBackPressed", "WAS PRESSED");
    super.onBackPressed();
}

CameraPreview:

public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    Log.w("surfaceChanged", "STARTED");
    if (camera != null) {
        Log.w("surfaceChanged", "camera = NOT NULL");
        Camera.Parameters cParams = camera.getParameters();
        cParams.setPreviewSize(width, height);
        cParams.setSceneMode(Parameters.SCENE_MODE_NIGHT);
        camera.setParameters(cParams);
        camera.startPreview();
    }
}

public void surfaceCreated(SurfaceHolder holder) {
    Log.w("surfaceCreated", "STARTED");
    if (camera == null) {
        camera = Camera.open(); 
    }
    try {
        camera.setPreviewDisplay(mHolder);
    } catch (Exception e) {
        Log.e("setPreviewDisplay", "FAILED: " + e.getMessage());
    }
}

public void surfaceDestroyed(SurfaceHolder holder) {
    Log.w("CameraSurfaceDestroyed", "INITIATED");
    camera.stopPreview();
    camera.release();
    camera = null;
}

public void startCamera() {
    Log.w("startCamera", "CALLED");
    mHolder = getHolder();
    surfaceCreated(mHolder);
    camera.startPreview();
    mHolder.addCallback(this);
}

public void stopCamera() {
    mHolder = getHolder();
    mHolder.removeCallback(this);
    camera.stopPreview();
}
 1
Author: jnthnjns,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-07 13:25:11

Miałem podobny problem z moim kodem, który był wymuszonym zamknięciem z błędem Method called after release().

Wywoływałem metodę SetupCamera() w OnResume(), która sprawdzała, czy obiekt jest null camera, a następnie wywoływała camera.Open().

Naprawiono mój problem polegający na pozbyciu się null-check i wywołaniu camera.Open() czy to było null, czy nie (już ustawiłem camera = null na onPause) po przeczytaniu Camera Docs.

Wiem, że nie jest to definitywne w śledzeniu mojego problemu, ale to absolutnie zadziałało na ja!

 1
Author: CodeMonkey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-28 04:19:35

Moje rozwiązanie robocze: Pierwszy: W {[3] } class declare mCamera as array:

Camera mCamera[] = new Camera[1];

Po Drugie: deklaracja konstruktora CameraPreview musi wyglądać tak:

public CameraPreview(Context context, Camera[] camera,
                     PreviewCallback previewCb,
                     AutoFocusCallback autoFocusCb) {
      mCamera = camera;
      ...
}

Ale mCamera w CameraPreview klasa musi być zadeklarowana w następujący sposób:

Camera[] mCamera; // without instantiating of the array!

I na koniec: w obu klasach wewnątrz wszystkich metod należy zastąpić wszystkie odwołania mCamera przez mCamera[0]

P. s: Sorry for my English

 1
Author: Yuriy Pelipas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-10 03:21:36

Spróbuj użyć poniższego kodu, zamiast nadpisywania onpause() i onResume(), nadpisuje OnStop() i onRestart(). W cyklu życia aktywności wywoływana jest metoda onStop (), gdy aktywność nie jest widoczna, a następnym wywołaniem metody cyklu życia jest metoda onRestart (). Spójrz na poniższy kod.

@Override
    protected void onStop() {
        super.onStop();
        try {
            m_camera.stopPreview();
            m_camera.release();
            preview.removeView(m_CameraPreview);
/*
m_CameraPreview is the object of the class that looks like this :                                public class CameraSurfaceView extends SurfaceView implements Callback
*/
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
    @Override
    protected void onRestart() {
        super.onRestart();
        m_camera=getCameraInstance();//Initialize the camera in your own way
        m_CameraPreview = new CameraSurfaceView(this, m_camera);
       preview = (FrameLayout)findViewById(R.id.camera_preview);   
        preview.addView(this.m_CameraPreview);
/* 
*camera_preview is the id of the framelayout defined in xml file and preview is *the instance of FrameLayout. 
*/
    }

Jak powiedział Dan, układ ramki będzie miał miejsce w stosunku do poprzedniej instancji kamery, a jego wywołania zwrotne "surfaceview" zostaną utworzone oprócz nowych obiektów tworzących stan rasy. Stąd trzeba by go zwolnić w OnStop () i ponownie uruchomić w onrestart (). Mam nadzieję, że to pomoże.

 0
Author: Pranav,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-21 12:50:38

Miałem ten sam błąd. Poniżej Sekwencja rozwiązuje mój problem.

Call getHolder().removeCallback(this); in surfaceDestroyed()

Call

 private void releaseCameraAndPreview() {

        if (mCamera != null) {
            mCamera.stopPreview();
            mCamera.setPreviewCallback(null);
            mCamera.release();
            mCamera = null;
        }

        if(mPreview != null){
            mPreview.destroyDrawingCache();
            mPreview.mCamera = null;
        }

    }

W onPause

Call

  private boolean safeCameraOpenInView(View view) {
        boolean qOpened = false;
        releaseCameraAndPreview();
        mCamera = getCameraInstance();
        mCameraView = view;
        qOpened = (mCamera != null);

        if(qOpened == true){
            mPreview = new CameraPreview(getActivity().getBaseContext(), mCamera,view);
            preview = (FrameLayout) view.findViewById(R.id.camera_preview);
            preview.addView(mPreview);
            mPreview.startCameraPreview();
        }
        return qOpened;
    }

W onCreateView().

 0
Author: Aman Srii,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-03 06:12:24