屏幕关闭时,Android相机不会拍照

时间:2014-08-26 03:22:12

标签: android android-activity android-camera commonsware-cwac

我有一个简单的应用程序,警报管理器定期调用该活动来显示预览框架并在构建预览框架时拍照。拍摄照片后,使用AsyncTask保存并使用finish()销毁活动。 当我打开屏幕时,代码工作得非常好。但是当屏幕关闭时它无法拍照。我想要监视房子并使用应用程序定期拍照,在这种情况下,保持屏幕始终打开或转动它手动不是一个可行的选择。

此外,相机活动的代码已经从 Commonsware 库中复制而来,效果非常好。我只是在关闭屏幕拍照时遇到问题。我也可以从日志中看到活动打开相机。但是,当构建预览框架时应该拍摄的Runnable不会运行,相机会进入暂停状态并停留在那里。

我已经完美地设置了必要的权限,因为我可以在屏幕打开的情况下获取图像。也许我在屏幕关闭时有理解活动生命周期,有人可以在那里照亮。

我尝试使用唤醒锁来打开屏幕,但没有做任何好事。

以下是活动的代码。

此外,我很抱歉,删除许可证的评论,以便在此处缩短。

    package com.thopedia.snapper; /***
 Copyright (c) 2008-2012 CommonsWare, LLC
*/
import all;

public class CameraActivity1 extends Activity {
    private PreviewFrameLayout frame=null;
    private SurfaceView preview=null;
    private SurfaceHolder previewHolder=null;
    private Camera camera=null;
    private boolean inPreview=false;
    private boolean cameraConfigured=false;
    private  PowerManager.WakeLock wakeLock;
    private PowerManager powerManager;

    @SuppressWarnings("deprecation")
    @Override
    public void onCreate(Bundle savedInstanceState) {
       /* powerManager = (PowerManager) getSystemService(POWER_SERVICE);
        wakeLock = powerManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, getClass()
                .getName());*/
        Log.v(GlobalVariables.TAG,"CameraActivity On create called");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        frame=(PreviewFrameLayout)findViewById(R.id.frame);
        preview=(SurfaceView)findViewById(R.id.preview);
        previewHolder=preview.getHolder();
        previewHolder.addCallback(surfaceCallback);
        previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
     }

