【问题标题】:java.lang.RuntimeException: takePicture failedjava.lang.RuntimeException: 拍照失败
【发布时间】:2014-02-12 09:22:24
【问题描述】:

当我连续单击捕获按钮(没有任何中断)时,出现运行时异常 我该如何解决这个问题?

如果不可能,我该如何处理这个异常?

btnCapture = (ImageButton) findViewById(R.id.btnCapture);
                final MediaPlayer mp = MediaPlayer.create(CameraLauncherActivity.this, R.raw.button);
                btnCapture.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {

                            // line where getting RuntimeException
                        camera.takePicture(null, null, mPicture);   

                    }
                });

日志:

02-12 14:48:41.580: E/AndroidRuntime(6997): FATAL EXCEPTION: main
02-12 14:48:41.580: E/AndroidRuntime(6997): java.lang.RuntimeException: takePicture failed
02-12 14:48:41.580: E/AndroidRuntime(6997):     at android.hardware.Camera.native_takePicture(Native Method)
02-12 14:48:41.580: E/AndroidRuntime(6997):     at android.hardware.Camera.takePicture(Camera.java:1126)
02-12 14:48:41.580: E/AndroidRuntime(6997):     at android.hardware.Camera.takePicture(Camera.java:1071)
02-12 14:48:41.580: E/AndroidRuntime(6997):     at app.cam.shane.CameraLauncherActivity$3.onClick(CameraLauncherActivity.java:116)
02-12 14:48:41.580: E/AndroidRuntime(6997):     at android.view.View.performClick(View.java:4223)
02-12 14:48:41.580: E/AndroidRuntime(6997):     at android.view.View$PerformClick.run(View.java:17275)
02-12 14:48:41.580: E/AndroidRuntime(6997):     at android.os.Handler.handleCallback(Handler.java:615)
02-12 14:48:41.580: E/AndroidRuntime(6997):     at android.os.Handler.dispatchMessage(Handler.java:92)
02-12 14:48:41.580: E/AndroidRuntime(6997):     at android.os.Looper.loop(Looper.java:137)
02-12 14:48:41.580: E/AndroidRuntime(6997):     at android.app.ActivityThread.main(ActivityThread.java:4921)
02-12 14:48:41.580: E/AndroidRuntime(6997):     at java.lang.reflect.Method.invokeNative(Native Method)
02-12 14:48:41.580: E/AndroidRuntime(6997):     at java.lang.reflect.Method.invoke(Method.java:511)
02-12 14:48:41.580: E/AndroidRuntime(6997):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1036)
02-12 14:48:41.580: E/AndroidRuntime(6997):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:803)
02-12 14:48:41.580: E/AndroidRuntime(6997):     at dalvik.system.NativeStart.main(Native Method)

注意:- 就像 Pudding Camera 一样,它们允许用户连续点击 Capture 按钮,但它们永远不会显示异常,如果你点击 50 次它会捕获 10 个或更多图像,每个图像在特定时间后但不显示异常,就像我进入我的代码一样,我该如何处理这个异常?

完整代码:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_camera);

    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

            preview=(SurfaceView)findViewById(R.id.surface);     
            previewHolder=preview.getHolder();    
            previewHolder.addCallback(surfaceCallback);    
            previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

            btnCapture = (ImageButton) findViewById(R.id.btnCapture);
            final MediaPlayer mp = MediaPlayer.create(CameraLauncherActivity.this, R.raw.button);
            btnCapture.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    mp.start();
                    camera.takePicture(null, null, mPicture);                 
                }
            });


    @Override
    public void onResume() {  
        super.onResume();   
        camera=Camera.open(); 
    }  

    @Override   
    public void onPause() {  
        super.onPause();  
        if (inPreview) {  
        camera.stopPreview();   
        }   
        camera.release();   
        camera=null;   
        inPreview=false;         
    }   


    private Camera.Size getBestPreviewSize(int width, int height,
            Camera.Parameters parameters) {
            Camera.Size result=null;

            for (Camera.Size size : parameters.getSupportedPreviewSizes()) {
                if (size.width <= width && size.height <= height) {
                    if (result == null) {
                        result=size;
                    }
                    else {
                        int resultArea=result.width * result.height;
                        int newArea=size.width * size.height;

                        if (newArea > resultArea) {
                            result=size;
                        }
                    }
                }
            }

            return(result);
        }

    private Camera.Size getSmallestPictureSize(Camera.Parameters parameters) {
        Camera.Size result=null;

        for (Camera.Size size : parameters.getSupportedPictureSizes()) {
            if (result == null) {
                result=size;
            }
            else {
                int resultArea=result.width * result.height;
                int newArea=size.width * size.height;

                if (newArea < resultArea) {
                    result=size;
                }
            }
        }

        return(result);
    }


    SurfaceHolder.Callback surfaceCallback=new SurfaceHolder.Callback(){

    public void surfaceCreated(SurfaceHolder holder) {     
        try {        
            camera.setPreviewDisplay(previewHolder); 
            }   catch (Throwable t) {   
                Log.e("PreviewDemo-surfaceCallback",
                        "Exception in setPreviewDisplay()", t);
                Toast.makeText(CameraLauncherActivity.this, t.getMessage(), Toast.LENGTH_LONG).show();       
                }     
            }      

    public void surfaceChanged(SurfaceHolder holder,int format, int width,int height) {
        params = camera.getParameters();       
        params.setFlashMode(Camera.Parameters.FLASH_MODE_ON);
        Camera.Size size = getBestPreviewSize(width, height, params);  
        Camera.Size pictureSize=getSmallestPictureSize(params);
        if (size != null && pictureSize != null) {      
            params.setPreviewSize(size.width, size.height);
            params.setPictureSize(pictureSize.width,
                    pictureSize.height);
            camera.setParameters(params);       
            camera.startPreview();       
            inPreview=true;                 

            }     
        }      

    public void surfaceDestroyed(SurfaceHolder holder) {

        }   
    };       

    PictureCallback mPicture = new PictureCallback() {
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            pictureFile = getOutputMediaFile();
            camera.startPreview();
            if (pictureFile == null) {
                return;
            }
            try {
                FileOutputStream fos = new FileOutputStream(pictureFile);
                fos.write(data);
                fos.close();
            } catch (FileNotFoundException e) {

            } catch (IOException e) {
            }
        }
    };

    static File getOutputMediaFile() {

        /* yyyy-MM-dd'T'HH:mm:ss.SSSZ */
        timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
        .format(new Date());

        // file name
        mediaFile = new File(LoginActivity.mediaStorageDir.getPath() + File.separator
                + "IMG_" + timeStamp + ".jpg");

        return mediaFile;

    }


}

