2014-02-09 48 views
9

我在我的Android应用程序的背景中拍照。但它给出了一个错误:Java.lang.Runtime异常:拍照失败?

02-09 15:22:12.061: E/cheeta(28633): timer testing 
02-09 15:22:13.546: W/System.err(28633): java.lang.RuntimeException: takePicture failed 
02-09 15:22:13.546: W/System.err(28633): at android.hardware.Camera.native_takePicture(Native Method) 
02-09 15:22:13.546: W/System.err(28633): at android.hardware.Camera.takePicture(Camera.java:1194) 
02-09 15:22:13.551: W/System.err(28633): at cam.sharp.MainActivity$MyTimerTask.run(MainActivity.java:69) 
02-09 15:22:13.551: W/System.err(28633): at java.util.Timer$TimerImpl.run(Timer.java:284) 
02-09 15:22:13.551: E/cheeta(28633): timer testing 
02-09 15:22:15.051: W/System.err(28633): java.lang.RuntimeException: takePicture failed 
02-09 15:22:15.051: W/System.err(28633): at android.hardware.Camera.native_takePicture(Native Method) 
02-09 15:22:15.051: W/System.err(28633): at android.hardware.Camera.takePicture(Camera.java:1194) 
02-09 15:22:15.051: W/System.err(28633): at cam.sharp.MainActivity$MyTimerTask.run(MainActivity.java:69) 
02-09 15:22:15.051: W/System.err(28633): at java.util.Timer$TimerImpl.run(Timer.java:284) 
02-09 15:22:15.051: E/cheeta(28633): timer testing 
02-09 15:22:16.551: W/System.err(28633): java.lang.RuntimeException: takePicture failed 
02-09 15:22:16.556: W/System.err(28633): at android.hardware.Camera.native_takePicture(Native Method) 
02-09 15:22:16.556: W/System.err(28633): at android.hardware.Camera.takePicture(Camera.java:1194) 
02-09 15:22:16.561: W/System.err(28633): at cam.sharp.MainActivity$MyTimerTask.run(MainActivity.java:69) 
02-09 15:22:16.561: W/System.err(28633): at java.util.Timer$TimerImpl.run(Timer.java:284) 
02-09 15:22:16.561: E/cheeta(28633): timer testing 

我有两个文件。

MainActivity.java和CameraPreview.java

这里是两个代码。

MainActivity.java

package cam.sharp; 

import java.io.File; 
import java.io.FileOutputStream; 
import java.util.Timer; 
import java.util.TimerTask; 

import android.app.Activity; 
import android.content.Context; 
import android.hardware.Camera; 
import android.os.Build; 
import android.os.Bundle; 
import android.util.Log; 
import android.widget.FrameLayout; 
import android.widget.Toast; 

public class MainActivity extends Activity { 

    private int cameraId = 0; 
    private Camera mCamera; 
    private CameraPreview mPreview; 
    String fileName = "tempImage.jpeg"; 
    File file; 

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

     // Create an instance of Camera 
     mCamera = getCameraInstance(cameraId); 

     if (mCamera == null) { 
      Toast.makeText(
        getApplicationContext(), 
        "The camera service is currently unavailable, please try again!", 
        Toast.LENGTH_LONG).show(); 
      finish(); 
     } else { 
      // Create our Preview view and set it as the content of our 
      // activity. 
      mPreview = new CameraPreview(this, mCamera); 
      FrameLayout frameLayout = (FrameLayout) findViewById(R.id.camera_preview); 
      frameLayout.addView(mPreview); 

     } 

     // start thread for these 

     MyTimerTask myTask = new MyTimerTask(); 
     Timer myTimer = new Timer(); 
     // public void schedule (TimerTask task, long delay, long period) 
     // Schedule a task for repeated fixed-delay execution after a specific 
     // delay. 
     // 
     // Parameters 
     // task the task to schedule. 
     // delay amount of time in milliseconds before first execution. 
     // period amount of time in milliseconds between subsequent executions. 

     myTimer.schedule(myTask, 3000, 1500); 

    } 

    class MyTimerTask extends TimerTask { 
     public void run() { 

      try { 
       mCamera.takePicture(null, null, null, mPictureCallback); 
       file = new File(getFilesDir(), fileName); 

      } catch (Exception e) { 
       e.printStackTrace(); 
      } 

      Log.e("cheeta", "timer testing"); 

     } 
    } 

    Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() { 
     public void onPictureTaken(byte[] imageData, Camera c) { 
      Log.e("Callback TAG", "Here in jpeg Callback"); 

      if (imageData != null) { 
       FileOutputStream outputStream; 
       try { 
        outputStream = openFileOutput(fileName, 
          Context.MODE_PRIVATE); 
        outputStream.write(imageData); 
        outputStream.close(); 

        // Intent intent = new Intent(SnapScreen.this, 
        // PreviewScreen.class); 
        // if (fromMessageReview == true) { 
        // intent.putExtra("fromMessageReview", "true"); 
        // } 
        // startActivity(intent); 
        // overridePendingTransition(R.anim.slide_in, 
        // R.anim.slide_out); 

        finish(); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 

      } 
     } 
    }; 

    @Override 
    protected void onDestroy() { 
     super.onDestroy(); 
     releaseCamera(); 
    } 

    /** A safe way to get an instance of the Camera object. */ 
    public static Camera getCameraInstance(int cameraId) { 
     Camera c = null; 
     try { 
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { 
       c = Camera.open(cameraId); 
      } else { 
       c = Camera.open(); 
      } 
     } catch (Exception e) { 
      c = null; 
     } 
     return c; // returns null if camera is unavailable 
    } 

    private void releaseCamera() { 
     if (mCamera != null) { 
      mCamera.release(); // release the camera for other applications 
      mCamera = null; 
     } 
    } 

} 