    @TargetApi(Build.VERSION_CODES.GINGERBREAD)
    @Override
    public void onResume() {
       // wakeLock.acquire();
        Log.v(GlobalVariables.TAG,"camera activity onResume called");
       super.onResume();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
            Camera.CameraInfo info=new Camera.CameraInfo();

            for (int i=0; i < Camera.getNumberOfCameras(); i++) {
                Camera.getCameraInfo(i, info);

                if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
                    try{
                        camera=Camera.open(i);
                    }catch (Exception e){
                        Log.v(GlobalVariables.TAG,"Camera Opening Exception");
                        if(!isFinishing()) {
                            finish();
                        }}}}}
        if (camera == null) {
            try{
                camera=Camera.open();
            }catch (Exception e){
                if(!isFinishing()) {
                    finish();
                }
                Log.v(GlobalVariables.TAG,"Camera opening exception");
            }
        }

        startPreview();
        preview.post(new Runnable() {
            @Override
            public void run() {
                if (inPreview) {
                    camera.takePicture(null, null, photoCallback);
                    inPreview=false;
                }
            }
        });
    }
    @Override
    public void onPause() {
        super.onPause();
        Log.v(GlobalVariables.TAG,"Camera activity onPause called");
        if (inPreview) {
            if(camera!=null) {
                camera.stopPreview();
            }
        }
        if(camera!=null) {
            camera.release();
            camera = null;
        }
        inPreview=false;
    }

    @Override
    protected void onDestroy() {
        Log.v(GlobalVariables.TAG,"Camera activity onDestroy called!");
        super.onDestroy();
        if(camera!=null){
            camera.release();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        new MenuInflater(this).inflate(R.menu.options, menu);
        return(super.onCreateOptionsMenu(menu));
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == R.id.camera) {
            if (inPreview) {
                camera.takePicture(null, null, photoCallback);
                inPreview=false;
            }
        }
        return(super.onOptionsItemSelected(item));
    }

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

    private void initPreview(int width, int height) {
        if (camera != null && previewHolder.getSurface() != null) {
            try {
                camera.setPreviewDisplay(previewHolder);
            }
            catch (Throwable t) {
                Log.e("PreviewDemo-surfaceCallback",
                        "Exception in setPreviewDisplay()", t);
                Toast.makeText(CameraActivity1.this, t.getMessage(),
                        Toast.LENGTH_LONG).show();
            }

            if (!cameraConfigured) {
                Camera.Parameters parameters=camera.getParameters();
                Camera.Size size=getBestPreviewSize(width, height, parameters);
                Camera.Size pictureSize=getSmallestPictureSize(parameters);

                if (size != null && pictureSize != null) {
                    parameters.setPreviewSize(size.width, size.height);
                    parameters.setPictureSize(pictureSize.width,
                            pictureSize.height);
                    parameters.setPictureFormat(ImageFormat.JPEG);
                    frame.setAspectRatio((double)size.width / size.height);
                    camera.setParameters(parameters);
                    cameraConfigured=true;
                }
            }
        }
    }

    private void startPreview() {
        if (cameraConfigured && camera != null) {
            camera.startPreview();
            inPreview=true;
        }
    }

    SurfaceHolder.Callback surfaceCallback=new SurfaceHolder.Callback() {
        public void surfaceCreated(SurfaceHolder holder) {
            // no-op -- wait until surfaceChanged()
        }

        public void surfaceChanged(SurfaceHolder holder, int format,
                                   int width, int height) {
            initPreview(width, height);
            startPreview();
        }

        public void surfaceDestroyed(SurfaceHolder holder) {
            // no-op
        }
    };

    Camera.PictureCallback photoCallback=new Camera.PictureCallback() {
        public void onPictureTaken(byte[] data, Camera camera) {
            new SavePhotoTask().execute(data);
            camera.startPreview();
            inPreview=true;
            if(!isFinishing()) {
                finish();
            }
        }
    };

onResume().

中正确创建预览表面后,我使用以下代码点击图片
preview.post(new Runnable() {
            @Override
            public void run() {
                if (inPreview) {
                    camera.takePicture(null, null, photoCallback);
                    inPreview=false;
                }
            }
        });

感谢任何帮助。谢谢

3 个答案:

答案 0 :(得分:1)

我认为你可以使用WakeLock来确保不会发生屏幕关闭。下面是示例代码/算法,您可以在屏幕关闭时打开屏幕。希望这有助于!

  1. 在Intent.ACTION_SCREEN_OFF上注册广播接收器。
  2. 每当屏幕关闭广播意图时,请使用以下代码唤醒。

    PowerManager pm = (PowerManager) context
                            .getSystemService(Context.POWER_SERVICE);
                    WakeLock wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK
                            | PowerManager.ACQUIRE_CAUSES_WAKEUP
                            | PowerManager.ON_AFTER_RELEASE, "MyWakeLock");
                    wakeLock.acquire();
    

答案 1 :(得分:1)

android:keepScreenOn="true" 

您可以在上面的行中使用您通过活动调用的XML中的父布局

它会始终保持您的屏幕显示,因此您不会遇到任何问题,希望它符合您的要求

答案 2 :(得分:1)

我在弄清楚广泛使用 LogCat 后发现问题是什么。)。

似乎在屏幕保持打开状态时,onPause()不会立即调用,SCREEN_OFF就是这种情况。当屏幕开启时,Runnable {1}}在执行onPause()方法之前执行,因此图片完全正常。但是当屏幕关闭时,Runnable在Activity之后执行完成onPause()方法。此时我们已经在onPause()发布了相机,因此我们无法获得图片。

在我弄清楚流程并将相机释放到onDestroy()之后开始工作了,这对于所有情况都不太理想,但对我来说效果很好,因为我的活动的唯一目的是拍照然后摧毁自己。

WAKELOCKS也没有改变代码的行为。我希望没有WAKE_LOCK就可以执行Activity但是它的工作完全正常。

希望这可以帮助陷入类似情况的人。