Android - Camera Module Interface
The CameraModule
interface is used when you want to override the default camera capture
functionality with your own custom native flow. By implementing this interface, you
can integrate third-party camera SDKs, custom capture experiences, or specialized
document scanning solutions directly into the mobile application.
The module utilizes Android's ActivityResultContract
to seamlessly connect your
custom camera flow with the main application. When a camera capture is requested,
your custom activity is launched, and the results are parsed back into the application
using the CameraModuleResult
type through the contract's parseResult
callback.
Implementation
Create a class that implements the CameraModule
interface. Once implemented,
override the required methods and implement your custom camera logic.
/**
* Example CameraModule implementation.
*
* A CameraModule allows you to override the default camera capture flow with custom
* camera functionality. This enables integration of third-party camera SDKs,
* specialized document capture, or custom image processing workflows.
*/
class CameraModuleExample(private val sdkUtils: SdkUtils): CameraModule {
override val contract =
object : ActivityResultContract<CameraModuleConfiguration, CameraModuleResult?>() {
override fun createIntent(context: Context, input: CameraModuleConfiguration): Intent {
return MyActivity.newIntent(context, params)
}
override fun parseResult(resultCode: Int, intent: Intent?): CameraModuleResult? {
return parseResults(resultCode, intent)
}
}
/**
* Called when user submits captured images. Return true to handle submission yourself,
* or false to let the default flow continue. If returning true, you must call the
* appropriate callback method (onSubmissionSuccess/onSubmissionError) when finished.
*/
override fun submitCapturedImages(
captureResult: CameraModuleResult.Success,
callback: CameraModuleSubmissionCallback
): Boolean {
// Handle custom submission logic here
callback.onSubmissionSuccess()
return true
}
/**
* Converts the activity result from your camera flow into a CameraModuleResult.
* Uses standard Android activity result codes to determine success or failure.
*/
private fun parseResults(resultCode: Int, intent: Intent?): CameraModuleResult? {
return when {
resultCode == Activity.RESULT_CANCELED -> {
CameraModuleResult.Failed(
CameraModuleConstants.ErrorCodes.USER_CANCELLED,
"User cancelled camera capture"
)
}
resultCode != Activity.RESULT_OK -> {
CameraModuleResult.Failed(
CameraModuleConstants.ErrorCodes.ACTIVITY_FAILED,
"Camera failed with code: $resultCode"
)
}
intent == null -> {
CameraModuleResult.Failed(
CameraModuleConstants.ErrorCodes.NO_DATA,
"No data returned from camera"
)
}
else -> parseSuccessfulResult(intent)
}
}
/**
* Extracts image data from a successful camera activity result.
* Parse the Intent data according to your camera implementation and return a CameraModuleResult.
*/
private fun parseSuccessfulResult(intent: Intent): CameraModuleResult {
val errorCode = intent.getStringExtra(CameraModuleConstants.ERROR_CODE_KEY)
if (errorCode != null) {
val errorMessage = intent.getStringExtra(CameraModuleConstants.ERROR_MESSAGE_KEY)
?: "Unknown camera error"
return CameraModuleResult.Failed(
CameraModuleConstants.ErrorCodes.LICENSE_ERROR,
errorMessage
)
}
// Parse image file paths. Depending on the flow, one or both may be returned.
val frontImagePath = intent.getStringExtra(CameraModuleConstants.FRONT_IMAGE_RESULT_KEY)
val backImagePath = intent.getStringExtra(CameraModuleConstants.BACK_IMAGE_RESULT_KEY)
// Create result based on which images were captured
return when {
frontImagePath != null && backImagePath != null -> {
CameraModuleResult.Success(File(frontImagePath), File(backImagePath))
}
frontImagePath != null -> {
CameraModuleResult.Success(File(frontImagePath), null)
}
backImagePath != null -> {
CameraModuleResult.Success(null, File(backImagePath))
}
else -> {
CameraModuleResult.Failed(
CameraModuleConstants.ErrorCodes.NO_IMAGES,
"No images were captured"
)
}
}
}
}
Key Components
ActivityResultContract
The contract
property defines how your custom camera activity is launched and how results
are processed. The createIntent
method launches your camera activity, while parseResult
converts the activity result into a CameraModuleResult
that the main application can understand.
submitCapturedImages Method
This callback is triggered when the user attempts to submit captured images. You can implement
custom validation, processing, or submission logic here. Return true
if you want to handle
the entire submission flow yourself, or false
to let the default flow continue.
CameraModuleResult Types
Your parseResult
method must return one of these result types:
CameraModuleResult.Success
- Contains the captured image files (front and/or back)CameraModuleResult.Failed
- Contains an error code and descriptive message
Update Your settings.json
Ensure your settings.json
file in the root of the DevApp is updated to reflect your
module changes. Learn more in Configuring settings.json.