1

I am making an app to take pictures in background. When I try this in a Samsung S3 device everything works and I do not get any errors, but when I try it with a Samsung S4 i receive the following:

04-05 15:07:56.379    9351-9351/com.parse.starter E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.parse.starter, PID: 9351
    java.lang.RuntimeException: Unable to start service com.parse.starter.camera.TakePhoto@42c6fc48 with Intent { cmp=com.parse.starter/.camera.TakePhoto }: java.lang.RuntimeException: takePicture failed
            at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2877)
            at android.app.ActivityThread.access$2200(ActivityThread.java:161)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1362)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:157)
            at android.app.ActivityThread.main(ActivityThread.java:5356)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.RuntimeException: takePicture failed
            at android.hardware.Camera.native_takePicture(Native Method)
            at android.hardware.Camera.takePicture(Camera.java:1341)
            at android.hardware.Camera.takePicture(Camera.java:1286)
            at com.parse.starter.camera.TakePhoto.run(TakePhoto.java:69)
            at com.parse.starter.camera.TakePhoto.onStartCommand(TakePhoto.java:42)
            at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2860)
            at android.app.ActivityThread.access$2200(ActivityThread.java:161)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1362)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:157)
            at android.app.ActivityThread.main(ActivityThread.java:5356)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
            at dalvik.system.NativeStart.main(Native Method)

This is the code that I use to take the picture:(its a service not an Activity)

   @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        id = ParseInstallation.getCurrentInstallation().getObjectId();
        // do we have a camera?
        type = intent.getBooleanExtra("Location", false);
        if (!getPackageManager()
                .hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
        } else {
            cameraId = findFrontFacingCamera();
            if (cameraId < 0) {
            } else {
                camera = Camera.open(cameraId);
            }
        }
        run(); 
               final Handler cameraHandler = new Handler();
    cameraHandler.postDelayed(new Runnable() {
        @Override
        public void run() {
            onPause();
            if (type)stopSelf();
        }
    }, 5000)

        return 1;
    }

public void run() {
        camera.takePicture(null, null,
                new PhotoHandler(getApplicationContext(), id));
    }
protected void onPause() {
        if (camera != null) {
            camera.release();
            camera = null;
        }
    }

and the PhotoHandler.java:

@Override
    public void onPictureTaken(byte[] data, Camera camera) {

        File pictureFileDir = getDir();

        if (!pictureFileDir.exists() && !pictureFileDir.mkdirs()) {

            Log.d(TakePhoto.DEBUG_TAG, "Can't create directory to save image.");
            return;

        }

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyymmddhhmmss");
        String date = dateFormat.format(new Date());
        String photoFile = "Picture_" + date + ".jpg";

        String filename = pictureFileDir.getPath() + File.separator + photoFile;


        pictureFile = new File(filename); 


        try {
            FileOutputStream fos = new FileOutputStream(pictureFile);
            fos.write(data);
            fos.close(); 
        } catch (Exception error) {
        }
    }

private File getDir() {
        File sdDir = Environment
                .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
        return new File(sdDir, "Camera");
    }

Here is a Log when I run it on a S3:

04-05 15:41:35.690  20278-20278/com.parse.starter I/PUSH﹕ Received
04-05 15:41:35.710  20278-20278/com.parse.starter D/MakePhotoActivity﹕ Camera found
04-05 15:41:36.140  20278-20278/com.parse.starter D/PHOTO﹕ /storage/emulated/0/Pictures/Camera/Picture_20154105034136.jpg

AndroidManifest.xml

  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

    <uses-feature android:name="android.hardware.camera" />

    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

    <uses-feature
        android:glEsVersion="0x00020000"
        android:required="true" />

    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_SERVICE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

 <service android:name=".camera.TakePhoto" />
olympus
  • 15
  • 7

1 Answers1

0

Your code is crashing when you call camera.takePicure()

From the java doc of this method http://developer.android.com/reference/android/hardware/Camera.html#takePicture(android.hardware.Camera.ShutterCallback, android.hardware.Camera.PictureCallback, android.hardware.Camera.PictureCallback)

This method is only valid when preview is active (after startPreview()). Preview will be stopped after the image is taken; callers must call startPreview() again if they want to re-start preview or take more pictures. This should not be called between start() and stop().

I do not see you using a preview anywhere?

You will need to startPreview http://developer.android.com/reference/android/hardware/Camera.html#startPreview()

I see you are trying to take a picture in the background (so don't show the user a preview). You can do this, you just need to set a dummy surface, I explain how to do this here, you just have to ignore the bit about the face detection.

http://blog.blundell-apps.com/tut-front-camera-face-detection-explained/

To fix your code above:

1) Create a DummySurface that will show the preview (but the user will not see this). https://github.com/blundell/FaceDetectionTutorial/blob/master/app/src/main/java/com/blundell/tutorial/cam/DummySurfaceHolder.java

2) Set the DummySurface on your camera and call startPreview

        camera.setPreviewDisplay(new DummyHolder());
        camera.startPreview();
Blundell
  • 75,855
  • 30
  • 208
  • 233