SmartSelfie Capture

The Smile ID Library is great for capturing high quality photos and supports a wide range of devices from low end to high end smart phones.

The Smile ID library enables capturing the perfect selfies through the library with various checks being done on the device before capturing the final selfie.

There are five components essential to setting up the selfie capture process namely CameraSourcePreview, SmartSelfieManager, SelfieCaptureConfig ,OnfaceStateChangedListener and SmartSelfieManager.OnCompleteListener

CameraSourcePreview

The CameraSourcePreview is a custom view that presents the camera as an oval in the middle of the screen surrounded by a progress bar that loads as the perfect selfie is captured. This custom view provides a simple way to capture user selfies.

It is advised to give the view as much real estate as possible giving an aspect ratio of about 2.5:3 but this can be changed as necessary

Place the view in your layout xml file as indicated below

<com.smileidentity.libsmileid.core.CameraSourcePreview
    android:id="@+id/previewCamera"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_alignParentTop="true"
    app:captured_progress_state_color="<YOUR COLOR CHOICE>"
    app:capturing_progress_state_color="<YOUR COLOR CHOICE>"
    app:overlay_height="300dp"
    app:overlay_width="250dp"
    app:progress_width="15dp" />
AttributeMeaning

capturing_progress_state_color (color)

defines the colour of the progress circle when the library is capturing the selfie

captured_progress_state_color (color)

defines the colour of the progress circle when the library captured a selfie also when the capture is complete.

progress_width (dimension)

Width of the capture progress circle

overlay_width (dimension)

Width of the oval guide of the face capture

overlay_height (dimension)

height of the oval guide of the face capture

SelfieCaptureConfig

This object carries instructions on how the SelfieManager should capture selfies and it has six main methods

Step 1 : Initialise the SelfieCaptureConfig

SelfieCaptureConfig.Builder using the method below which takes a context as it's argument

SelfieCaptureConfig.Builder selfieCaptureConfigBuilder = new SelfieCaptureConfig.Builder(Context context)

Step 2 : set the camera type

This method tells the SelfieManager which camera to use and takes two arguments from SelfieCaptureConfig which could either be SelfieCaptureConfig.BACK_CAMERA or SelfieCaptureConfig.FRONT_CAMERA

/**
SelfieCaptureConfig.BACK_CAMERA // for the back camera
SelfieCaptureConfig.FRONT_CAMERA //for the selfie camera
**/
selfieCaptureConfigBuilder.setCameraType(SelfieCaptureConfig.FRONT_CAMERA)

Step 3 : Set the preview

This method takes the CameraSourcePreview as an argument and instructs the SelfieManager you will be using this view to show the camera activity as the selfie capture process progresses

CameraSourcePreview preview = findViewById(R.id.previewCamera);
selfieCaptureConfigBuilder.setPreview(mPreview)

Step 4 : Set if you would like to capture the selfie manually

By default the sdk will capture the selfie once it . has done checks on the face in the camera however there are cases when you might want to capture the selfie manually and you can do this through

selfieCaptureConfigBuilder.setManualSelfieCapture(true)

Step 5 Setup if you would like the screen flash

This enables the screen to flash when capturing the photo

selfieCaptureConfigBuilder.setFlashScreenOnShutter(true)

Step . 6 Finally build

So to summarise the whole process the below would be the final code

SelfieCaptureConfig selfieCaptureConfigBuilder = new SelfieCaptureConfig.Builder(this)
                .setCameraType(SelfieCaptureConfig.FRONT_CAMERA)
                .setPreview(mPreview)
                .setManualSelfieCapture(mMultipleEnroll)
                .setFlashScreenOnShutter(!mMultipleEnroll)
                .build();

SmartSelfieManager

At the heart of the selfie capture process is the SmartSelfieManager class which manages the whole process by getting input from the CameraSourcePreview and providing your application with call backs via the OnFaceStateChangeListener and SmartSelfieManager.OnCompleteListener

Step 1 : Create the SelfieCaptureConfig object

This object carries instructions on how the SelfieManager should capture selfies and it has four main methods

Instantiate the class using SmartSelfieManager(SelfieCaptureConfig config) and this method expects an object of SelfieCaptureConfig to instruct how

//selfieCaptureConfigBuilder mentioned with the SelfieCaptureConfig section
SmartSelfieManager smartSelfieManager = new SmartSelfieManager(selfieCaptureConfigBuilder);

Step 2 : Setup Callbacks

Everything that happens in the SmartSelfieManager is relayed back to the implementing class through two callbacks the first on is SmartSelfieManafer.OnCompleteListener and OnFaceStateChangedListener

SmartSelfieManafer.OnCompleteListener

This interface has two methods the first one is onComplete which is called once the capture is complete and it returns a bitmap to the implementing class

void onComplete(Bitmap fullPreview);

The second one is on Error which relays errors that happens within the SmartSelfieManager the main one is SIDError.COULD_NOT_INITIALIZE_CAMERA which happens in case there is an error whilst trying to initialize the camera, it may also return exceptions with a sumarry of what went wrong

SmartSelfieManafer.takePicture

This method will take a manual selfie for cases when selfie has been set to capture manually

OnFaceStateChangedListener

This interface has one method which is onFaceStateChange which is responsible for relaying back to you prompts which you may use to inform the user on actions to direct them to take the best photo

void onFaceStateChange(FaceState status)