【问题讨论】:

  • 您是否在清单中添加了所需的权限?
  • 一切正常,只想控制连续点击并控制异常
  • 你必须在takePicture()之后打电话给startPreview()
  • 1.请在您的问题中添加 onPictureTaken() 代码。 2. onTouchEvent() 什么时候使用? 3.你想只按按钮拍照吗? 4. 按一次按钮会出现RuntimeException吗?
  • @Melquiades 你好兄弟,我发布了完整的代码,请立即检查,多次按下时会出现 RuntimeException 没有任何中断,否则工作正常

标签: java android android-camera runtimeexception


【解决方案1】:

首先,在 onPictureTaken 中捕获您的异常,留下空的捕获部分不是一个好习惯。然后,我将添加一个标志,以防止在保存上一张图片时调用 takePicture()。稍后在您的按钮 onClick 中,您将检查是否可以调用 takePicture()。

  1. 将标志声明为 Activity 的成员:

    private boolean safeToTakePicture = false;
    
  2. surfaceChanged()中,只需在调用startPreview()后设置flag为true即可:

    camera.startPreview();
    safeToTakePicture = true;
    
  3. 在您的onClick() 监听器中检查标志并拍照(如果可以的话):

    if (safeToTakePicture) {
        mp.start();
        camera.takePicture(null, null, mPicture); 
        safeToTakePicture = false;
    }
    
  4. onPictureTaken()中,图片保存后再次设置flag为true(并添加异常打印):

    PictureCallback mPicture = new PictureCallback() {
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            pictureFile = getOutputMediaFile();
            camera.startPreview();
    
            if (pictureFile == null) {
                //no path to picture, return
                safeToTakePicture = true;
                return;
            }
            try {
                FileOutputStream fos = new FileOutputStream(pictureFile);
                fos.write(data);
                fos.close();
    
            } catch (FileNotFoundException e) {
                e.printStackTrace();              //<-------- show exception
            } catch (IOException e) {
                e.printStackTrace();              //<-------- show exception
            }
    
            //finished saving picture 
            safeToTakePicture = true;
        }
    };
    

注意事项: 正如文档所说,“必须先开始预览,然后才能拍照。”,因此可能的增强功能是使用 setPreviewCallback() 注册回调,当预览数据可用时将调用该回调,并且调用 onPreviewFrame 时将标志设置为 true。

【讨论】:

  • 这样一个惊人的解决方案 :) 你真是个天才.. 很好的解释,还有一个小问题,如果我也想使用相机的默认按钮来捕捉图像,比如在布丁相机中
  • 为什么我的实现方法没有调用它开始? :(surfaceChanged()
  • @Melquiades 此代码在 Thread 中不起作用,我遇到异常 pastie.org/9583142 它的第一张图片很好,但在第一张图片之后它就崩溃了
  • @ErumHannan,你能用你的代码在 SO 上发布一个新问题,并通知我,我会看看。
  • @SoftDev MediaPlayer - 见原始问题
【解决方案2】:

我也有类似的问题。后来发现startPreview很重要。

_camera.startPreview()是很重要的拍前checkout第5点和第6点 in this link.

【讨论】:

  • 在 takePicture(..) 之前 onTouchEvent(,..) 或捕获按钮?
  • @Sun 是的,您需要在保存工作完成后调用 camera.startPreview()(例如在 onPictureTaken() 中),否则相机将不允许您拍​​摄另一张图像跨度>
【解决方案3】:

在我的情况下,这可能有很多原因,我试图在没有预览的情况下拍照(隐藏照片)并且我使用的是SurfaceView,所以我将其替换为SurfaceTexture

SurfaceTexture surfaceTexture = new SurfaceTexture(10);
camera.setPreviewTexture(surfaceTexture);

问题解决了…… P.S 我只在 6.0 以上的设备上收到此错误

【讨论】:

    【解决方案4】:

    您是否忘记在相机上拨打startPreview()

    更多信息请参见here

    【讨论】:

      【解决方案5】:

      此方法将帮助您尝试解决问题。

      private void safeCameraOpen(int id) {
      
              try {
                  releaseCameraAndPreview();
                  mCamera = Camera.open(id);
              } catch (Exception e) {
                  Log.e(getString(R.string.app_name), "failed to open Camera");
                  e.printStackTrace();
              }
      
          }
      
      private void releaseCameraAndPreview() {
              if (mCamera != null) {
                  mCamera.release();
                  mCamera = null;
              }
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-01-23
        • 2014-09-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-23
        • 1970-01-01
        相关资源
        最近更新 更多