Implementation guide
Before starting implementation you should have finished Installation of the MCD SDK.
Main Interface
Main interface of MCD SDK is com.meawallet.mcd.MeaCardData
. All methods are static
and can be used directly without object instance.
com.meawallet.mcd.MeaCardData.Configuration
is a class that provides access to the main configuration values of MCD SDK such as Version Code
, Version Name
and Build Type
.
Easy Launch Widget is a native Android UI element that wraps around SDK functionality and exposes API for styling appearance and interacting with a user. With the Easy Launch widget, you can omit some of the SDK implementation steps and data management tasks and more rapidly get a visual card-like representation of data visible to the user.
Initialize
To begin Issuer app should initialize MeaCardData
instance.
if (!MeaCardData.isInitialized()) {
MeaCardData.initialize(this);
}
Easy Launch Card View
Add Widget To View Hierarchy
EasyLaunchCardView
is the main class of Easy Launch Widget. Add it to your view hierachy and reference in the Fragment or Activty.
...
<com.meawallet.mcd.EasyLaunchCardView
android:id="@+id/easy_launch_widget"
android:elevation="4dp"
android:layout_width="match_parent"
android:layout_height="220dp"/>
...
public class CardActivity extends AppCompatActivity {
...
private EasyLaunchCardView mMeaCard;
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_card);
...
mMeaCard = findViewById(R.id.easy_launch_widget);
...
}
...
}
Card Identity Provider
Two input parameters are required to retrieve card data:
cardId
- Card ID.cardSecret
- Secret generated on app backend, see Time-based Secret (TOTP) Generation.
Easy Launch Widget doesn't store cardId
or cardSecret
at any given moment. It uses McdCardIdentityProvider
interface for acquiring data when needed. Implement the interface and provide it to EasyLaunchCardView
instance
using setCardIdentityProvider(McdCardIdentityProvider)
method.
McdCardIdentityProvider
provides async and sync interface for passing generated card secret:
- synchronous
- asynchronous
McdCardIdentityProvider identityProvider = new McdCardIdentityProvider() {
@Override
public String getCardId() {
return cardId; // cardId provided by banking app backend.
}
@Override
public String getSecret() {
return cardSecret; // cardSecret generated and provided by banking app backend.
}
};
mMeaCard.setCardIdentityProvider(identityProvider);
McdCardIdentityProvider identityProvider = new McdCardIdentityProvider() {
@Override
public String getCardId() {
return cardId; // cardId provided by banking app backend.
}
@Override
public void getSecret(McdSecretListener secretListener) {
secretListener.setSecret(cardSecret); // cardSecret generated and provided by banking app backend.
}
};
mMeaCard.setCardIdentityProvider(identityProvider);
Default Appearance And Behaviour
By completing the steps above, you have implemented the bare minimum of Easy Launch Widget and have it with default appearance and behavior.
Default behavior:
on click
- Show card data. If card data is not retrieved, it is retrieved first. The secondclick
hides card data.on long click
- Copy card PAN to clipboard, if card data is retrieved.- Menu button on the top right corner for accessing more actions -
Show / Hide
,Copy PAN
,Copy Name
,Copy Expiry
,Copy CVV
. - Shows toast message when any of card data is copied to clipboard.
- All texts are in English.
- Default colors are used for card background, texts, and loading indicators.
The Easy Launch Widget takes care of disposing of retrieved data after 60 seconds. The widget also maintains a proper plastic-card-like aspect ratio. It fills maximum available space within given boundaries. The rest of the assigned area is filled with transparent background.
The widget doesn't observe the lifecycles of Android components. According to Functional Requirements and Guidelines
the application developer has to take care of user authentification and handling data hiding/disposal when a user leaves a screen or application. Use EasyLaunchCardView
methods hideCardData()
and disposeCardData()
when necessary.
Card View Customization
Use XML layout attributes and runtime methods to customize EasyLaunchCardView
. Add translations for text values, add onClick
and onLongClick
listeners to get action result callbacks.
Card background, fonts, text and loading indicator colors, touch and card data loading events can be customized and handled. For more UI customization details refer to Card Custom Layout.
See MCD SDK Android API Reference for more details.
Customization with XML Layout
...
<com.meawallet.mcd.EasyLaunchCardView
android:id="@+id/easy_launch_widget_customized"
android:elevation="4dp"
app:mcdDefaultListenersEnabled="false"
app:mcdTextColor="@android:color/holo_purple"
app:mcdCardBackground="@drawable/creditcard_background"
app:mcdShowCardMenuTitle="@string/easylaunch_menu_show_card"
app:mcdPanCopyInfoText="PAN is cool!"
android:layout_width="150dp"
android:layout_height="130dp"/>
...
Available XML attributes
Attribute | Format | Description |
---|---|---|
app:mcdCardBackground | reference|color | Card background |
app:mcdTextColor | reference|color | Text and symbol color |
app:mcdFontSize | reference|float | Font size |
app:mcdFont | reference | Reference to the Font resource |
app:mcdLayout | reference | Reference to the XML Layout resource |
app:mcdInfoToastsEnabled | boolean | Enable/Disable info toasts on card data copy |
app:mcdPanCopyInfoText | reference|string | Toast message text |
app:mcdHolderNameCopyInfoText | reference|string | Toast message text |
app:mcdValidThruCopyInfoText | reference|string | Toast message text |
app:mcdCvvCopyInfoText | reference|string | Toast message text |
app:mcdDefaultMenuEnabled | boolean | Enable/Disable menu on top-right corner |
app:mcdPanCopyMenuTitle | reference|string | Menu entry text |
app:mcdHolderNameCopyMenuTitle | reference|string | Menu entry text |
app:mcdValidThruCopyMenuTitle | reference|string | Menu entry text |
app:mcdCvvCopyMenuTitle | reference|string | Menu entry text |
app:mcdShowCardMenuTitle | reference|string | Menu entry text |
app:mcdHideCardMenuTitle | reference|string | Menu entry text |
app:mcdDefaultListenersEnabled | boolean | Enable/Disable default click and long click listeners |
app:mcdLoadingIndicatorEnabled | boolean | Enable/Disable default loading indicator |
app:mcdLoadingIndicatorColor | reference|color | Loading indicator color |
Customization with Code
...
mMeaCardCustomized.setTextColor( colorInteger );
mMeaCardCustomized.setValidThruCopyMenuTitle("Copy expiry right now!");
mMeaCardCustomized.setInfoToastsEnabled(false); // disables for example info toast after PAN copied
mMeaCardCustomized.setOnCardClickListener(v -> {
EasyLaunchCardView cardWidget = (EasyLaunchCardView) v;
// Get card data and keep track of result calbacks
cardWidget.showCardData(new McdEasyLaunchListener() {
@Override
public void onSuccess() {
// card data is displayed on widget
}
@Override
public void onFailure(@NonNull McdError mcdError) {
...
}
});
});
mMeaCardCustomized.setOnCardLongClickListener(v -> {
EasyLaunchCardView cardWidget = (EasyLaunchCardView) v;
cardWidget.setCardBackground(ContextCompat.getDrawable(CardActivity.this, R.drawable.card_background));
cardWidget.setTextColor(Color.WHITE);
cardWidget.setFont(R.font.custom_font);
cardWidget.setFontSize(12.5f);
return true;
});
...
Custom Card Layout
Android XML Layout could be used as template for Card View by setting app:mcdLayout
attribute.
At run time custom layout's TextView elements with the following tags are used as placeholders for actual card data:
android:tag | Description |
---|---|
pan | PAN |
expiry | Expiry date in MM/YY format |
name | Name embossed on the card |
cvv | CVV |
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="405dp"
android:layout_height="255dp">
<TextView
android:tag="pan"
android:id="@+id/pan"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textSize="24dp"
android:text="1234 5678 9012 3456" />
<TextView
android:tag="expiry"
android:layout_below="@id/pan"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="11/25" />
<TextView
android:tag="name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_margin="16dp"
android:textSize="24dp"
android:text="Cardholder Name" />
<TextView
android:tag="cvv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_margin="16dp"
android:text="123" />
</RelativeLayout>
Custom Card layout overrides default layout, thus app:mcdFont
and app:mcdFontSize
attributes are ignored.
Card Data Loading Events
EasyLaunchCardView
widget provides methods to set listeners for card data loading events.
- Loading started:
setOnCardDataLoadingStartedListener(listener)
mEasyLaunchCardView.setOnCardDataLoadingStartedListener(() -> {
Log.d(TAG, "Card data loading started");
// ...
});
- Loading completed or loading failed:
setOnCardDataLoadingCompletedListener(listener)
mEasyLaunchCardView.setOnCardDataLoadingCompletedListener(new McdEasyLaunchListener() {
@Override
public void onSuccess() {
Log.d(TAG, "Card data loaded");
}
@Override
public void onFailure(@NonNull McdError mcdError) {
Log.d(TAG, "Card data loading failed: " + mcdError);
}
});
- Card data cleared:
setOnCardDataClearedListener(listener)
mEasyLaunchCardView.setOnCardDataClearedListener(() -> {
Log.d(TAG, "Card data cleared");
//...
});
Get Card Data Images
Two input parameters are required to retrieve card data images:
cardId
- Card ID of the card.secret
- Secret generated on backend, see Time-based Secret (TOTP) Generation.
Card data images can be retrieved with async and sync methods:
- asynchronous
- synchronous
Network request is executed on a background thread and result is returned on the main UI thread as a callback.
MeaCardData.getCardDataImages(cardId, secret, new McdGetCardDataImagesListener() {
@Override
public void onSuccess(@NonNull McdCardDataImages cardDataImages) {
try {
// Use retrieved data.
} catch (McdException e) {
// Handle error.
}
}
@Override
public void onFailure(@NonNull McdError mcdError) {
int errorCode = mcdError.getCode();
String errorMessage = mcdError.getMessage();
// Handle error.
}
});
Network request is executed on the same thread, cannot be used from the main UI thread.
try {
McdCardDataImages cardDataImages = MeaCardData.getCardDataImages(cardId, secret);
// Use retrieved data.
} catch (McdException exception) {
McdError mcdError = exception.getMcdError();
int errorCode = mcdError.getCode();
String errorMessage = mcdError.getMessage();
// Handle error.
}
Card Data Image Bitmaps
PAN, Expiry Date, Emboss Name and CVV can be exported as Bitmap
images:
// Default font, black color, size 10dp, default character spacing
Bitmap panImage = cardDataImages.getPanImage(Typeface.DEFAULT, Color.BLACK, 10.0f, 0.0f);
// Default monospace font, green color, size 8dp, default character spacing
Bitmap expiryImage = cardDataImages.getExpiryImage(Typeface.MONOSPACE, Color.GREEN, 8.0f, 0.0f);
// Sans Serif Bold font, red color, size 12dp, negative character spacing: condensed text
Bitmap embossNameImage = cardDataImages.getEmbossNameImage(Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD), Color.RED, 12f, -0.05f);
// Custom font loaded from resources, green color, size 20dp, positive character spacing - text is expanded
Bitmap cvvImage = cardDataImages.getCvvImage(getFont(context, R.font.custom_font_name), Color.GREEN, 20f, 0.1f);
Copying Card Data to Clipboard
PAN, Expiry Date, Emboss Name and CVV can be copied to clipboard:
// Copy PAN to clipboard.
cardDataImages.copyPanToClipboard();
// Copy Expiry Date to clipboard.
cardDataImages.copyExpiryToClipboard();
// Copy Emboss Name to clipboard.
cardDataImages.copyEmbossNameToClipboard();
// Copy CVV to clipboard.
cardDataImages.copyCvvToClipboard();
Card Data Cleared Event
MeaCardDataImages
object provides method to set listener for card data cleared event:
cardDataImages.setOnCardDataClearedListener(() -> {
// Handle data wipe event, e.g. clear or hide card data images
});
Card PIN Management
Get Card PIN Image Data
Two input parameters are required to retrieve Card PIN Data:
cardId
- Card ID.secret
- Secret generated on backend, see Time-based Secret (TOTP) Generation.
Card PIN Image Data can be retrieved in two ways:
- asynchronous
- synchronous
Network request is executed on a background thread and result is returned on the main UI thread as a callback.
@Override
MeaCardData.getCardPinImage(cardId, secret, new McdGetCardPinImageListener() {
@Override
public void onSuccess(@NonNull McdCardPinImage cardPinImage) {
// Use retrieved card PIN data.
}
@Override
public void onFailure(@NonNull McdError mcdError) {
// Handle error.
}
});
Network request is executed on the same thread, cannot be used from the main UI thread.
try {
McdCardPinImage cardPinImage = MeaCardData.getCardPinImage(cardId, secret);
// Use retrieved data.
} catch (McdException exception) {
// Handle error.
}
Card PIN Image Bitmap
Card PIN can be exported as Bitmap
Image:
// Default font, black color, size 10dp, default character spacing
Bitmap pinImage = cardPinImage.getPinImage(Typeface.DEFAULT, Color.BLACK, 10.0f, 0.0f);
Copying PIN to Clipboard
Card PIN can be copied to clipboard:
cardDataImages.copyEmbossNameToClipboard();
Data Cleared Event
MeaCardPinImage
object provides method to set listener for data cleared event:
cardPinImage.setOnCardPinClearedListener(() -> {
// Handle data wipe event, e.g. clear or hide PIN
});
Set Card PIN
Four input parameters are required to set Card PIN:
cardId
- Card ID.secret
- Secret generated on backend, see Time-based Secret (TOTP) Generation.oldPin
- Old PIN value.newPin
- New PIN value.
Card PIN can be set in two ways:
- asynchronous
- synchronous
Network request is executed on a background thread and result is returned on the main UI thread as a callback.
MeaCardData.setCardPin(cardId, secret, oldPin, newPin, new McdSetCardPinListener() {
@Override
public void onSuccess(boolean isPinSet) {
// PIN successfully set.
}
@Override
public void onFailure(@NonNull McdError mcdError) {
// Handle error.
}
});
Network request is executed on the same thread, cannot be used from the main UI thread.
try {
boolean isPinSet = MeaCardData.setCardPin(cardId, secret, oldPin, newPin);
} catch (McdException exception) {
// Handle error.
}
Unblock Card PIN
Two input parameters are required to unblock Card PIN:
cardId
- Card ID.secret
- Secret generated on backend, see Time-based Secret (TOTP) Generation.
Card PIN can be unblocked in two ways:
- asynchronous
- synchronous
Network request is executed on a background thread and result is returned on the main UI thread as a callback.
MeaCardData.unblockCardPin(cardId, secret, new McdUnblockCardPinListener() {
@Override
public void onSuccess(boolean isPinUnblocked) {
// PIN successfully unblocked.
}
@Override
public void onFailure(@NonNull McdError mcdError) {
// Handle error.
}
});
Network request is executed on the same thread, cannot be used from the main UI thread.
try {
boolean isPinUnblocked = MeaCardData.unblockCardPin(cardId, secret);
} catch (McdException exception) {
// Handle error.
}
Get Card Data (Deprecated)
This method is deprecated. Use EasyLaunchCardView instead.
Two input parameters are required to retrieve card data:
cardId
- Card ID.secret
- Secret generated on backend, see Time-based Secret (TOTP) Generation.
Card data can be retrieved in two ways:
- asynchronous
- synchronous
Network request is executed on a background thread and result is returned on the main UI thread as a callback.
MeaCardData.getCardData(cardId, secret, new McdGetCardDataListener() {
@Override
public void onSuccess(@NonNull McdCardData mcdCardData) {
String cardPan = mcdCardData.getPan();
String cardCvv = mcdCardData.getCvv();
// Use retrieved data.
}
@Override
public void onFailure(@NonNull McdError mcdError) {
int errorCode = mcdError.getCode();
String errorMessage = mcdError.getMessage();
// Handle error.
}
});
Network request is executed on the same thread, cannot be used from the main UI thread.
McdCardData mcdCardData;
try {
mcdCardData = MeaCardData.getCardData(cardId, secret);
}
catch (McdException exception) {
McdError mcdError = exception.getMcdError();
int errorCode = mcdError.getCode();
String errorMessage = mcdError.getMessage();
// Handle error.
}
String cardPan = mcdCardData.getPan();
String cardCvv = mcdCardData.getCvv();
// Use retrieved data.
Error Handling
McdError
is a generic MCD SDK error object containing all error info (error code, error name, error message and request ID). McdError
can be returned with onFailure
callback or gathered from McdException
object.
Debugging
Use dependency with -debug
suffix to enable MeaCardData
debugging and logging. See Gradle Configuration.