CameraPreview.java

package cam.sharp; 

import java.io.IOException; 

import android.annotation.SuppressLint; 
import android.content.Context; 
import android.hardware.Camera; 
import android.util.Log; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 

/** A basic Camera preview class */ 
@SuppressLint("ViewConstructor") 
public class CameraPreview extends SurfaceView implements 
SurfaceHolder.Callback { 
    private static final String TAG = "Camera Preview"; 
    private SurfaceHolder mHolder; 
    public Camera mCamera; 

    @SuppressWarnings("deprecation") 
    @SuppressLint("NewApi") 
    public CameraPreview(Context context, Camera camera) { 
     super(context); 
     mCamera = camera; 
     mCamera.setDisplayOrientation(90); 

     // 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); 
       mCamera.setDisplayOrientation(90); 
       mCamera.startPreview(); 

     } catch (IOException e) { 
      Log.d(TAG, "Error setting camera preview: " + e.getMessage()); 
     } 
    } 

    public void surfaceDestroyed(SurfaceHolder holder) { 
     // empty. Take care of releasing the Camera preview in your activity. 
    } 

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

     // set preview size and make any resize, rotate or 
     // reformatting changes here 

     // start preview with new settings 
     try { 
      mCamera.setPreviewDisplay(mHolder); 
      mCamera.startPreview(); 
     } catch (Exception e) { 
      Log.d(TAG, "Error starting camera preview: " + e.getMessage()); 
     } 
    } 
} 

有人能看到什么问题?我打电话给mCamera.startPreview();但仍然没有用。

感谢

+1

你添加的权限,以清单文件? – pedromss

+0

是的,我向Manifest文件添加权限。但有时会出现错误。 –

+0

它是否工作代码?我也得到同样的错误@AndroidCheeta – Erum

回答

6

你在你的代码2个问题:

第一:在你onPictureTaken回拨您呼叫在该活动应该被销毁转向信号,并调用finish()方法,至极onDestroy()方法,依次释放相机。然而你的MainActivity.java没有被销毁(不知道为什么,但是通过logCat,我发现onCreate()只被调用一次,所以我认为这个活动并没有被销毁。一个可能的解释可能是定时器是由一个不同的线程,因此可能不知道MainActivity已被销毁,但我无法确认),因此myTimer将继续运行,当它到达mCamera.takePicture(null, null, null, mPictureCallback);时,它将抛出NullPointException,因为相机已经发布,并且MainActivity.onCreate()未被再次调用以获得mCamera的新实例。

因此,要解决的第一个问题:

Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() { 
    public void onPictureTaken(byte[] imageData, Camera c) { 
     Log.e("Callback TAG", "Here in jpeg Callback"); 

     if (imageData != null) { 
      FileOutputStream outputStream = null; 
      try { 
       outputStream = openFileOutput(fileName, Context.MODE_PRIVATE); 
       outputStream.write(imageData); 
       // Removed the finish call you had here 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } finally { 
       if (outputStream != null) try { 
        outputStream.close(); 
       } catch (IOException ex) { 
        // TODO Auto-generated catch block 
        ex.printStackTrace(); 
       } 
      } 

     } 
    } 
}; 

二:是你打电话给你的startPreview()方法。 Accooding到takePicture()文档:

This method is only valid when preview is active (after startPreview()). Preview will be stopped after the image is taken; callers must call startPreview() again if they want to re-start preview or take more pictures. This should not be called between start() and stop().

你只叫startPreview()一次,当你创建的摄像头,并且因为问题1,在MainActivity的onCreate()才会被调用一次。既然你有一个计时器拍照每1.5秒,你应该在调用takePicture()之前调用startPreview(),所以要解决这个问题:

class MyTimerTask extends TimerTask { 
    public void run() { 

     try { 
      // Call startPreview before taking a picture 
      mCamera.startPreview(); 
      mCamera.takePicture(null, null, null, mPictureCallback); 
      file = new File(getFilesDir(), fileName); 
     } catch (NullPointerException ne) { 
      ne.printStackTrace(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

     Log.e("cheeta", "timer testing"); 

    } 
} 

在此之后,应用程序continuasly拍摄照片,并将它们存储。我从来没有使用过这样的定时器,所以我不知道如何让它停止。如果你只想要一个少数的照片每次调用内带到CameraPreview Activity我建议你使用一个计时器的动作侦听器,像这样:

Timer tm = new Timer(1000, new ActionListener() { 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      // Take x pictures 
      tm.stop(); 
     } 
    }); 
+0

现在我没有设备,因为我会测试,如果它的工作,我一定会接受你的答案。谢谢 –

+0

它是否工作代码?我也得到同样的错误 – Erum