カメラアプリの開発中に、他のアプリに切り替えたときにのみ発生する例外が発生しました(アプリのonPause()
)。
_01-15 17:22:15.017: E/AndroidRuntime(14336): FATAL EXCEPTION: main
01-15 17:22:15.017: E/AndroidRuntime(14336): Java.lang.RuntimeException: Method called after release()
01-15 17:22:15.017: E/AndroidRuntime(14336): at Android.hardware.Camera.setPreviewDisplay(Native Method)
01-15 17:22:15.017: E/AndroidRuntime(14336): at Android.hardware.Camera.setPreviewDisplay(Camera.Java:357)
01-15 17:22:15.017: E/AndroidRuntime(14336): at com.sora.cbir.yuki.image.leaf.CameraPreview.surfaceCreated(CameraPreview.Java:32)
01-15 17:22:15.017: E/AndroidRuntime(14336): at Android.view.SurfaceView.updateWindow(SurfaceView.Java:551)
01-15 17:22:15.017: E/AndroidRuntime(14336): at Android.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.Java:213)
01-15 17:22:15.017: E/AndroidRuntime(14336): at Android.view.View.dispatchWindowVisibilityChanged(View.Java:4075)
01-15 17:22:15.017: E/AndroidRuntime(14336): at Android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.Java:742)
01-15 17:22:15.017: E/AndroidRuntime(14336): at Android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.Java:742)
01-15 17:22:15.017: E/AndroidRuntime(14336): at Android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.Java:742)
01-15 17:22:15.017: E/AndroidRuntime(14336): at Android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.Java:742)
01-15 17:22:15.017: E/AndroidRuntime(14336): at Android.view.ViewRoot.performTraversals(ViewRoot.Java:858)
01-15 17:22:15.017: E/AndroidRuntime(14336): at Android.view.ViewRoot.handleMessage(ViewRoot.Java:1995)
01-15 17:22:15.017: E/AndroidRuntime(14336): at Android.os.Handler.dispatchMessage(Handler.Java:99)
01-15 17:22:15.017: E/AndroidRuntime(14336): at Android.os.Looper.loop(Looper.Java:150)
01-15 17:22:15.017: E/AndroidRuntime(14336): at Android.app.ActivityThread.main(ActivityThread.Java:4389)
01-15 17:22:15.017: E/AndroidRuntime(14336): at Java.lang.reflect.Method.invokeNative(Native Method)
01-15 17:22:15.017: E/AndroidRuntime(14336): at Java.lang.reflect.Method.invoke(Method.Java:507)
01-15 17:22:15.017: E/AndroidRuntime(14336): at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:849)
01-15 17:22:15.017: E/AndroidRuntime(14336): at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:607)
01-15 17:22:15.017: E/AndroidRuntime(14336): at dalvik.system.NativeStart.main(Native Method)
_
私はいくつかの研究を行い、追加する必要があることがわかりました
_mCamera.setPreviewCallback(null);
_
androidのカメラスタックの回避策として
onPause()
は次のようになります。
_@Override
protected void onPause() {
super.onPause();
try
{
// release the camera immediately on pause event
//releaseCamera();
mCamera.stopPreview();
mCamera.setPreviewCallback(null);
mCamera.release();
mCamera = null;
}
catch(Exception e)
{
e.printStackTrace();
}
}
_
そして私のonResume()
:
_@Override
protected void onResume()
{
super.onResume();
try
{
mCamera.setPreviewCallback(null);
mCamera = getCameraInstance();
//mCamera.setPreviewCallback(null);
mPreview = new CameraPreview(Imageupload.this, mCamera);//set preview
preview.addView(mPreview);
} catch (Exception e){
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
}
_
そして最後に私のgetCameraInstance()
メソッド:
_public Camera getCameraInstance(){
Camera camera = null;
try {
camera = Camera.open(); // attempt to get a Camera instance
}
catch (Exception e){
// Camera is not available (in use or does not exist)
}
Camera.Parameters parameters = camera.getParameters();
//mPreviewSize = getBestPreviewSize(parameters, wt, ht);
//mPictureSize = getBestPictureSize(parameters, wt, ht);
//Shift W & H => if camera rotates 90 deg
mPreviewSize = getOptimalPreviewSize(parameters, wt, ht); //original => wt,ht
mPictureSize = getOptimalPictureSize(parameters, wt, ht); //original => wt,ht
Log.d("CAMERA", "SCREEN RESOLUTION H: "+ht);
Log.d("CAMERA", "SCREEN RESOLUTION W: "+wt);
Log.d("CAMERA", "PREVIEW RESOLUTION H: "+mPreviewSize.height);
Log.d("CAMERA", "PREVIEW RESOLUTION W: "+mPreviewSize.width);
Log.d("CAMERA", "PICTURE RESOLUTION H: "+mPictureSize.height);
Log.d("CAMERA", "PICTURE RESOLUTION W: "+mPictureSize.width);
//set preview size based on device screen
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
//set picture size based on device screen
parameters.setPictureSize(mPictureSize.width, mPictureSize.height);
//set output camera mode
parameters.setPictureFormat(PixelFormat.JPEG);
//set focous mode
parameters.setFocusMode(FOCUS_MODE_AUTO);
//set flash mode
parameters.setFlashMode("auto");
List<int[]> fps = parameters.getSupportedPreviewFpsRange();
//System.out.println("FPS size: " +fps.size());
//System.out.println("MAX FPS:"+(fps.get(fps.size()-1)[1])/1000);
//log min and max camera supported fps
Log.d("CAMERA", "CAMERA MAX FPS: "+(fps.get(fps.size()-1)[1])/1000);
Log.d("CAMERA", "CAMERA MIN FPS: "+(fps.get(fps.size()-1)[0])/1000);
if(camera_fps)
{
parameters.setPreviewFpsRange(fps.get(fps.size()-1)[1], fps.get(fps.size()-1)[1]);
}
//set camera parameters
camera.setParameters(parameters);
Toast.makeText(getApplicationContext(), "Your device are capable of previewing @" + fps.get(fps.size()-1)[1]/1000+"fps!",Toast.LENGTH_SHORT).show();
return camera; // returns null if camera is unavailable
}
_
これを修正する方法についてのアイデアはありますか?
私は同じ問題を抱えています。 mCamera.setPreviewCallback(null);
は役に立ちませんでした。私の活動では、これをreleaseCamera
に追加しました:
mPreview.getHolder().removeCallback(mPreview);
そして、それは今動作します。
@ ookami.kbソリューションも私のために機能し、@ srunniもコメントしました。
public void onPause() {
super.onPause();
if (mCamera != null) {
mCamera.setPreviewCallback(null);
mPreview.getHolder().removeCallback(mPreview);
mCamera.release();
}
}
OnDestroyメソッドも削除しました。
ドキュメントでは、 camera.release()
はすべてのカメラリソースを解放することを明確に述べています。この呼び出しの後、カメラ参照は使用できなくなります。
カメラを再度使用する場合は、open(int)
メソッドを使用してカメラを取得する必要があります。
それはすべて camera docs で説明されています。
正しく再開するには、これを行う必要があります。
@Override
public void onResume() {
super.onResume();
// Get the Camera instance as the activity achieves full user focus
if (mCamera == null) {
initializeCamera(); // Local method to handle camera initialization
}
}
protected void initializeCamera(){
// Get an instance of Camera Object
mCamera = getCameraInstance();
// create a basic camera preview class that can be included in a View layout.
mPreview=new CameraPreview(this,mCamera);
//add your preview class to the FrameLayout element.
preview.addView(mPreview);
//Trigger capturing an image by calling the Camera.takePicture() method.
captureButton.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
// get an image from the camera
mCamera.takePicture(null, null, mPicture);
}
}
);
}
また、oncreate()でFrameLayoutプレビューとButton captureButtonを定義する以外に何もしないことを思い出してください。
@Override public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
this.getHolder().removeCallback(this);
mCamera.stopPreview();
mCamera.release();
mCamera = null;
Log.e("surfaceDestroyed", "surfaceDestroyed");
}
そして、再開機能でカメラを再初期化します。
私は置きました
mPreview.getHolder().removeCallback(mPreview);
の間に。
mCamera.setPreviewCallback(null);
そして
mCamera.release();
そしてそれは私のために働いた。
@Override
protected void onPause() {
super.onPause();
this.saveTextEdits();
try {
mCamera.stopPreview();
mCamera.setPreviewCallback(null);
**mPreview.getHolder().removeCallback(mPreview);**
mCamera.release();
mCamera = null;
}catch (Exception e){
}
}
オカンビの答えに追加。
これは、再開時にすべてを台無しにする機能です。
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}
Try {}は、スローされている例外をキャッチしていません。つまり、そのmCameraは存在せず、setPreviewDisplay(holder)を呼び出そうとするとクラッシュします。
したがって、コールバックを削除することにより、このsurfaceCreatedは呼び出されず、クラッシュを回避します。
これは、Googleによって非常に不十分に文書化されています。
あなたが得た場合:
Nullオブジェクト参照で仮想メソッド「void Android.hardware.Camera.setPreviewCallback(Android.hardware.Camera $ PreviewCallback)」を呼び出そうとしました
私は@ ookami.kbに同意します-mCamera.setPreviewCallback(null);
は十分ではありません。その後ろにこれも追加します:
mCameraView.getHolder().removeCallback(mCameraView);
私は同じ問題に直面しました-mCamera = null; in surfaceDestroyed(SurfaceHolder holder)Previewクラスの追加.
public void surfaceDestroyed(SurfaceHolder holder) {
// Surface will be destroyed when we return, so stop the preview.
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}
および-追加
camera = Camera.open();
camera.startPreview();
params = camera.getParameters();
preview.setCamera(camera);
in OnResume()私のCameraActivityのメソッド。