Taking picture from camera without preview

前端 未结 9 1183
北荒
北荒 2020-11-22 13:01

I am writing an Android 1.5 application which starts just after boot-up. This is a Service and should take a picture without preview. This app will log the ligh

相关标签:
9条回答
  • 2020-11-22 13:41

    There is a way of doing this but it's somewhat tricky. what should be done, is attach a surfaceholder to the window manager from the service

    WindowManager wm = (WindowManager) mCtx.getSystemService(Context.WINDOW_SERVICE);
    params = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
                WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
                PixelFormat.TRANSLUCENT);        
    wm.addView(surfaceview, params);
    

    and then set

    surfaceview.setZOrderOnTop(true);
    mHolder.setFormat(PixelFormat.TRANSPARENT);
    

    where mHolder is the holder you get from the surface view.

    this way, you can play with the surfaceview's alpha, make it completly transparent, but the camera will still get frames.

    that's how i do it. hope it helps :)

    0 讨论(0)
  • 2020-11-22 13:42

    You can try this working code, This service click front picture, if you want to capture back camera picture then uncomment back camera in code and comment front camera.

    Note :- Allow Camera and Storage permission to App And startService from Activity or anywhere.

    public class MyService extends Service {
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
            CapturePhoto();
        }
    
        private void CapturePhoto() {
    
            Log.d("kkkk","Preparing to take photo");
            Camera camera = null;
    
            Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
    
                int frontCamera = 1;
                //int backCamera=0;
    
                Camera.getCameraInfo(frontCamera, cameraInfo);
    
                try {
                    camera = Camera.open(frontCamera);
                } catch (RuntimeException e) {
                    Log.d("kkkk","Camera not available: " + 1);
                    camera = null;
                    //e.printStackTrace();
                }
                try {
                    if (null == camera) {
                        Log.d("kkkk","Could not get camera instance");
                    } else {
                        Log.d("kkkk","Got the camera, creating the dummy surface texture");
                         try {
                             camera.setPreviewTexture(new SurfaceTexture(0));
                            camera.startPreview();
                        } catch (Exception e) {
                            Log.d("kkkk","Could not set the surface preview texture");
                            e.printStackTrace();
                        }
                        camera.takePicture(null, null, new Camera.PictureCallback() {
    
                            @Override
                            public void onPictureTaken(byte[] data, Camera camera) {
                                File pictureFileDir=new File("/sdcard/CaptureByService");
    
                                if (!pictureFileDir.exists() && !pictureFileDir.mkdirs()) {
                                    pictureFileDir.mkdirs();
                                }
                                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyymmddhhmmss");
                                String date = dateFormat.format(new Date());
                                String photoFile = "ServiceClickedPic_" + "_" + date + ".jpg";
                                String filename = pictureFileDir.getPath() + File.separator + photoFile;
                                File mainPicture = new File(filename);
    
                                try {
                                    FileOutputStream fos = new FileOutputStream(mainPicture);
                                    fos.write(data);
                                    fos.close();
                                    Log.d("kkkk","image saved");
                                } catch (Exception error) {
                                    Log.d("kkkk","Image could not be saved");
                                }
                                camera.release();
                            }
                        });
                    }
                } catch (Exception e) {
                    camera.release();
                }
        }
    }
    
    0 讨论(0)
  • 2020-11-22 13:43

    Taking the Photo

    Get this working first before trying to hide the preview.

    • Correctly set up the preview
      • Use a SurfaceView (pre-Android-4.0 compatibility) or SurfaceTexture (Android 4+, can be made transparent)
      • Set and initialise it before taking the photo
      • Wait for the SurfaceView's SurfaceHolder (via getHolder()) to report surfaceCreated() or the TextureView to report onSurfaceTextureAvailable to its SurfaceTextureListener before setting and initialising the preview.
    • Ensure the preview is visible:
      • Add it to the WindowManager
      • Ensure its layout size is at least 1x1 pixels (you might want to start by making it MATCH_PARENT x MATCH_PARENT for testing)
      • Ensure its visibility is View.VISIBLE (which seems to be the default if you don't specify it)
      • Ensure you use the FLAG_HARDWARE_ACCELERATED in the LayoutParams if it's a TextureView.
    • Use takePicture's JPEG callback since the documentation says the other callbacks aren't supported on all devices

    Troubleshooting

    • If surfaceCreated/onSurfaceTextureAvailable doesn't get called, the SurfaceView/TextureView probably isn't being displayed.
    • If takePicture fails, first ensure the preview is working correctly. You can remove your takePicture call and let the preview run to see if it displays on the screen.
    • If the picture is darker than it should be, you might need to delay for about a second before calling takePicture so that the camera has time to adjust its exposure once the preview has started.

    Hiding the Preview

    • Make the preview View 1x1 size to minimise its visibility (or try 8x16 for possibly more reliability)

      new WindowManager.LayoutParams(1, 1, /*...*/)
      
    • Move the preview out of the centre to reduce its noticeability:

      new WindowManager.LayoutParams(width, height,
          Integer.MIN_VALUE, Integer.MIN_VALUE, /*...*/)
      
    • Make the preview transparent (only works for TextureView)

      WindowManager.LayoutParams params = new WindowManager.LayoutParams(
          width, height, /*...*/
          PixelFormat.TRANSPARENT);
      params.alpha = 0;
      

    Working Example (tested on Sony Xperia M, Android 4.3)

    /** Takes a single photo on service start. */
    public class PhotoTakingService extends Service {
    
        @Override
        public void onCreate() {
            super.onCreate();
            takePhoto(this);
        }
    
        @SuppressWarnings("deprecation")
        private static void takePhoto(final Context context) {
            final SurfaceView preview = new SurfaceView(context);
            SurfaceHolder holder = preview.getHolder();
            // deprecated setting, but required on Android versions prior to 3.0
            holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    
            holder.addCallback(new Callback() {
                @Override
                //The preview must happen at or after this point or takePicture fails
                public void surfaceCreated(SurfaceHolder holder) {
                    showMessage("Surface created");
    
                    Camera camera = null;
    
                    try {
                        camera = Camera.open();
                        showMessage("Opened camera");
    
                        try {
                            camera.setPreviewDisplay(holder);
                        } catch (IOException e) {
                            throw new RuntimeException(e);
                        }
    
                        camera.startPreview();
                        showMessage("Started preview");
    
                        camera.takePicture(null, null, new PictureCallback() {
    
                            @Override
                            public void onPictureTaken(byte[] data, Camera camera) {
                                showMessage("Took picture");
                                camera.release();
                            }
                        });
                    } catch (Exception e) {
                        if (camera != null)
                            camera.release();
                        throw new RuntimeException(e);
                    }
                }
    
                @Override public void surfaceDestroyed(SurfaceHolder holder) {}
                @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}
            });
    
            WindowManager wm = (WindowManager)context
                .getSystemService(Context.WINDOW_SERVICE);
            WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                    1, 1, //Must be at least 1x1
                    WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
                    0,
                    //Don't know if this is a safe default
                    PixelFormat.UNKNOWN);
    
            //Don't set the preview visibility to GONE or INVISIBLE
            wm.addView(preview, params);
        }
    
        private static void showMessage(String message) {
            Log.i("Camera", message);
        }
    
        @Override public IBinder onBind(Intent intent) { return null; }
    }
    
    0 讨论(0)
提交回复
热议问题