This method returns an enum which has values listed below

  • NO_FACE_FOUND => If SmartSelfieManager cannot find a face on the camera

  • DO_MOVE_CLOSER => If SmartSelfieManager detects the user is a bit far from the camera

  • DO_SMILE => If SmartSelfieManager has found a face and needs to prove it is indeed a human and asks them to smile

  • DO_SMILE_MORE => If SmartSelfieManager detects a smile but needs to be certain t might ask the user to smile more

  • CAPTURING => SmartSelfieManager is busy capturing the photos

  • FACE_TOO_CLOSE => Face is too close to the camera and needs to move a bit further

  • BLURRY => If the camera feed is a bit . blurry

  • TOO_DARK => If lighting condition is not optimum for the perfect selfie

  • COLOR_CHECK_FAILED =>

  • IDLE

  • COMPATIBILITY_MODE => If there is an issue with the device's compatibility with the library

In summary the two callbacks would be

 smartSelfieManager.setOnCompleteListener(this);
 smartSelfieManager.setOnFaceStateChangeListener(this);
 
  @Override
    public void onFaceStateChange(FaceState faceState) {
        switch (faceState) {
            case DO_SMILE:
                //prompt the user to smile
                break;
            case CAPTURING:
                //prompt the user your app is capturing
                break;
            case DO_SMILE_MORE:
                //prompt the user to smile more
                break;
            case NO_FACE_FOUND:
                //prompt the user there is no face found
                break;
            case DO_MOVE_CLOSER:
                //prompt the user to move closer to the camera
                break;
        }
    }
    
    
    @Override
    public void onComplete(Bitmap fullPreviewFrame) {
        if (fullPreviewFrame != null) {
            //Process returned full preview frame
        }
        
    }
    
     @Override
    public void onError(Throwable e) {
        //handle error
    }
    

Important SmartSelfieManager Callbacks

From version 6.1.0 of the library there has been callbacks introduced to provide better stability with regards to how the android OS manages the camera there are below and should correlate with android fragment/Activity lifecycles

@Override
protected void onResume() {
    super.onResume();
    smartSelfieManager.resume();
}
@Override
protected void onPause() {
    super.onPause();
    smartSelfieManager.pause();
}
@Override
protected void onStop() {
    super.onStop();
    smartSelfieManager.stop();
}
//smartSelfieManager.resume() should be called when your activity/fragment resumes (onResume)
//smartSelfieManager.pause() should be called when your activity/fragment pauses (onPause)
//smartSelfieManager.stop() should be called when your activity/fragment stops (onStop)
Important SmartSelfieManager Callbacks
From version 6.1.0 of the library there has been callbacks introduced to provide better stability with regards to how the android OS manages the camera there are below and should correlate with android fragment/Activity lifecycles
@Override
protected void onResume() {
    super.onResume();
    smartSelfieManager.resume();
}
@Override
protected void onPause() {
    super.onPause();
    smartSelfieManager.pause();
}
@Override
protected void onStop() {
    super.onStop();
    smartSelfieManager.stop();
}
//smartSelfieManager.resume() should be called when your activity/fragment resumes (onResume)
//smartSelfieManager.pause() should be called when your activity/fragment pauses (onPause)
//smartSelfieManager.stop() should be called when your activity/fragment stops (onStop)

OVERALL EXAMPLE USAGE IN AN ACTIVITY OR FRAGMENT

public class SIDSelfieActivity extends AppCompatActivity implements
        OnFaceStateChangeListener,
        SmartSelfieManager.OnCompleteListener{
    CameraSourcePreview mPreview;
    private TextView mPromptTv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.sid_activity_selfie);
        mPreview = findViewById(R.id.previewCamera);
        mPromptTv = findViewById(R.id.prompt_tv);
        initSmartSelfie();
    }  
    
   private void initSmartSelfie(){
        smartSelfieManager = new SmartSelfieManager(getCaptureConfig());
        smartSelfieManager.setOnCompleteListener(this);
        smartSelfieManager.setOnFaceStateChangeListener(this)
        smartSelfieManager.captureSelfie($UNIQUE_TAG); <= should be unique per job that you run unless you want to overwrite a job
   }     
    
    private SelfieCaptureConfig getCaptureConfig() {
        return new SelfieCaptureConfig.Builder(this)//or getActivity() if in fragment
                .setCameraType(SelfieCaptureConfig.FRONT_CAMERA)
                .setPreview(mPreview)
                .setManualSelfieCapture(false)
                .setProminentSmileText("Smile!")
                .build();
    }

    
    @Override
    protected void onResume() {
        super.onResume();
        smartSelfieManager.resume();
    }
    @Override
    protected void onPause() {
        super.onPause();
        smartSelfieManager.pause();
    }
    @Override
    protected void onStop() {
        super.onStop();
        smartSelfieManager.stop();
    }  

    @Override
    public void onComplete(Bitmap fullPreviewFrame) {
        //Capture is complete all selfies ready, can start upload screen 
    }
    
     @Override
    public void onError(Throwable e) {
        /**
         handle errors and maybe retry using
         initSmartSelfie();
         smartSelfieManager.resume();
         **/
    }
    
    @Override
    public void onFaceStateChange(FaceState faceState) {
        switch (faceState) {
            case DO_SMILE:
                mPromptTv.setText("Smile for the camera");
                break;
            case CAPTURING:
                mPromptTv.setText("Please wait while we capture");
                break;
            case DO_SMILE_MORE:
                mPromptTv.setText("Smile More");
                break;
            case NO_FACE_FOUND:
                mPromptTv.setText("Cannot find a face");
                break;
            case DO_MOVE_CLOSER:
                mPromptTv.setText("Please move closer");
                break;
            case BLURRY:
                mPromptTv.setText("Image is blurry");
                break;
            case TOO_DARK:
                mPromptTv.setText("Need more light");
                break;
            case COMPATIBILITY_MODE:
                mPromptTv.setText("COMPATIBILITY MODE");
                break;
        }
    }
}

Last updated