Capture Flow with Fragments
In order to use the capture flow with Fragments, follow these steps:
Request camera access.
Configure the capture feature using the
CaptureConfiguration
as in the documentation.Create the
CaptureFlowFragment
by callingcreateCaptureFlowFragment()
fromGiniBank
. It is the entrance forGini Bank SDK
.For open-with feature, create the
CaptureFlowFragment
by callingcreateCaptureFlowFragmentForIntent(intent: Intent, callback: (CreateCaptureFlowFragmentForIntentResult) -> Unit)
to to create theCaptureFlowFragment
with the PDF/images from the intent.Set a listener (
CaptureFlowFragmentListener
) on the instance ofCaptureFlowFragment
via thesetListener()
instance method. This allows unsubscribing when the host fragment has finished it process (by returning a result through the listener).Hide your activity’s action bar. The Gini Bank SDK fragments show their own navigation bars.
Show the
CaptureFlowFragment
with your fragment manager.Handle the extraction results.
Send the final transfer summary values to Gini by calling
GiniBank.sendTransferSummary()
method which will be used to improve the future extraction accuracyClean up the SDK by calling
GiniBank.releaseCapture()
which will release the resources used by SDK.
Follow these recommendations:
Provide values for all necessary fields, including those that were not extracted.
Provide the final data approved by the user (and not the initially extracted only).
Send transfer summary only after TAN verification.
You don’t need to implement any extra steps.
The diagram shows the interaction between your app and the SDK:
Gini Bank SDK returns one of the following results:
CaptureResult.Success
A document was analysed and the extractions are available in the properties of the CaptureResult.Success
object.
CaptureResult.Cancel
The user canceled Gini Bank SDK.
CaptureResult.Error
An error occurred and the details are available in the value
property of the CaptureResult.Error
object.
CaptureResult.Empty
Gini Bank SDK was able to extract information, but they were not payment related. Your app should proceed with enabling your user to enter the payment information manually.
CaptureResult.EnterManually
The document analysis finished with no results or an error and the user clicked the Enter manually button on either the No Results Screen or the Error Screen. To enable manual entry of payment information, let your app prompt users for manual input.
Learn how to launch the capture flow and handle the results from the example:
class ClientExampleFragment :
Fragment(R.layout.fragment_client_example),
// Implement this listener in the fragment that wants to host the Gini Bank SDK
CaptureFlowFragmentListener {
private lateinit var permissionHandler: PermissionHandler
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (savedInstanceState == null) {
requestCameraPermissionAndStartBankSDK()
} else {
// Set the listener on CaptureFlowFragment again after the fragment has been restored
val captureFlowFragment =
requireActivity().supportFragmentManager.findFragmentByTag("CaptureFlowFragment") as? CaptureFlowFragment
captureFlowFragment?.setListener(this)
}
// Hide the action bar because the Gini Bank SDK fragments have their own action bars (navigation bars)
(requireActivity() as AppCompatActivity).supportActionBar?.hide()
}
private fun requestCameraPermissionAndStartBankSDK() {
permissionHandler = PermissionHandler(requireActivity())
lifecycleScope.launch {
if (permissionHandler.grantPermission(Manifest.permission.CAMERA)) {
// Always configure the Gini Bank SDK before starting it
configureBankSDK()
// If your activity was launched from another app via "open with" then
// pass the activity's intent to Gini Bank SDK
if (isIntentActionViewOrSend(requireActivity().intent) {
startBankSDKForIntent(requireActivity().intent)
} else {
// Otherwise you can start the Gini Bank SDK without any intent
startBankSDK()
}
} else {
// Inform user that camera permission is needed
}
}
}
// Configures the Gini Bank SDK (it is the same as activity flow but major versions in Gini Bank SDK may have different configuration)
private fun configureBankSDK() {
val clientId = // your Gini Pay API client ID
val clientSecret = // your Gini Pay API client secret
val networkService = GiniCaptureDefaultNetworkService
.builder(requireContext())
.setClientCredentials(
clientId,
clientSecret,
"example.com"
)
.build()
val captureConfiguration = CaptureConfiguration(
networkService = networkService,
fileImportEnabled = true,
documentImportEnabledFileTypes = DocumentImportEnabledFileTypes.PDF_AND_IMAGES,
qrCodeScanningEnabled = true,
flashButtonEnabled = true,
multiPageEnabled = true,
)
GiniBank.setCaptureConfiguration(requireContext(), captureConfiguration)
}
private fun startBankSDK() {
// Create the CaptureFlowFragment (the entrance for Gini Bank SDK)
val captureFlowFragment = GiniBank.createCaptureFlowFragment()
// Set the listener to receive the Gini Bank SDK's results
captureFlowFragment.setListener(this)
// Show the CaptureFlowFragment for example via the fragment manager:
requireActivity().supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, captureFlowFragment, "CaptureFlowFragment")
.addToBackStack(null)
.commit()
}
fun startBankSDKForIntent(openWithIntent: Intent) {
GiniBank.createCaptureFlowFragmentForIntent(requireContext(), openWithIntent) { result ->
when (result) {
GiniBank.CreateCaptureFlowFragmentForIntentResult.Cancelled -> {
// Creating the CaptureFlowFragment was cancelled
}
is GiniBank.CreateCaptureFlowFragmentForIntentResult.Error -> {
// There was an error in opening the file(s) from the intent
}
is GiniBank.CreateCaptureFlowFragmentForIntentResult.Success -> {
// Opening the file(s) from the intent and creating the CaptureFlowFragment
// Set the listener to receive the Gini Bank SDK's results
result.fragment.setListener(this)
// Show the CaptureFlowFragment for example via the fragment manager:
requireActivity().supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, result.fragment, "CaptureFlowFragment")
.addToBackStack(null)
.commit()
}
}
}
}
// Handle the results from Gini Bank SDK
override fun onFinishedWithResult(result: CaptureResult) {
when (result) {
is CaptureResult.Success -> {
// Handle extraction results (to proceed with the transaction)
handleExtractions(result.specificExtractions)
// After the user has seen (and maybe edited) the extractions and has executed the transfer
// please send the transfer summary to Gini with the final data approved by the user.
// The stopGiniBankSDKWithTransferSummary(...) method shows how to send the transfer summary.
}
is CaptureResult.Error -> {
when (result.value) {
is ResultError.Capture ->
// There was a capture error
is ResultError.FileImport ->
// There was a file import error
else -> {}
}
}
CaptureResult.Empty -> {
// Handle empty result
}
CaptureResult.Cancel -> {
// Process was cancelled by user
}
CaptureResult.EnterManually -> {
// User wants to enter the invoice data manually
}
}
}
fun stopGiniBankSDKWithTransferSummary(paymentRecipient: String,
paymentReference: String,
paymentPurpose: String,
iban: String,
bic: String,
amount: Amount
) {
// After the user has seen and potentially corrected the extractions, send the final
// transfer summary values to Gini which will be used to improve the future extraction accuracy:
GiniBank.sendTransferSummary(
paymentRecipient,
paymentReference,
paymentPurpose,
iban,
bic,
amount
)
// cleanup the capture SDK after sending the transfer summary
GiniBank.releaseCapture(this)
}
private fun isIntentActionViewOrSend(intent: Intent): Boolean {
val action = intent.action
return Intent.ACTION_VIEW == action || Intent.ACTION_SEND == action || Intent.ACTION_SEND_MULTIPLE == action
}
}
Gini GmbH | Ridlerstr. 57 | 80339 München