Intereting Posts
Могу ли я заставить пользователя согласиться с юридической оговоркой перед установкой приложения для Android? Как установить элемент представления сетки как выбранный FFMPEG с поддержкой аппаратного кодека Какое мобильное кросс-платформенное решение на основе Ruby? Задача планирования в Кордове Как создать плагин в phonegap для запуска приложения в фоновом режиме? Android.util.Log при публикации – что я могу сделать / не делать Как я могу поместить ListView в ScrollView без его свертывания? Сериализовать POJO для JSON с помощью GSON Не должны ли ссылки на строку ссылаться на имена действий фильтра намерений в AndroidManifest? Toggle GPS Programmatically Android 4.4 C # Web – localhost: порт работает, 127.0.0.1:port не работает Внедрить onClick только для составного компонента TextView. Можно ли использовать так много устаревших методов в обратном коде? FileProvider выбрасывает исключение на GetUriForFile

Метод, вызванный после выпуска

У меня есть один класс активности (CameraActivity), который использует мой класс CameraPreview. В «OnResume» запускаются камера и предварительный просмотр. В «OnPause» я выпускаю ресурсы камеры. Когда приложение запускается, все работает нормально внутри «OnResume», но когда я запускаю другое действие с помощью намерения (например, открытый URL-адрес в браузере), а затем возвращаюсь к своей активности, тогда исключение происходит внутри класса OnResume, входящего в CamerPreview. Ниже приведен код:

// Класс CameraActivity

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; } 

// Следующий класс 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()); } } } 

Это от 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) 

РЕДАКТИРОВАТЬ

Я обновил «surfaceDestroyed» и поместил журналы, как было предложено, но теперь я получаю исключение в «onPause» -> onSurfaceDestroyed. Первоначально onPause выполнял штраф.

1- Экземпляр камеры создается в «onResume» класса активности с помощью метода «getCameraInstance» и передает экземпляр mCamera в класс CameraPreview. Я попытался изменить его так, чтобы экземпляр камеры был создан только на стороне «onSurfaceCreated» и присваивал экземпляр mCamera классу активности, но он не работал. Я также заметил через отладку, что элемент previewCallBack класса CameraPreview действителен в первый раз, но второй раз член «previewCallBack» класса CameraPreview имеет значение NULL.

Обратите внимание, что в первый раз, когда вызывается «onResume», все работает нормально, но когда он запускается во второй раз после onPause, тогда исключение происходит изначально, хотя код одинаковый в 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) 

Solutions Collecting From Web of "Метод, вызванный после выпуска"

Когда вы добавили камеру в FrameLayout, вот так:

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

Будет surfaceCreated метод surfaceCreated , и поэтому mCamera.setPreviewDisplay(holder); Будет вызываться.

Когда вы создаете / открываете новую камеру, у FrameLayout все еще есть ваша предыдущая камера, и поэтому ее surfaceCreated будет вызвана в дополнение к вашей новой камере.

Что вы должны сделать, это удалить предыдущую камеру из FrameLayout когда вы отпустите камеру (по onPause() ) следующим образом:

 preview.removeView(mPreview); 

Надеюсь, поможет.

Дэн прав. Также см. Здесь .

Образец кода:

 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; } } 

РЕДАКТИРОВАТЬ

На это сложно ответить, я не могу быть на 100% уверен, что сейчас вызывает ваши исключения. Я включил свой код камеры ниже, надеюсь, что это поможет, я использую startCamera() и stopCamera() которые я вызываю в onPause и onResume . Я также создаю новый экземпляр класса CameraPreview в моем onCreate , я не повторно onResume экземпляр в onResume если мой cameraView == null . Есть пара вещей, которые мы делаем по-другому. Надеюсь, код ниже поможет, может быть, вы сможете поиграть с ним, чтобы заставить вас работать:

PS: Все работает для меня. Т.е. переход в другие действия и т. Д. Единственная часть жизненного цикла, который я не тестировал, – onDestroy , но это потому, что мое приложение предназначено для начала в начале этого цикла.

Основная деятельность:

 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(); } 

У меня была аналогичная проблема с моим кодом, который был принудительным закрытием с Method called after release() ошибки Method called after release() .

Я SetupCamera() метод SetupCamera() в OnResume() который проверял нулевой объект camera а затем вызывал camera.Open() .

Я исправил свою проблему, чтобы избавиться от нулевой проверки и просто вызвать camera.Open() ли это null или нет (я уже установил camera = null on onPause ) после прочтения Документов камеры .

Я знаю, что это не является окончательным в определении моей проблемы, но это абсолютно сработало для меня!

Мое рабочее решение: во-первых: класс mCamera объявляет mCamera как массив:

 Camera mCamera[] = new Camera[1]; 

Во-вторых: объявление конструктора CameraPreview должно выглядеть так:

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

Но mCamera в CameraPreview должен быть объявлен следующим образом:

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

И, наконец: в обоих классах внутри всех методов вы должны заменить все ссылки mCamera на mCamera[0]

PS: Извините за мой английский

Попробуйте использовать код ниже, вместо того, чтобы переопределять onPause () и onResume (), переопределить onStop () и onRestart (). В жизненном цикле активности вызывается onStop (), когда активность не видима, а следующий вызов метода жизненного цикла будет в onRestart (). Посмотрите на код ниже.

 @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. */ } 

Как сказал Дэн, рамочная компоновка будет удерживаться в предыдущем экземпляре камеры, и его обратные обратные вызовы будут созданы в дополнение к новым объектам, создающим условие гонки. Следовательно, вам нужно будет выпустить его в onStop () и повторно инициализировать в onRestart (). Надеюсь это поможет.

У меня была такая же ошибка. Ниже последовательность решает мою проблему.

Вызовите getHolder().removeCallback(this); surfaceDestroyed()

Вызов

  private void releaseCameraAndPreview() { if (mCamera != null) { mCamera.stopPreview(); mCamera.setPreviewCallback(null); mCamera.release(); mCamera = null; } if(mPreview != null){ mPreview.destroyDrawingCache(); mPreview.mCamera = null; } } 

onPause

Вызов

  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; } 

В onCreateView() .