Updated on 2026-08-14
This commit is contained in:
parent
0645cffc25
commit
72a2623faa
13 changed files with 287 additions and 2 deletions
2
.idea/gradle.xml
generated
2
.idea/gradle.xml
generated
|
|
@ -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" />
|
||||||
|
|
|
||||||
|
|
@ -23,4 +23,4 @@ allprojects {
|
||||||
|
|
||||||
task clean(type: Delete) {
|
task clean(type: Delete) {
|
||||||
delete rootProject.buildDir
|
delete rootProject.buildDir
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
1
tangem-sdk-new/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
/build
|
||||||
47
tangem-sdk-new/build.gradle
Normal file
47
tangem-sdk-new/build.gradle
Normal 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'
|
||||||
|
}
|
||||||
0
tangem-sdk-new/consumer-rules.pro
Normal file
0
tangem-sdk-new/consumer-rules.pro
Normal file
21
tangem-sdk-new/proguard-rules.pro
vendored
Normal file
21
tangem-sdk-new/proguard-rules.pro
vendored
Normal 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
|
||||||
5
tangem-sdk-new/src/main/AndroidManifest.xml
Normal file
5
tangem-sdk-new/src/main/AndroidManifest.xml
Normal 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>
|
||||||
|
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
3
tangem-sdk-new/src/main/res/values/strings.xml
Normal file
3
tangem-sdk-new/src/main/res/values/strings.xml
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<resources>
|
||||||
|
<string name="app_name">Tangem Sdk</string>
|
||||||
|
</resources>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue