Updated on 2026-08-14

This commit is contained in:
Tangem 2020-04-21 08:36:10 +03:00
parent 99c8d24f7c
commit 9daf982e41
5 changed files with 392 additions and 137 deletions

View file

@ -20,7 +20,7 @@ interface CardSessionRunnable<T : CommandResponse> {
/**
* The starting point for custom business logic.
* Implement this interface and use [TangemSdk.startSession] to run.
* Implement this interface and use [TangemSdk.startSessionWithRunnable] to run.
* @param session run commands in this [CardSession].
* @param callback trigger the callback to complete the task.
*/

View file

@ -49,7 +49,7 @@ class TangemSdk(
* in the form of [Card] if the task was performed successfully or [SessionError] in case of an error.
*/
fun scanCard(initialMessage: Message? = null, callback: (result: CompletionResult<Card>) -> Unit) {
startSession(ScanTask(), null, initialMessage, callback)
startSessionWithRunnable(ScanTask(), null, initialMessage, callback)
}
/**
@ -72,7 +72,7 @@ class TangemSdk(
*/
fun sign(hashes: Array<ByteArray>, cardId: String, initialMessage: Message? = null,
callback: (result: CompletionResult<SignResponse>) -> Unit) {
startSession(SignCommand(hashes), cardId, initialMessage, callback)
startSessionWithRunnable(SignCommand(hashes), cardId, initialMessage, callback)
}
/**
@ -90,7 +90,7 @@ class TangemSdk(
*/
fun readIssuerData(cardId: String, initialMessage: Message? = null,
callback: (result: CompletionResult<ReadIssuerDataResponse>) -> Unit) {
startSession(ReadIssuerDataCommand(config.issuerPublicKey), cardId, initialMessage, callback)
startSessionWithRunnable(ReadIssuerDataCommand(config.issuerPublicKey), cardId, initialMessage, callback)
}
/**
@ -109,7 +109,7 @@ class TangemSdk(
*/
fun readIssuerExtraData(cardId: String,
callback: (result: CompletionResult<ReadIssuerExtraDataResponse>) -> Unit) {
startSession(ReadIssuerExtraDataCommand(config.issuerPublicKey), cardId, null, callback)
startSessionWithRunnable(ReadIssuerExtraDataCommand(config.issuerPublicKey), cardId, null, callback)
}
/**
@ -140,7 +140,7 @@ class TangemSdk(
issuerDataCounter,
config.issuerPublicKey
)
startSession(command, cardId, initialMessage, callback)
startSessionWithRunnable(command, cardId, initialMessage, callback)
}
/**
@ -179,7 +179,7 @@ class TangemSdk(
issuerDataCounter,
config.issuerPublicKey
)
startSession(command, cardId, initialMessage, callback)
startSessionWithRunnable(command, cardId, initialMessage, callback)
}
/**
@ -206,7 +206,7 @@ class TangemSdk(
callback: (result: CompletionResult<WriteUserDataResponse>) -> Unit
) {
val command = WriteUserDataCommand(userData, userProtectedData, userCounter, userProtectedCounter)
startSession(command, cardId, initialMessage, callback)
startSessionWithRunnable(command, cardId, initialMessage, callback)
}
/**
@ -228,7 +228,7 @@ class TangemSdk(
*/
fun readUserData(cardId: String, initialMessage: Message? = null,
callback: (result: CompletionResult<ReadUserDataResponse>) -> Unit) {
startSession(ReadUserDataCommand(), cardId, initialMessage, callback)
startSessionWithRunnable(ReadUserDataCommand(), cardId, initialMessage, callback)
}
/**
@ -250,7 +250,7 @@ class TangemSdk(
*/
fun createWallet(cardId: String, initialMessage: Message? = null,
callback: (result: CompletionResult<CreateWalletResponse>) -> Unit) {
startSession(CreateWalletTask(), cardId, initialMessage, callback)
startSessionWithRunnable(CreateWalletTask(), cardId, initialMessage, callback)
}
/**
@ -269,7 +269,7 @@ class TangemSdk(
*/
fun purgeWallet(cardId: String, initialMessage: Message? = null,
callback: (result: CompletionResult<PurgeWalletResponse>) -> Unit) {
startSession(PurgeWalletCommand(), cardId, initialMessage, callback)
startSessionWithRunnable(PurgeWalletCommand(), cardId, initialMessage, callback)
}
/**
@ -287,7 +287,7 @@ class TangemSdk(
* */
fun depersonalize(cardId: String, initialMessage: Message? = null,
callback: (result: CompletionResult<DepersonalizeResponse>) -> Unit) {
startSession(DepersonalizeCommand(), cardId, initialMessage, callback)
startSessionWithRunnable(DepersonalizeCommand(), cardId, initialMessage, callback)
}
/**
@ -313,7 +313,7 @@ class TangemSdk(
initialMessage: Message? = null,
callback: (result: CompletionResult<Card>) -> Unit) {
val command = PersonalizeCommand(config, issuer, manufacturer, acquirer)
startSession(command, null, initialMessage, callback)
startSessionWithRunnable(command, null, initialMessage, callback)
}
/**
@ -330,7 +330,7 @@ class TangemSdk(
* If null, default message will be used.
* @callback: Standard [TangemSdk] callback.
*/
fun <T : CommandResponse> startSession(
fun <T : CommandResponse> startSessionWithRunnable(
runnable: CardSessionRunnable<T>, cardId: String? = null, initialMessage: Message? = null,
callback: (result: CompletionResult<T>) -> Unit) {
val cardSession = CardSession(buildEnvironment(), reader, viewDelegate, cardId, initialMessage)
@ -349,8 +349,7 @@ class TangemSdk(
* @callback: At first, you should check that the [SessionError] is not null,
* then you can use the [CardSession] to interact with a card.
*/
fun <T : CommandResponse> startSession(
cardId: String? = null, initialMessage: Message? = null,
fun startSession(cardId: String? = null, initialMessage: Message? = null,
callback: (session: CardSession, error: SessionError?) -> Unit) {
val cardSession = CardSession(buildEnvironment(), reader, viewDelegate, cardId, initialMessage)
Thread().run { cardSession.start(callback) }

View file

@ -0,0 +1,23 @@
version: 2.1
orbs:
android: circleci/android@0.2.0
jobs:
build:
executor: android/android
environment:
JVM_OPTS: -Xmx2048m
GRADLE_OPTS: -Xmx1536m -XX:+HeapDumpOnOutOfMemoryError -Dorg.gradle.caching=true -Dorg.gradle.configureondemand=true -Dkotlin.compiler.execution.strategy=in-process -Dkotlin.incremental=false
steps:
- checkout
- run:
name: Build
command: ./gradlew build
- run:
name: Run Tests
command: ./gradlew test
- store_test_results: # for display in Test Summary: https://circleci.com/docs/2.0/collect-test-data/
path: tangem-core/build/test-results/

View file

@ -1,5 +1,6 @@
![Release](https://jitpack.io/v/Tangem/tangem-sdk-android.svg)
[![Release](https://jitpack.io/v/Tangem/tangem-sdk-android.svg)](https://jitpack.io/#tangem/tangem-sdk-android)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![CircleCI](https://circleci.com/gh/Tangem/tangem-sdk-android.svg?style=shield)](https://circleci.com/gh/Tangem/tangem-sdk-android)
# Welcome to Tangem
The Tangem card is a self-custodial hardware wallet for blockchain assets. The main functions of Tangem cards are to securely create and store a private key from a blockchain wallet and sign blockchain transactions. The Tangem card does not allow users to import/export, backup/restore private keys, thereby guaranteeing that the wallet is unique and unclonable.
@ -12,10 +13,19 @@ The Tangem card is a self-custodial hardware wallet for blockchain assets. The m
- [Card interaction](#card-interaction)
- [Scan card](#scan-card)
- [Sign](#sign)
- [Read Issuer Data](#read-issuer-data)
- [Read Issuer Extra Data](#read-issuer-extra-data)
- [Write Issuer Data](#write-issuer-data)
- [Write Issuer Extra Data](#write-issuer-extra-data)
- [Write User Data](#write-user-data)
- [Read User Data](#read-user-data)
- [Create Wallet](#create-wallet)
- [Purge Wallet](#purge-wallet)
- [Depersonalize](#depersonalize)
- [Personalize](#personalize)
- [Customization](#customization)
- [UI](#ui)
- [Tasks](#tasks)
- [Localization](#localization)
- [Custom Tasks](#custom-tasks)
## Getting Started
@ -41,8 +51,8 @@ And add Tangem library to the dependencies (in an app or module build.gradle fil
```gradle
dependencies {
implementation "com.github.tangem.tangem-sdk-android:tangem-core:$latestVersionOfCore"
implementation "com.github.tangem.tangem-sdk-android:tangem-sdk:$latestVersionOfSdk"
implementation "com.github.tangem.tangem-sdk-android:tangem-core:$latestVersion"
implementation "com.github.tangem.tangem-sdk-android:tangem-sdk:$latestVersion"
}
```
Tangem Core is a JVM library (without Android dependencies) that provides core functionality of interacting with Tangem cards.
@ -75,155 +85,351 @@ Tangem Sdk is an Android library that implements NFC interaction between Android
Tangem SDK is a self-sufficient solution that implements a card abstraction model, methods of interaction with the card and interactions with the user via UI.
### Initialization
To get started, you need to create an instance of the `CardManager` class. It provides the simple way of interacting with the card.
Our default implementation of `CardManager` requires `NfcReader` and `DefaultCardManagerDelegate`.
To get started, you need to create an instance of the `TangemSdk` class. It provides the simple way of interacting with the card.
Our default implementation of `TangemSdk` comes with `NfcReader` and `DefaultSessionViewDelegate` and can be initialized with a static method
TangemSdk.init(activity: Activity).
```kotlin
private val nfcManager = NfcManager()
private val cardManagerDelegate: DefaultCardManagerDelegate = DefaultCardManagerDelegate(nfcManager.reader)
private val cardManager = CardManager(nfcManager.reader, cardManagerDelegate)
val tangemSdk: TangemSdk = TangemSdk.init(activity)
```
NfcManager requires a reference to activity in order to use Android API for interacting with NFC. DefaultCardManagerDelegate requires a reference to activity in order to render views.
TangemSdk requires a reference to activity in order to use Android API for interacting with NFC. DefaultSessionViewDelegate requires a reference to activity in order to render views.
```kotlin
nfcManager.setCurrentActivity(this)
cardManagerDelegate.activity = this
```
Default implementation of `TangemSdk` allows you to start using SDK in your application without any additional setup.
```kotlin
lifecycle.addObserver(NfcLifecycleObserver(nfcManager))
```
You can also provide your implementations of `CardReader` and `SessionViewDelegate`.
You can read more about this in [Customization](#customization).
Default implementation of `NfcManager`, `CardReader` and `CardManagerDelegate` allows you to start using CardManager in your application without any additional setup.
### Card interaction
You can also provide your implementations of `CardReader` and `CardManagerDelegate`.
You can read more about this in [Customization](#сustomization).
### Tasks
Tangem SDK provides a number of commands and tasks that can be run from a `TangemSdk` class.
#### Scan card
To start using any card, you first need to read it using the `scanCard()` method. This method launches an NFC session, and once its connected with the card, it obtains the card data. Optionally, if the card contains a wallet (private and public key pair), it proves that the wallet owns a private key that corresponds to a public one.
To start using any card, you first need to read it using the `scanCard()` method. This method launches an NFC session, and once its connected with the card, it obtains the card data. If the card contains a wallet (private and public key pair), it proves that the wallet owns a private key that corresponds to a public one.
Example:
```kotlin
cardManager.scanCard { taskEvent ->
when (taskEvent) {
is TaskEvent.Event<ScanEvent> -> {
when (taskEvent.data) {
is ScanEvent.OnReadEvent -> {
// Handle returned card data
cardId = (taskEvent.data as ScanEvent.OnReadEvent).card.cardId
// Switch to UI thread to show results in UI
runOnUiThread {}
}
is ScanEvent.OnVerifyEvent -> {
//Handle card verification
val isGenuine = (taskEvent.data as ScanEvent.OnVerifyEvent).isGenuine
tangemSdk.scanCard { result ->
when (result) {
is CompletionResult.Success -> {
// Handle returned card data
val card = result.data
cardId = card.cardId
// Switch to UI thread to show results in UI
runOnUiThread {
tv_card_cid?.text = cardId
}
}
is CompletionResult.Failure -> {
if (result.error is SessionError.UserCancelledError) {
// Handle case when user cancelled manually
}
// Handle other errors
}
}
}
}
is TaskEvent.Completion<ScanEvent> -> {
if (taskEvent.error != null) {
if (taskEvent.error is TaskError.UserCancelledError) {
// Handle case when user cancelled manually
}
// Handle other errors
}
// Handle completion
}
}
}
```
Communication with the card is an asynchronous operation. In order to get a result for the method, you need to subscribe to the task callback. In order to render the callback results on UI, you need to switch to the main thread.
Every task can invoke callback several times with different events:
Every `CardSessionRunnable` (`Command` or custom tasks) can invoke callback once with either success or error:
`Completion<T>(val error: TaskError? = null)` this event is triggered only once when task is completely finished. It means that it's the final callback. If error is not nil, then something went wrong during the operation.
`CompletionResult<T>` this is the sealed class for the results of `CardSessionRunnable`.
`Event<T>(val data: T)` this event is triggered when one of operations inside the task is completed.
**Possible events of the Scan card task:**
`OnReadEvent(val result: Card)` this event is triggered after the card has been successfully read. In addition, the obtained card object is contained inside the enum. At this stage, the authenticity of the card is ***NOT*** verified.
`OnVerifyEvent(val isGenuine: Boolean)` this event is triggered when the cards authenticity has been verified. If the card is authentic, isGenuine will be set to true, otherwise, it will be set to false.
`Success<T>(val data: T)` is triggered after successful operation and contains a `CommandResponse`.
`Failure<T>(val error: SessionError)` is triggered on error.
#### Sign
This method allows you to sign one or multiple hashes. Simultaneous signing of array of hashes in a single SIGN command is required to support Bitcoin-type multi-input blockchains (UTXO). The SIGN command will return a corresponding array of signatures.
```kotlin
cardManager.sign(
hashes = arrayOf(hash1, hash2),
cardId = card.cardId) { taskEvent ->
when (taskEvent) {
is TaskEvent.Event -> {
// Handle sign response data
val signResponse = taskEvent.data
}
is TaskEvent.Completion<ScanEvent> -> {
if (taskEvent.error != null) {
if (taskEvent.error is TaskError.UserCancelledError) {
// Handle case when user cancelled manually
tangemSdk.sign(
hashes = arrayOf(hash1, hash2),
cardId) { result ->
when (result) {
is CompletionResult.Failure -> {
if (result.error is SessionError.UserCancelledError) {
// Handle case when user cancelled manually
}
// Handle other errors
}
is CompletionResult.Success -> {
val signResponse = result.data
}
// Handle other errors
}
// Handle completion
}
}
}
```
#### Read Issuer Data
An example of usage (description is available at documentation for `TangemSdk.readIssuerData` method and corresponding command class):
```kotlin
tangemSdk.readIssuerData(cardId) { result ->
when (result) {
is CompletionResult.Failure -> {
if (result.error is SessionError.UserCancelledError) {
// Handle case when user cancelled manually
}
// Handle other errors
}
is CompletionResult.Success -> {
val issuerData = result.data.issuerData
val issuerDataSignature = result.data.issuerDataSignature
}
}
}
```
#### Read Issuer Extra Data
An example of usage (description is available at documentation for `TangemSdk.readIssuerExtraData` method and corresponding command class):
```kotlin
tangemSdk.readIssuerExtraData(cardId) { result ->
when (result) {
is CompletionResult.Failure -> {
if (result.error is SessionError.UserCancelledError) {
// Handle case when user cancelled manually
}
// Handle other errors
}
is CompletionResult.Success -> {
val issuerData = result.data.issuerData
val issuerDataSignature = result.data.issuerDataSignature
}
}
}
```
#### Write Issuer Data
An example of usage (description is available at documentation for `TangemSdk.writeIssuerData` method and corresponding command class):
```kotlin
tangemSdk.writeIssuerData(cardId, issuerData, issuerDataSignature, issuerDataCounter) { result ->
when (result) {
is CompletionResult.Failure -> {
if (result.error is SessionError.UserCancelledError) {
// Handle case when user cancelled manually
}
// Handle other errors
}
is CompletionResult.Success -> {
val writeIssuerDataResult = result.data
}
}
}
```
#### Write Issuer Extra Data
An example of usage (description is available at documentation for `TangemSdk.writeIssuerExtraData` method and corresponding command class):
```kotlin
tangemSdk.writeIssuerExtraData(cardId,
issuerData, startingSignature, finalizingSignature, issuerDataCounter
) { result ->
when (result) {
is CompletionResult.Failure -> {
if (result.error is SessionError.UserCancelledError) {
// Handle case when user cancelled manually
}
// Handle other errors
}
is CompletionResult.Success -> runOnUiThread {
val writeIssuerDataResult = result.data
}
}
}
```
#### Write User Data
An example of usage (description is available at documentation for `TangemSdk.writeUserData` method and corresponding command class):
```kotlin
tangemSdk.writeUserData(
cardId, userData, userProtectedData, userCounter, userProtectedCounter
) { result ->
when (result) {
is CompletionResult.Failure -> {
if (result.error is SessionError.UserCancelledError) {
// Handle case when user cancelled manually
}
// Handle other errors
}
is CompletionResult.Success -> runOnUiThread {
val writeUserDataResult = result.data
}
}
}
```
#### Read User Data
An example of usage (description is available at documentation for `TangemSdk.readUserData` method and corresponding command class):
```kotlin
tangemSdk.readUserData(cardId) { result ->
when (result) {
is CompletionResult.Failure -> {
if (result.error is SessionError.UserCancelledError) {
// Handle case when user cancelled manually
}
// Handle other errors
}
is CompletionResult.Success -> runOnUiThread {
val readUserDataResult = result.data
}
}
}
```
#### Create Wallet
An example of usage (description is available at documentation for `TangemSdk.createWallet` method and corresponding command class):
```kotlin
tangemSdk.createWallet(cardId) { result ->
when (result) {
is CompletionResult.Failure -> {
if (result.error is SessionError.UserCancelledError) {
// Handle case when user cancelled manually
}
// Handle other errors
}
is CompletionResult.Success -> runOnUiThread {
val createWalletResult = result.data
}
}
}
```
#### Purge Wallet
An example of usage (description is available at documentation for `TangemSdk.purgeWallet` method and corresponding command class):
```kotlin
tangemSdk.purgeWallet(cardId) { result ->
when (result) {
is CompletionResult.Failure -> {
if (result.error is SessionError.UserCancelledError) {
// Handle case when user cancelled manually
}
// Handle other errors
}
is CompletionResult.Success -> runOnUiThread {
val purgeWalletResult = result.data
}
}
}
```
#### Depersonalize
An example of usage (description is available at documentation for `TangemSdk.depersonalize` method and corresponding command class):
```kotlin
tangemSdk.depersonalize(cardId) { result ->
when (result) {
is CompletionResult.Failure -> {
if (result.error is SessionError.UserCancelledError) {
// Handle case when user cancelled manually
}
// Handle other errors
}
is CompletionResult.Success -> runOnUiThread {
val depersonalizeResult = result.data
}
}
}
```
#### Personalize
An example of usage (description is available at documentation for `TangemSdk.personalize` method and corresponding command class):
```kotlin
tangemSdk.personalize(config, issuer, manufacturer, acquirer) { result ->
when (result) {
is CompletionResult.Failure -> {
if (result.error is SessionError.UserCancelledError) {
// Handle case when user cancelled manually
}
// Handle other errors
}
is CompletionResult.Success -> runOnUiThread {
val card = result.data
}
}
}
```
## Customization
### UI
If the interaction with user is required, the SDK performs the entire cycle of this interaction. In order to change the appearance or behavior of the user UI, you can provide you own implementation of the `CardManagerDelegate` inteface. After this, initialize the `CardManager` class with your delegate class.
If the interaction with user is required, the SDK performs the entire cycle of this interaction. In order to change the appearance or behavior of the user UI, you can provide you own implementation of the `SessionViewDelegate` inteface. After this, initialize the `TangemSdk` class with your delegate class.
```kolin
val myCardManagerDelegate = MyCardManagerDelegate()
val cardManager = CardManager(cardManagerDelegate = myCardManagerDelegate)
val tangemSdk = TangemSdk.customInit(this, viewDelegate = MySessionViewDelegate())
```
> If you pass null instead of `cardManagerDelegate`, the SDK wont be able to process errors that require user intervention and return them to `.failure(let error)`.
### Custom Tasks
`TangemSdk` specific methods run particular commands and tasks. If you want to trigger card commands in a different order, or implement additional
business logic, you have several options.
One option is to start a session, get an instance of `CardSession`, and use it to perform commands.
To do this, you need to call `tangemSdk.startSession()` method and get a `CardSession` instance in a callback.
### Tasks
`CardManager` only covers general tasks. If you want to trigger card commands in a certain order, you need to create your own task.
To do this, you need to create a subclass of the `Task` class, and override the `onRun(..)` method.
Then call the `runTask(..)` method of the `CardManager` class with you task.
> For example, if you want to read the card and immediately sign a transaction with it, you can achieve it this way.
```kotlin
val task = YourTask()
cardManager.runTask(task) { taskEvent ->
// Handle your events
}
```
> For example, you want to read the card and immediately sign a transaction on it. In such a case, you need to inherit from the `Task` class and override the `onRun(..)` method, in which you implement the required behavior.
Its possible to run just one command without the need to create a separate task by using the `runCommand(..)` method.
> For example, if you need to read the card details, but dont need to check the authenticity.
```kotlin
// Create command
val readCommand = ReadCardCommand()
// Run command with the callback
cardManager.runCommand(readCommand) { taskEvent ->
when (taskEvent) {
is TaskEvent.Event -> {
// Handle returned card data
val card: Card = taskEvent.data
}
is TaskEvent.Completion -> {
if (taskEvent.error != null) {
if (taskEvent.error is TaskError.UserCancelledError) {
// Handle case when user cancelled manually
tangemSdk.startSession { session, error ->
if (error == null) {
session.startWithRunnable(
SignCommand(createSampleHashes())) {result ->
when (result) {
is CompletionResult.Failure -> {
if (result.error is SessionError.UserCancelledError) {
// Handle case when user cancelled manually
}
// Handle other errors
}
is CompletionResult.Success -> {
val signResponse = result.data
}
}
}
}
}
```
Another option is to put all logic in a in `CardSessionRunnable` class and launch it using `tangemSdk.startSessionWithRunnable()` method.
In Tangem SDK we use this approach for our `ScanTask`.
> For example, you want to read the card and immediately sign a transaction with it. With subclassing `CardSessionRunnable` you can achieve it this way.
```kotlin
class OneTapSignTask(private val hashesToSign: Array<ByteArray>) : CardSessionRunnable<Card> {
override fun run(session: CardSession, callback: (result: CompletionResult<Card>) -> Unit) {
val card = session.environment.card
if (card == null) {
callback(CompletionResult.Failure(SessionError.MissingPreflightRead()))
} else if (card.cardData?.productMask?.contains(Product.Tag) != false) {
callback(CompletionResult.Success(card))
} else if (card.status != CardStatus.Loaded) {
callback(CompletionResult.Success(card))
} else if (card.curve == null || card.walletPublicKey == null) {
callback(CompletionResult.Failure(SessionError.CardError()))
} else {
val signCommand = SignCommand(hashesToSign)
signCommand.run(session) { result ->
when (result) {
is CompletionResult.Success -> callback(CompletionResult.Success(result.data))
is CompletionResult.Failure -> callback(CompletionResult.Failure(result.error))
}
// Handle other errors
}
// Handle completion
}
}
}

View file

@ -1,21 +1,48 @@
package com.tangem.tangem_sdk_new.extensions
import androidx.fragment.app.FragmentActivity
import com.tangem.CardReader
import com.tangem.Config
import com.tangem.SessionViewDelegate
import com.tangem.TangemSdk
import com.tangem.tangem_sdk_new.DefaultSessionViewDelegate
import com.tangem.tangem_sdk_new.NfcLifecycleObserver
import com.tangem.tangem_sdk_new.TerminalKeysStorage
import com.tangem.tangem_sdk_new.nfc.NfcManager
fun TangemSdk.Companion.init(activity: FragmentActivity): TangemSdk {
val nfcManager = NfcManager().apply {
this.setCurrentActivity(activity)
activity.lifecycle.addObserver(NfcLifecycleObserver(this))
}
val viewDelegate = DefaultSessionViewDelegate(nfcManager.reader).apply {
this.activity = activity
}
return TangemSdk(nfcManager.reader, viewDelegate).apply {
this.setTerminalKeysService(TerminalKeysStorage(activity.application))
}
fun TangemSdk.Companion.init(activity: FragmentActivity, config: Config = Config()): TangemSdk {
val nfcManager = TangemSdk.initNfcManager(activity)
val viewDelegate = DefaultSessionViewDelegate(nfcManager.reader)
viewDelegate.activity = activity
val tangemSdk = TangemSdk(nfcManager.reader, viewDelegate, config)
tangemSdk.setTerminalKeysService(TerminalKeysStorage(activity.application))
return tangemSdk
}
fun TangemSdk.Companion.customInit(
activity: FragmentActivity,
viewDelegate: SessionViewDelegate? = null, cardReader: CardReader? = null,
config: Config = Config()
): TangemSdk {
val nfcManager = TangemSdk.initNfcManager(activity)
val tangemSdk = TangemSdk(
cardReader ?: nfcManager.reader,
viewDelegate ?: DefaultSessionViewDelegate(nfcManager.reader)
.apply { this.activity = activity },
config
)
tangemSdk.setTerminalKeysService(TerminalKeysStorage(activity.application))
return tangemSdk
}
fun TangemSdk.Companion.initNfcManager(activity: FragmentActivity): NfcManager {
val nfcManager = NfcManager()
nfcManager.setCurrentActivity(activity)
activity.lifecycle.addObserver(NfcLifecycleObserver(nfcManager))
return nfcManager
}