Ana
Ana

Reputation: 196

Capture image in service without preview android

Problem statement:

When someone tries to open the device with the wrong pattern / PIN, my application should trigger an alarm, send an alert SMS to the registered mobile number. AND it should capture the image of the person trying to unlock the device, and send this image to registered Email ID.

What I have achieved:

I am confused about how can I capture image in background IntentService when the device is locked, and that, too without preview.

I cannot use the Camera intent obviously. Because startActivityForResult can't be called from Service. PLUS, I don't want user to capture the image after opening the Camera app.

My research led me to these posts already.

Can I use Android Camera in service without preview?

How to Capture Image When Device is Locked

Issue is:

Camera API is deprecate`. Camera2 API requires Minimum sdk version 21,

but my client's requirement is minSdkVersion 15, which I can't change. I am unable to figure out what should I do now. Any reference or help please?

Upvotes: 3

Views: 2870

Answers (1)

Ana
Ana

Reputation: 196

I solved my issue with help of this blog

So I capture the image within background service using this code:

@Override
public void onStart(Intent intent, int startId) {
    mCamera = getAvailableFrontCamera();     // globally declared instance of camera
    if (mCamera == null){
        mCamera = Camera.open();    //Take rear facing camera only if no front camera available
    }
    SurfaceView sv = new SurfaceView(getApplicationContext());
    SurfaceTexture surfaceTexture = new SurfaceTexture(10);

    try {
        mCamera.setPreviewTexture(surfaceTexture);
        //mCamera.setPreviewDisplay(sv.getHolder());
        parameters = mCamera.getParameters();

        //set camera parameters
        mCamera.setParameters(parameters);


        //This boolean is used as app crashes while writing images to file if simultaneous calls are made to takePicture
        if(safeToCapture) {
            mCamera.startPreview();
            mCamera.takePicture(null, null, mCall);
        }
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }


    //Get a surface
    sHolder = sv.getHolder();
    //tells Android that this surface will have its data constantly replaced
    sHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}

Camera.PictureCallback mCall = new Camera.PictureCallback()
{

    public void onPictureTaken(byte[] data, Camera camera)
    {
        safeToCapture = false;
        //decode the data obtained by the camera into a Bitmap

        FileOutputStream outStream = null;
        try{

            // create a File object for the parent directory
            File myDirectory = new File(Environment.getExternalStorageDirectory()+"/Test");
            // have the object build the directory structure, if needed.
            myDirectory.mkdirs();

            //SDF for getting current time for unique image name
            SimpleDateFormat curTimeFormat = new SimpleDateFormat("ddMMyyyyhhmmss");
            String curTime = curTimeFormat.format(new java.util.Date());

            // create a File object for the output file
            outStream = new FileOutputStream(myDirectory+"/user"+curTime+".jpg");
            outStream.write(data);
            outStream.close();
            mCamera.release();
            mCamera = null;

            String strImagePath = Environment.getExternalStorageDirectory()+"/"+myDirectory.getName()+"/user"+curTime+".jpg";
            sendEmailWithImage(strImagePath);
            Log.d("CAMERA", "picture clicked - "+strImagePath);
        } catch (FileNotFoundException e){
            Log.d("CAMERA", e.getMessage());
        } catch (IOException e){
            Log.d("CAMERA", e.getMessage());
        }

        safeToCapture = true;    //Set a boolean to true again after saving file.

    }
};

private Camera getAvailableFrontCamera (){

    int cameraCount = 0;
    Camera cam = null;
    Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
    cameraCount = Camera.getNumberOfCameras();
    for (int camIdx = 0; camIdx < cameraCount; camIdx++) {
        Camera.getCameraInfo(camIdx, cameraInfo);
        if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            try {
                cam = Camera.open(camIdx);
            } catch (RuntimeException e) {
                Log.e("CAMERA", "Camera failed to open: " + e.getLocalizedMessage());
            }
        }
    }

    return cam;
}


//Send Email using javamail API as user will not be allowed to choose available
// application using a Chooser dialog for intent.
public void sendEmailWithImage(String imageFile){
    .
    .
    .
}

Following uses-features and permissions will be needed for this in manifest file:

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

<uses-permission android:name="android.permission.SEND_MAIL" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />

I have set property required to false, so that user will be able to install my app even without any of the Camera available. May be this can help someone in future.

Upvotes: 3

Related Questions