Updated on 2026-08-14

This commit is contained in:
Tangem 2019-10-01 17:09:37 +03:00
parent 0645cffc25
commit 72a2623faa
13 changed files with 287 additions and 2 deletions

2
.idea/gradle.xml generated
View file

@ -13,6 +13,8 @@
<option value="$PROJECT_DIR$/tangem-card" /> <option value="$PROJECT_DIR$/tangem-card" />
<option value="$PROJECT_DIR$/tangem-card-new" /> <option value="$PROJECT_DIR$/tangem-card-new" />
<option value="$PROJECT_DIR$/tangem-sdk" /> <option value="$PROJECT_DIR$/tangem-sdk" />
<option value="$PROJECT_DIR$/tangem-sdk-new" />
<option value="$PROJECT_DIR$/tangemtest" />
</set> </set>
</option> </option>
<option name="resolveModulePerSourceSet" value="false" /> <option name="resolveModulePerSourceSet" value="false" />

View file

@ -23,4 +23,4 @@ allprojects {
task clean(type: Delete) { task clean(type: Delete) {
delete rootProject.buildDir delete rootProject.buildDir
} }

View file

@ -1 +1 @@
include ':app', ':tangem-sdk', ':server-android', ':tangem-card', ':tangem-card-new' include ':app', ':tangem-sdk', ':server-android', ':tangem-card', ':tangem-card-new', ':tangem-sdk-new', ':tangemtest'

1
tangem-sdk-new/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/build

View file

@ -0,0 +1,47 @@
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 29
buildToolsVersion "29.0.0"
defaultConfig {
minSdkVersion 21
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'consumer-rules.pro'
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
dependencies {
implementation project(':tangem-card-new')
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.core:core-ktx:1.1.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.1.0'
implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0'
implementation "androidx.lifecycle:lifecycle-runtime:2.1.0"
implementation "androidx.lifecycle:lifecycle-common-java8:2.1.0"
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}

View file

21
tangem-sdk-new/proguard-rules.pro vendored Normal file
View file

@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View file

@ -0,0 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tangem.tangem_sdk_new" >
<uses-permission android:name="android.permission.NFC" />
</manifest>

View file

@ -0,0 +1,36 @@
package com.tangem.tangem_sdk_new
import android.app.AlertDialog
import androidx.fragment.app.FragmentActivity
import com.tangem.CardError
import com.tangem.CardManagerDelegate
class BasicCardManagerDelegate(val activity: FragmentActivity) : CardManagerDelegate {
private var dialog: AlertDialog? = null
override fun showSecurityDelay(seconds: Int) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun hideSecurityDelay() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun requestPin(success: () -> String, error: (cardError: CardError) -> CardError) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun openNfcPopup() {
dialog = AlertDialog.Builder(activity)
.setTitle("NFC reader mode")
.create()
dialog?.show()
}
override fun closeNfcPopup() {
dialog?.dismiss()
}
}

View file

@ -0,0 +1,28 @@
package com.tangem.tangem_sdk_new
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
class NfcLifecycleObserver(private var nfcManager: NfcManager) : DefaultLifecycleObserver {
override fun onResume(owner: LifecycleOwner) {
super.onResume(owner)
nfcManager.onResume()
}
override fun onPause(owner: LifecycleOwner) {
super.onPause(owner)
nfcManager.onPause()
}
override fun onStop(owner: LifecycleOwner) {
super.onStop(owner)
nfcManager.onStop()
}
override fun onDestroy(owner: LifecycleOwner) {
super.onDestroy(owner)
nfcManager.onDestroy()
}
}

View file

@ -0,0 +1,99 @@
package com.tangem.tangem_sdk_new
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.nfc.NfcAdapter
import android.nfc.Tag
import android.nfc.tech.IsoDep
import android.os.Build
import android.os.Bundle
import androidx.fragment.app.FragmentActivity
class NfcManager(private val reader: NfcReader) : NfcAdapter.ReaderCallback {
private var activity: FragmentActivity? = null
private var nfcAdapter: NfcAdapter? = null
private var readerCallback: NfcAdapter.ReaderCallback? = null
// private var nfcEnableDialog: NfcEnableDialog? = null
fun setCurrentActivity(activity: FragmentActivity, readerCallback: NfcAdapter.ReaderCallback) {
this.activity = activity
nfcAdapter = NfcAdapter.getDefaultAdapter(activity)
this.readerCallback = readerCallback
}
private val mBroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val action = intent.action ?: return
if (action == NfcAdapter.ACTION_ADAPTER_STATE_CHANGED) {
if (intent.getIntExtra(NfcAdapter.EXTRA_ADAPTER_STATE, NfcAdapter.STATE_ON) == NfcAdapter.STATE_ON)
enableReaderMode()
}
}
}
override fun onTagDiscovered(tag: Tag?) {
reader.isoDep = IsoDep.get(tag)
reader.onTagDiscovered(tag)
if (!reader.readingActive) ignoreTag(tag)
}
fun onResume() {
val filter = IntentFilter(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED)
activity?.registerReceiver(mBroadcastReceiver, filter)
if (nfcAdapter == null || nfcAdapter?.isEnabled != true)
// showNFCEnableDialog()
else
enableReaderMode()
}
fun onPause() {
activity?.unregisterReceiver(mBroadcastReceiver)
disableReaderMode()
}
fun onStop() {
// nfcEnableDialog?.dismiss()
}
fun onDestroy() {
activity = null
nfcAdapter = null
readerCallback = null
}
// private fun showNFCEnableDialog() {
// nfcEnableDialog = NfcEnableDialog()
// activity?.supportFragmentManager?.let { nfcEnableDialog?.show(it, NfcEnableDialog.TAG) }
// }
private fun enableReaderMode() {
val options = Bundle()
nfcAdapter?.enableReaderMode(activity, readerCallback, READER_FLAGS, options)
}
private fun disableReaderMode() {
nfcAdapter?.disableReaderMode(activity)
}
fun ignoreTag(tag: Tag?) {
if (Build.VERSION.SDK_INT >= 24) {
nfcAdapter?.ignore(tag, 1500, null, null)
}
IsoDep.get(tag)?.close()
}
companion object {
// reader mode flags: listen for type A (not B), skipping ndef check
private const val READER_FLAGS = NfcAdapter.FLAG_READER_NFC_A or
NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK or
NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS
}
}

View file

@ -0,0 +1,43 @@
package com.tangem.tangem_sdk_new
import android.nfc.Tag
import android.nfc.tech.IsoDep
import com.tangem.CardReader
import com.tangem.data.ResponseApdu
class NfcReader() : CardReader {
var isoDep: IsoDep? = null
var readingActive = false
var data: ByteArray? = null
var callback: ((responseApdu: ResponseApdu) -> Unit)? = null
override fun sendApdu(apduSerialized: ByteArray, callback: (responseApdu: ResponseApdu) -> Unit) {
data = apduSerialized
this.callback = callback
}
fun onTagDiscovered(tag: Tag?) {
if (data != null) {
readingActive = true
connect()
val rawResponse = isoDep?.transceive(data)
if (rawResponse != null) {
readingActive = false
data = null
}
rawResponse?.let { callback?.invoke(ResponseApdu(it)) }
}
}
private fun connect() {
val timeout = isoDep?.timeout
isoDep?.connect()
isoDep?.close()
isoDep?.connect()
isoDep?.timeout = timeout ?: 0
}
}

View file

@ -0,0 +1,3 @@
<resources>
<string name="app_name">Tangem Sdk</string>
</resources>