Capture Flow with Fragments

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

  1. Request camera access.

  2. Configure the capture feature using the GiniCapture.Builder() as in the documentation.

  3. Create the GiniCaptureFragment by calling createGiniCaptureFragment() from GiniCapture. It is the entrance for Gini Capture SDK.

  4. For open-with feature, create the GiniCaptureFragment by calling GiniCapture.getInstance().createGiniCaptureFragmentForIntent(Context context, Intent intent, CreateGiniCaptureFragmentForIntentCallback captureIntentCallback) to to create the GiniCaptureFragment with the PDF/images from the intent.

  5. Set a listener (GiniCaptureFragmentListener) on the instance of GiniCaptureFragment 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 Capture SDK fragments show their own navigation bars.

  7. Show the GiniCaptureFragment with your fragment manager.

  8. Handle the extraction results.

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

  10. Clean up the SDK by calling GiniCapture.cleanup(Conext context) 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 Capture SDK returns one of the following results:

  • CaptureSDKResult.Success

A document was analysed and the extractions are available in the properties of the CaptureSDKResult.Success object.

  • CaptureSDKResult.Cancel

The user canceled Gini Capture SDK.

  • CaptureSDKResult.Error

An error occurred and the details are available in the value property of the CaptureSDKResult.Error object.

  • CaptureSDKResult.Empty

Gini Capture 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.

  • CaptureSDKResult.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 Capture SDK GiniCaptureFragmentListener { private lateinit var permissionHandler: PermissionHandler private var mFileImportCancellationToken: CancellationToken? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) if (savedInstanceState == null) { requestCameraPermissionAndStartCaptureSDK() } else { // Set the listener on GiniCaptureFragment again after the fragment has been restored val giniCaptureFragment = requireActivity().supportFragmentManager.findFragmentByTag("fragment_host") as? GiniCaptureFragment giniCaptureFragment?.setListener(this) } // Hide the action bar because the Gini Capture SDK fragments have their own action bars (navigation bars) (requireActivity() as AppCompatActivity).supportActionBar?.hide() } private fun requestCameraPermissionAndStartCaptureSDK() { permissionHandler = PermissionHandler(requireActivity()) lifecycleScope.launch { if (permissionHandler.grantPermission(Manifest.permission.CAMERA)) { // Always configure the Gini Capture SDK before starting it configureCaptureSDK() // If your activity was launched from another app via "open with" then // pass the activity's intent to Gini Capture SDK if (isIntentActionViewOrSend(requireActivity().intent) { startCaptureSDKForIntent(requireActivity().intent) } else { // Otherwise you can start the Gini Capture SDK without any intent startCaptureSDK() } } else { // Inform user that camera permission is needed } } } // Configures the Gini Capture SDK (it is the same as activity flow but major versions in Gini Capture SDK may have different configuration) private fun configureCaptureSDK() { val clientId = // your Gini Pay API client ID val clientSecret = // your Gini Pay API client secret val documentMetadata = DocumentMetadata() val networkService = GiniCaptureDefaultNetworkService .builder(requireContext()) .setClientCredentials( clientId, clientSecret, "example.com" ) .setDocumentMetadata(documentMetadata) .build() GiniCapture.Builder() .setGiniCaptureNetworkService(networkService) .setFileImportEnabled(true) .setDocumentImportEnabledFileTypes(DocumentImportEnabledFileTypes.PDF_AND_IMAGES) .setQRCodeScanningEnabled(true) .setFlashButtonEnabled(true) .setMultiPageEnabled(true) .build() } private fun startCaptureSDK() { // Create the GiniCaptureFragment (the entrance for Gini Capture SDK) val giniCaptureFragment = GiniCapture.createGiniCaptureFragment() // Set the listener to receive the Gini Capture SDK's results giniCaptureFragment.setListener(this) requireActivity().supportFragmentManager.beginTransaction() .replace(R.id.fragment_host, giniCaptureFragment, "GiniCaptureFragment") .addToBackStack(null) .commit() } fun startCaptureSDKForIntent(openWithIntent: Intent) { mFileImportCancellationToken = GiniCapture.getInstance().createGiniCaptureFragmentForIntent( requireActivity(), openWithIntent, object : GiniCapture.CreateGiniCaptureFragmentForIntentCallback { override fun callback(result: GiniCapture.CreateGiniCaptureFragmentForIntentResult?) { when (result) { is GiniCapture.CreateGiniCaptureFragmentForIntentResult.Success -> { // Opening the file(s) from the intent and creating the GiniCaptureFragment finished // Set the listener to receive the Gini Capture SDK's results result.fragment.setListener(this@ClientCaptureSDKFragment) // Show the CaptureFlowFragment for example via the fragment manager: requireActivity().supportFragmentManager.beginTransaction() .replace(R.id.fragment_host, result.fragment, "GiniCaptureFragment") .addToBackStack(null) .commit() } is GiniCapture.CreateGiniCaptureFragmentForIntentResult.Error -> { // There was an error in opening the file(s) from the intent } is GiniCapture.CreateGiniCaptureFragmentForIntentResult.Cancelled -> { // Creating the CaptureFlowFragment was cancelled } } } }) } override fun onDestroy() { super.onDestroy() if (mFileImportCancellationToken != null) { mFileImportCancellationToken!!.cancel() mFileImportCancellationToken = null } } // Handle the results from Gini Capture SDK override fun onFinishedWithResult(result: CaptureSDKResult) { when (result) { is CaptureSDKResult.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 stopGiniCaptureSDKWithTransferSummary(...) method shows how to send the transfer summary. } is CaptureSDKResult.Error -> { // Something went wrong when opening the file(s) from the intent or uploading the document } CaptureSDKResult.Empty -> { // Handle empty result } CaptureSDKResult.Cancel -> { // Process was cancelled by user } CaptureSDKResult.EnterManually -> { // User wants to enter the invoice data manually } } } fun stopGiniCaptureSDKWithTransferSummary(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: GiniCapture.sendTransferSummary( paymentRecipient, paymentReference, paymentPurpose, iban, bic, amount ) // cleanup the capture SDK after sending the transfer summary GiniCapture.cleanup(requireActivity()) } private fun isIntentActionViewOrSend(intent: Intent): Boolean { val action = intent.action return Intent.ACTION_VIEW == action || Intent.ACTION_SEND == action || Intent.ACTION_SEND_MULTIPLE == action } }