Capture Flow with Fragments

In order to use the capture flow with Fragments, follow these steps:

  1. Request camera access.

  2. Configure the capture feature using the CaptureConfiguration as in the documentation.

  3. Create the CaptureFlowFragment by calling createCaptureFlowFragment() from GiniBank. It is the entrance for Gini Bank SDK.

  4. For open-with feature, create the CaptureFlowFragment by calling createCaptureFlowFragmentForIntent(intent: Intent, callback: (CreateCaptureFlowFragmentForIntentResult) -> Unit) to to create the CaptureFlowFragment with the PDF/images from the intent.

  5. Set a listener (CaptureFlowFragmentListener) on the instance of CaptureFlowFragment via the setListener() instance method. This allows unsubscribing when the host fragment has finished it process (by returning a result through the listener).

  6. Hide your activity’s action bar. The Gini Bank SDK fragments show their own navigation bars.

  7. Show the CaptureFlowFragment with your fragment manager.

  8. Handle the extraction results.

  9. Send the final transfer summary values to Gini by calling GiniBank.sendTransferSummary()method which will be used to improve the future extraction accuracy

  10. Clean 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 } }