Using DyScanView
The DyScanView is a more complicated integration strategy that gives you more control over the user experience in your app, for example by reserving parts of the screen for other Views, or even drawing Views on top of the DyScanView. In exchange, you will be responsible for many things that DyScanActivity normally takes care of for you, such as requesting permissions, providing callbacks, and notifying the View of when certain events occur. We assume in this guide that you have already imported the library into your project.
For the default integration methodology, see the Android Integration Guide.
Adding DyScanView to a layout
To incorporate the View into a layout, you should first add a new namespace just below the android namespace to be able to set the attributes in the layout:
After this, you can add a DyScanView to the layout. You must use the fully qualified class name in the layout file. The example below shows one attribute set on the View; a complete list of available attributes appears in Customizing the Layout.
We recommend using a RelativeLayout
as the parent to the DyScanView. You can then use the layout attributes such as android:layout_above
and android:layout_below
in order to dictate the relationship between the DyScanView and the other Views.
The DyScanView currently does not support being used in landscape activities. All activities that use the DyScanView should set the screenOrientation attribute on the activity tag to "portrait". If the activity is used in landscape mode it will crash.
Setting up DyScanView in the code
(Only for version lower than 1.1.0) The first thing you'll want to do is set your API key in onCreate()
with setApiKey(String apiKey)
.
We may change how the key is provided in the future for security reasons; for now, please endeavor to keep the key safe.
Listening for the result
Now you'll want to provide a callback implementing the DyScanView.DyScanResultListener interface by passing it into setResultListener()
. This call should happen as early as possible, ideally immediately after setting the API key. As an example, the following code will progress to the EnterCardActivity when scanning is complete, passing along the card details if we got them.
onSuccess()
will be called when we successfully scan a card, and onFailure()
is called when we were not able to scan a card.
Optionally, you can implement the function onProgressUpdate
to access information about the card being scanned while the scan is ongoing (available for version 1.6.6
of DyScan and up). The DyScanProgressUpdate
class has two attributes (both of string type): lastFourDigits
and network
, which correspond to the last four digits and network of the credit card (e.g., Visa or Mastercard) being scanned, respectively. You may choose to surface this information to your users to give them more feedback as they are waiting for their card to scan.
If dyscanView.setPromptIfFewDigits(true)
has been called, DyScanProgressUpdate
will additionally have a boolean
attribute fewDigitsSeen
which will be true
when you should remind the user to show the card digits to the camera.
The CreditCard object is basically the same as mentioned in DyScanActivity, but will also contain the bounding boxes of where the card number and expiration date were found. The integer passed in to onFailure()
is an indicator of why things failed; the various values that can be passed in are provided here:
Exit Reason
Explanation
EXIT_REASON_AUTH_FAILURE
Our servers are indicating that the API key provided is not valid. You should check that you have set this value by calling setApiKey()
and that it is the correct value.
EXIT_REASON_PERMISSIONS_NOT_GRANTED
The system indicated that we do not have permissions to access the camera. You should make sure that you have requested camera permissions from the user prior to calling onPermissionsGranted()
.
EXIT_REASON_CAMERA_ERROR
We were not able to access the camera properly. It may be the case that another app (or your app) has failed to release the camera.
EXIT_REASON_USER_REQUESTED_MANUAL_ENTRY
If you have opted to have the manual entry button shown in the UI, this is the code that will be returned when the user presses that button.
You do not have to explicitly check for these codes, but you may find it valuable to do so.
Camera Permissions
It is your responsibility to check for and, if necessary, request camera permissions. This can be done in the Activity (or Fragment) containing this View, or in a prior Activity. In either case, once you have verified that the user has granted permission to use the camera, you should make a call to onPermissionsGranted()
, which takes no parameters. We will not attempt to start up any camera functionality prior to being told that permissions were granted.
Lifecycle Callbacks
We finally depend on your notifying us of certain Activity (or Fragment) lifecycle events. This is largely for resource management reasons. In your onResume()
, onPause()
, and onDestroy()
functions you must make a call into our function of the exact same name with no arguments. We will not start up our preview until we have been informed that onResume()
has been called.
Additional Important Considerations
When adding credit card scanning to your app, you are asking your users to point their phone camera at their credit cards. You should be sure to reduce their risk by prohibiting screenshots in your Activity by marking the window as secure. This is done by setting FLAG_SECURE
on the window. For example:
This should be done prior to calling setContentView()
.
Do not forget to set this flag; without it the preview may be shown on non-secure screens and the contents may be captured.
Getting Card Number and Expiration Date Locations
We provide an overlay that fades in with the card number and expiration date that is disabled by default. It will use the most recent bounding boxes that we have in order to place the overlaid card number and expiration date approximately over where they appear on the card. Additionally, the time it takes for the details to fade in is configurable. If you wanted the details to fade in over the course of a second, you could use this layout:
If you have more customized behavior in mind, you can instead use the bounding boxes we return in the CreditCard
class upon success. They are provided as Rect
s and can be accessed with card.cardNumberBoundingBox
and card.dateBoundingBox
. They are provided as bounding boxes using the DyScanView's coordinate system, so you will likely have to convert them to another coordinate system prior to use. Specifically, the View's coordinate system is a graphics coordinate system, where the origin is in the upper left corner, the x axis increases to the right, the y axis increases down the screen, and each dimension is measured in pixels.
Customizing the Layout
There are myriad attributes that can be set on the DyScanView in order to customize its appearance and behavior. You must have added the dyneti
namespace as mentioned at the top of this page in order to use the custom attributes we provide.
Attribute
Description
Default Value
showCorners
Whether to show the scan area outline.
true
cornerThickness
How thick to make the lines outlining the scan area, indicating to the user where to place their credit card.
15f
cornerInactiveColor
The color to use in drawing the outline of the scan region when nothing of interest is detected.
Color.GRAY
cornerActiveColor
The color to use in drawing the outline of the scan region when corners are detected.
Color.CYAN
cornerCompletedColor
The color to use in drawing the outline of the scan region when we have successfully scanned a card.
Color.GREEN
roundCorners
Whether the scan region has round corners resembling the credit-card outline. If set to false, the scan region becomes a rectangle.
true
expandCorners
Whether to show the corners expanded outward with respect to the scan frame.
false
chopCorners
Whether to show the corners with limited length instead of having them expand all the way until they intersect.
false
bgColor
The color to use to obscure everything outside the scan region in order to draw the user’s attention to the scan region.
Color.GRAY
bgOpacity
The opacity to use when obscuring everything outside the scan region, as an integer ranging from 0 (transparent) to 255 (opaque).
115
showResultOverlay
Whether to briefly show the scanned card number (and date, if present) as an overlay over the screen after a successful scan.
false
showDynetiLogo
Whether to show the Dyneti logo and wordmark above the scan region.
true
resultOverlayAnimationMs
How long to spend animating a fade-in of the detected card number and date, in milliseconds.
1000
resultOverlayAlwaysHorizontal
Whether to display number on completion horizontally in fixed position.
false
showCardOverlay
Whether to show the overlay displaying a sample card number and expiration date hinting at the user to place their card in the scan region.
true
cardOverlayColor
The color to use in displaying the card overlay.
Color.WHITE
cardOverlayOpacity
The opacity to use in displaying the card overlay.
0.4f
cardOverlayNumber
The String to use as the credit card number displayed in the card overlay. Note that the text will be scaled to fit a region in the display, which may have strange results if the String is too long or too short.
"4242 4242 4242 4242"
cardOverlayDate
The String to use as the expiration date displayed in the card overlay. Note that the text will be scaled to fit a region in the display, which may have strange results if the String is too long or too short.
"11/11"
lightTorchWhenDark
Whether the phone will turn on the flashlight if multiple frames have appeared to be too dark. If set to false, torch toggle button will appear.
true
vibrateOnCompletion
Whether the device will vibrate once it has successfully extracted the credit card data from the images provided by the camera.
true
cardFrameContentDescription
The content description of card scan frame.
"Align your card to this frame"
isChallenge
Whether DyScanView is being used as a fraud check. This is currently only used for logging purposes, but in the future may impact behavior.
false
Additionally, there are some public functions you can use to easily add buttons with additional functionality to your scan screen. These are described below:
Public functions
Name
Description
setVertical(boolean)
Sets scan region orientation
true - vertical card
false - horizontal card
isVertical()
Returns a boolean whether scan region is set to vertical card orientation (true when vertical)
setTorchEnabled(boolean)
Turns torch on or off
isTorchEnabled()
Returns a boolean whether torch is currently turned on (true when torch is on)
setSidewaysScanningEnabled(boolean)
Whether to allow cards to scan in sideways orientation. If set to true, vertical cards will be able to be scanned when positioned in the horizontal scan window. Note that enableSidewaysScanning and showRotateButton should not simultaneously be set to true when using the view controller, and that isVertical should not be used when enableSidewaysScanning is set to true when using DyScan as a view.
setDetectWrongCard(boolean)
Whether to detect when the end-user is scanning the wrong card (when using DyScan for verification). If set to true and the string parameters expectedBIN
and expectedLastFourDigits
(which correspond to the first six and last four digits of the expected credit card number) are provided, when the end user attempts to scan the wrong card, the onProgressUpdate
callback returns a boolean numberMismatch
with true value (which can be used to signal the end user that they are not scanning the expected card) and the scan continues. Upon scanning the expected card, the scan completes.
setPromptIfFewDigits(boolean)
setOverlayText(String)
Can be used to set custom overlay text to assist users.
setOverlayTextFont(int)
The resource identifier of the font you wish to use.
setOverlayTextColor(int)
The color int for the overlay text.
setOverlayTextFontSize(float)
The font size in points for the overlay text.
setGiftCardMode(boolean)
When the boolean
passed in is true, enables gift card scanning mode. In this mode the scan will look exclusively for gift cards matching a configuration set by setGiftCardConfig
(see below).
setGiftCardConfig(string)
A String
provided by Dyneti for your gift card format.
Troubleshooting
Below we have explanations of the solutions to the most common situations where the DyScanView is not working as expected. Look for the issue you're having below.
The app crashes
This happens when the result listener has not been set and our code wants to return a result. If the result listener is not set, there is no point in running our code since your code will not be able to receive the results we provide. We don't prevent the crash so that this issue is caught quickly. The solution is to add the result listener; see the section on listening for a result for details on how to add the listener.
onFailure() is called unexpectedly
This happens when we are not able to scan a card. This may happen for reasons such as another app still having possession of the camera, the auth check on the API key indicating the key is invalid, or the system telling us that the user has not granted camera permissions. You should look at the integer argument provided in order to get more details on what is happening and how to resolve the issue; a table explaining them is present in the section on listening for a result.
No preview shows up
There are three reasons that the preview may not show up in your activity despite the DyScanView taking up space in the layout. In each case it is a missing call on our View; check that you are making all 3 calls and add any that may be missing. The first is that you need to set the API key. The second is that you need to inform us that camera permissions have been granted. And finally, our View needs to be lifecycle-aware, and so depends on you forwarding us lifecycle events.
Something else
Reach out to us on the communication channel we already have open. We're happy to get to the bottom of this issue together.
Last updated