Sun*_*Sun 42 java android runtimeexception android-camera
当我连续点击"捕获"按钮(没有任何中断)时,获取运行时异常如何解决此问题?
如果它不可能,那我怎么处理这个例外?
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)
注意: -就像在布丁相机中一样,它们允许用户连续点击捕获按钮,但它们永远不会显示异常,如果你进行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;
    }
}
Mel*_*des 64
首先,在onPictureTaken中捕获您的异常,留下空捕获部分不是一个好习惯.然后,我会添加一个标志,以防止在保存上一张图片时调用takePicture().稍后在你的按钮onClick上你会检查是否可以调用takePicture().
声明一个标志作为您的Activity的成员:
private boolean safeToTakePicture = false;
在surfaceChanged(),调用startPreview()后,只需将标志设置为true:
camera.startPreview();
safeToTakePicture = true;
在你的onClick()监听器中检查标志并拍照,如果可以的话:
if (safeToTakePicture) {
    mp.start();
    camera.takePicture(null, null, mPicture); 
    safeToTakePicture = false;
}
在onPictureTaken(),保存图片后,再次将标志设置为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.
在这种情况下,可能有很多原因,我试图在没有预览的情况下拍照(隐藏照片),并且我正在使用SurfaceView,所以我将其替换为SurfaceTexture
SurfaceTexture surfaceTexture = new SurfaceTexture(10);
camera.setPreviewTexture(surfaceTexture);
问题得以解决... PS我仅在6.0以上的设备上收到此错误
| 归档时间: | 
 | 
| 查看次数: | 41645 次 | 
| 最近记录: |