Исключение Java.lang.Runtime: Сбой при съемке?

Я фотографирую в фоновом режиме в своем приложении для Android. Однако это дает ошибку:

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 (); Но все равно бесполезно.

благодаря

У вас есть 2 проблемы в вашем коде:

Во-первых: в вашем onPictureTaken вызове 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() . В соответствии с документацией takePicture() :

Этот метод действителен только в том случае, если предварительный просмотр активен (после startPreview ()). Предварительный просмотр будет остановлен после того, как изображение будет снято; Вызывающие абоненты должны снова вызвать startPreview (), если они хотят повторно запустить предварительный просмотр или сделать больше снимков. Это не должно вызываться между start () и stop ().

Вы только startPreview() один раз, когда вы создаете камеру, и из-за проблемы 1, onCreate() на MainActivity вызывается только один раз. Поскольку у вас есть таймер, снимающий каждые 1,5 секунды, вы должны вызвать startPreview() перед вызовом takePicture() , чтобы решить эту проблему:

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

После этого приложение непрерывно фотографирует и сохраняет их. Я никогда не использовал Таймер, поэтому я не уверен, как остановить его. Если вы хотите только небольшое количество снимков, сделанных в каждом вызове CameraPreview Activity я предлагаю использовать таймер с прослушивателем действий, например:

 Timer tm = new Timer(1000, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // Take x pictures tm.stop(); } });