@digitalshieldfe/react-native-backup-card-sdk 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build.gradle +33 -49
- package/android/libs/backupcardsdk.aar +0 -0
- package/android/src/main/AndroidManifest.xml +1 -4
- package/android/src/main/java/com/ziancube/reactnativebackupcardsdk/BackupCardSdkModule.kt +244 -74
- package/android/src/main/java/com/ziancube/reactnativebackupcardsdk/BackupCardSdkPackage.kt +1 -1
- package/android/src/main/java/com/ziancube/reactnativebackupcardsdk/nfc/NfcExceptions.kt +11 -0
- package/android/src/main/java/com/ziancube/reactnativebackupcardsdk/nfc/NfcUtils.kt +30 -0
- package/android/src/main/java/com/ziancube/reactnativebackupcardsdk/utils/MiUtil.kt +74 -0
- package/android/src/main/java/com/ziancube/reactnativebackupcardsdk/utils/NfcPermissionUtils.kt +23 -0
- package/lib/module/NativeBackupCardSdk.js +3 -0
- package/lib/module/NativeBackupCardSdk.js.map +1 -1
- package/lib/module/cardOperations.js +27 -0
- package/lib/module/cardOperations.js.map +1 -0
- package/lib/module/index.js +2 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/nfc.js +75 -0
- package/lib/module/nfc.js.map +1 -0
- package/lib/typescript/src/NativeBackupCardSdk.d.ts +50 -4
- package/lib/typescript/src/NativeBackupCardSdk.d.ts.map +1 -1
- package/lib/typescript/src/cardOperations.d.ts +7 -0
- package/lib/typescript/src/cardOperations.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +5 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/nfc.d.ts +28 -0
- package/lib/typescript/src/nfc.d.ts.map +1 -0
- package/package.json +7 -5
- package/src/NativeBackupCardSdk.ts +62 -4
- package/src/cardOperations.ts +61 -0
- package/src/index.tsx +22 -2
- package/src/nfc.ts +74 -0
- package/android/consumer-rules.pro +0 -0
- package/android/proguard-rules.pro +0 -21
- package/android/src/main/java/com/ziancube/backupcardsdk/BackupCardSdk.kt +0 -478
- package/android/src/main/java/com/ziancube/backupcardsdk/GPChannelNatives.java +0 -41
- package/android/src/main/java/com/ziancube/backupcardsdk/listener/ApiAsyncListener.java +0 -13
- package/android/src/main/java/com/ziancube/backupcardsdk/nfc/ApiNfc.java +0 -173
- package/android/src/main/java/com/ziancube/backupcardsdk/nfc/ImplNfc.java +0 -39
- package/android/src/main/java/com/ziancube/backupcardsdk/nfc/NfcComm.java +0 -115
- package/android/src/main/java/com/ziancube/backupcardsdk/utils/ApduParam.java +0 -67
- package/android/src/main/java/com/ziancube/backupcardsdk/utils/CommList.java +0 -41
- package/android/src/main/java/com/ziancube/backupcardsdk/utils/Utils.java +0 -109
- package/android/src/main/jni/CMakeLists.txt +0 -60
- package/android/src/main/jni/GPChannel/include/GPChannelSDK.h +0 -306
- package/android/src/main/jni/GPChannel/include/context/BaseContext.h +0 -56
- package/android/src/main/jni/GPChannel/include/device/ApduBuilder.hpp +0 -72
- package/android/src/main/jni/GPChannel/include/utility/Apdu.hpp +0 -166
- package/android/src/main/jni/GPChannel/include/utility/Debug.hpp +0 -59
- package/android/src/main/jni/GPChannel/include/utility/Singleton.h +0 -34
- package/android/src/main/jni/GPChannel/include/utility/mutex.h +0 -24
- package/android/src/main/jni/GPChannel/include/utility/trim.hpp +0 -155
- package/android/src/main/jni/GPChannel/include/utility/util.h +0 -104
- package/android/src/main/jni/GPChannel/include/utility/xFactory.hpp +0 -26
- package/android/src/main/jni/GPChannel/include/utility/xManager.hpp +0 -84
- package/android/src/main/jni/GPChannel/src/arm64-v8a/libJUB_GPC_APDU_SDK.a +0 -0
- package/android/src/main/jni/GPChannel/src/arm64-v8a/libTrezorCrypto.a +0 -0
- package/android/src/main/jni/GPChannel/src/armeabi-v7a/libJUB_GPC_APDU_SDK.a +0 -0
- package/android/src/main/jni/GPChannel/src/armeabi-v7a/libTrezorCrypto.a +0 -0
- package/android/src/main/jni/GPChannel/src/x86/libJUB_GPC_APDU_SDK.a +0 -0
- package/android/src/main/jni/GPChannel/src/x86/libTrezorCrypto.a +0 -0
- package/android/src/main/jni/src/implJni.cpp +0 -313
- package/android/src/main/jni/src/implJni.h +0 -9
- package/android/src/main/jni/utils/jsoncpp/AUTHORS +0 -111
- package/android/src/main/jni/utils/jsoncpp/CMakeLists.txt +0 -159
- package/android/src/main/jni/utils/jsoncpp/LICENSE +0 -55
- package/android/src/main/jni/utils/jsoncpp/README.md +0 -135
- package/android/src/main/jni/utils/jsoncpp/amalgamate.py +0 -155
- package/android/src/main/jni/utils/jsoncpp/appveyor.yml +0 -22
- package/android/src/main/jni/utils/jsoncpp/dev.makefile +0 -35
- package/android/src/main/jni/utils/jsoncpp/devtools/__init__.py +0 -6
- package/android/src/main/jni/utils/jsoncpp/devtools/agent_vmw7.json +0 -33
- package/android/src/main/jni/utils/jsoncpp/devtools/agent_vmxp.json +0 -26
- package/android/src/main/jni/utils/jsoncpp/devtools/antglob.py +0 -205
- package/android/src/main/jni/utils/jsoncpp/devtools/batchbuild.py +0 -278
- package/android/src/main/jni/utils/jsoncpp/devtools/fixeol.py +0 -70
- package/android/src/main/jni/utils/jsoncpp/devtools/licenseupdater.py +0 -94
- package/android/src/main/jni/utils/jsoncpp/devtools/tarball.py +0 -52
- package/android/src/main/jni/utils/jsoncpp/doxybuild.py +0 -189
- package/android/src/main/jni/utils/jsoncpp/include/CMakeLists.txt +0 -2
- package/android/src/main/jni/utils/jsoncpp/include/json/allocator.h +0 -98
- package/android/src/main/jni/utils/jsoncpp/include/json/assertions.h +0 -54
- package/android/src/main/jni/utils/jsoncpp/include/json/autolink.h +0 -25
- package/android/src/main/jni/utils/jsoncpp/include/json/config.h +0 -187
- package/android/src/main/jni/utils/jsoncpp/include/json/features.h +0 -61
- package/android/src/main/jni/utils/jsoncpp/include/json/forwards.h +0 -37
- package/android/src/main/jni/utils/jsoncpp/include/json/json.h +0 -15
- package/android/src/main/jni/utils/jsoncpp/include/json/reader.h +0 -411
- package/android/src/main/jni/utils/jsoncpp/include/json/value.h +0 -888
- package/android/src/main/jni/utils/jsoncpp/include/json/version.h +0 -20
- package/android/src/main/jni/utils/jsoncpp/include/json/writer.h +0 -357
- package/android/src/main/jni/utils/jsoncpp/makefiles/vs71/jsontest.vcproj +0 -119
- package/android/src/main/jni/utils/jsoncpp/makefiles/vs71/lib_json.vcproj +0 -205
- package/android/src/main/jni/utils/jsoncpp/makefiles/vs71/test_lib_json.vcproj +0 -130
- package/android/src/main/jni/utils/jsoncpp/makerelease.py +0 -390
- package/android/src/main/jni/utils/jsoncpp/meson.build +0 -103
- package/android/src/main/jni/utils/jsoncpp/pkg-config/jsoncpp.pc.in +0 -9
- package/android/src/main/jni/utils/jsoncpp/src/CMakeLists.txt +0 -5
- package/android/src/main/jni/utils/jsoncpp/src/jsontestrunner/CMakeLists.txt +0 -25
- package/android/src/main/jni/utils/jsoncpp/src/jsontestrunner/main.cpp +0 -333
- package/android/src/main/jni/utils/jsoncpp/src/lib_json/CMakeLists.txt +0 -117
- package/android/src/main/jni/utils/jsoncpp/src/lib_json/json_reader.cpp +0 -2060
- package/android/src/main/jni/utils/jsoncpp/src/lib_json/json_tool.h +0 -114
- package/android/src/main/jni/utils/jsoncpp/src/lib_json/json_value.cpp +0 -1661
- package/android/src/main/jni/utils/jsoncpp/src/lib_json/json_valueiterator.inl +0 -167
- package/android/src/main/jni/utils/jsoncpp/src/lib_json/json_writer.cpp +0 -1233
- package/android/src/main/jni/utils/jsoncpp/src/lib_json/version.h.in +0 -20
- package/android/src/main/jni/utils/jsoncpp/src/test_lib_json/CMakeLists.txt +0 -38
- package/android/src/main/jni/utils/jsoncpp/src/test_lib_json/jsontest.cpp +0 -457
- package/android/src/main/jni/utils/jsoncpp/src/test_lib_json/jsontest.h +0 -286
- package/android/src/main/jni/utils/jsoncpp/src/test_lib_json/main.cpp +0 -2606
- package/android/src/main/jni/utils/jsoncpp/travis.sh +0 -23
- package/android/src/main/jni/utils/jsoncpp/version +0 -1
- package/android/src/main/jni/utils/jsoncpp/version.in +0 -1
- package/android/src/main/jni/utils/logUtils.cpp +0 -108
- package/android/src/main/jni/utils/logUtils.h +0 -87
- package/android/src/main/jni/utils/mSIGNA/stdutils/uchar_vector.h +0 -614
package/android/build.gradle
CHANGED
|
@@ -15,7 +15,6 @@ buildscript {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
repositories {
|
|
18
|
-
mavenLocal()
|
|
19
18
|
google()
|
|
20
19
|
mavenCentral()
|
|
21
20
|
}
|
|
@@ -33,6 +32,33 @@ apply plugin: "kotlin-android"
|
|
|
33
32
|
|
|
34
33
|
apply plugin: "com.facebook.react"
|
|
35
34
|
|
|
35
|
+
react {
|
|
36
|
+
jsRootDir = file("../src/")
|
|
37
|
+
libraryName = "BackupCardSdkSpec"
|
|
38
|
+
codegenJavaPackageName = "com.ziancube.reactnativebackupcardsdk"
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Kotlin/Java TurboModule uses BackupCardSdkSpec-generated.cpp (JavaTurboModule).
|
|
42
|
+
// BackupCardSdkSpecJSI-generated.cpp targets a C++ module class that is not implemented
|
|
43
|
+
// and conflicts with BackupCardSdkSpecJSI.h from the same codegen run.
|
|
44
|
+
def patchBackupCardCodegen = tasks.register("patchBackupCardCodegen") {
|
|
45
|
+
doLast {
|
|
46
|
+
def jsiCpp =
|
|
47
|
+
file(
|
|
48
|
+
"${layout.buildDirectory.get()}/generated/source/codegen/jni/react/renderer/components/BackupCardSdkSpec/BackupCardSdkSpecJSI-generated.cpp"
|
|
49
|
+
)
|
|
50
|
+
if (jsiCpp.exists()) {
|
|
51
|
+
jsiCpp.delete()
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
tasks.configureEach { task ->
|
|
57
|
+
if (task.name == "generateCodegenArtifactsFromSchema") {
|
|
58
|
+
task.finalizedBy(patchBackupCardCodegen)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
36
62
|
android {
|
|
37
63
|
namespace "com.ziancube.reactnativebackupcardsdk"
|
|
38
64
|
|
|
@@ -41,31 +67,6 @@ android {
|
|
|
41
67
|
defaultConfig {
|
|
42
68
|
minSdkVersion getExtOrDefault("minSdkVersion")
|
|
43
69
|
targetSdkVersion getExtOrDefault("targetSdkVersion")
|
|
44
|
-
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
|
45
|
-
consumerProguardFiles "consumer-rules.pro"
|
|
46
|
-
|
|
47
|
-
externalNativeBuild {
|
|
48
|
-
cmake {
|
|
49
|
-
cppFlags(
|
|
50
|
-
"",
|
|
51
|
-
"-std=c++11",
|
|
52
|
-
"-frtti",
|
|
53
|
-
"-fexceptions",
|
|
54
|
-
"-DHAVE_ENDIAN_H"
|
|
55
|
-
)
|
|
56
|
-
|
|
57
|
-
arguments(
|
|
58
|
-
"-DANDROID_TOOLCHAIN=clang",
|
|
59
|
-
"-DANDROID_STL=c++_static",
|
|
60
|
-
"-DANDROID_ARM_MODE=arm",
|
|
61
|
-
"-DANDROID_PLATFORM=android-19"
|
|
62
|
-
)
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
ndk {
|
|
67
|
-
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86'
|
|
68
|
-
}
|
|
69
70
|
}
|
|
70
71
|
|
|
71
72
|
buildFeatures {
|
|
@@ -75,10 +76,6 @@ android {
|
|
|
75
76
|
buildTypes {
|
|
76
77
|
release {
|
|
77
78
|
minifyEnabled false
|
|
78
|
-
proguardFiles(
|
|
79
|
-
getDefaultProguardFile("proguard-android-optimize.txt"),
|
|
80
|
-
"proguard-rules.pro"
|
|
81
|
-
)
|
|
82
79
|
}
|
|
83
80
|
}
|
|
84
81
|
|
|
@@ -87,28 +84,15 @@ android {
|
|
|
87
84
|
}
|
|
88
85
|
|
|
89
86
|
compileOptions {
|
|
90
|
-
sourceCompatibility JavaVersion.
|
|
91
|
-
targetCompatibility JavaVersion.
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
externalNativeBuild {
|
|
95
|
-
cmake {
|
|
96
|
-
path = file("src/main/jni/CMakeLists.txt")
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
publishing {
|
|
101
|
-
singleVariant("release") {
|
|
102
|
-
withSourcesJar()
|
|
103
|
-
}
|
|
87
|
+
sourceCompatibility JavaVersion.VERSION_1_8
|
|
88
|
+
targetCompatibility JavaVersion.VERSION_1_8
|
|
104
89
|
}
|
|
105
90
|
}
|
|
106
91
|
|
|
107
92
|
dependencies {
|
|
108
|
-
implementation("
|
|
109
|
-
|
|
93
|
+
implementation(files("libs/backupcardsdk.aar"))
|
|
94
|
+
// Transitive deps of backupcardsdk (not bundled inside the AAR)
|
|
95
|
+
implementation("androidx.appcompat:appcompat:1.7.1")
|
|
96
|
+
implementation("com.google.android.material:material:1.13.0")
|
|
110
97
|
implementation("com.facebook.react:react-android")
|
|
111
|
-
testImplementation("junit:junit:4.13.2")
|
|
112
|
-
androidTestImplementation("androidx.test.ext:junit:1.1.5")
|
|
113
|
-
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
|
|
114
98
|
}
|
|
Binary file
|
|
@@ -1,5 +1,2 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="utf-8"?>
|
|
2
1
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
3
|
-
|
|
4
|
-
<uses-feature android:name="android.hardware.nfc" android:required="false" />
|
|
5
|
-
</manifest>
|
|
2
|
+
</manifest>
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
package com.ziancube.reactnativebackupcardsdk
|
|
2
2
|
|
|
3
|
+
import android.app.Activity
|
|
3
4
|
import android.content.Intent
|
|
5
|
+
import android.util.Log
|
|
4
6
|
import com.facebook.react.bridge.Arguments
|
|
5
7
|
import com.facebook.react.bridge.BaseActivityEventListener
|
|
6
8
|
import com.facebook.react.bridge.Promise
|
|
@@ -12,7 +14,12 @@ import com.facebook.react.bridge.LifecycleEventListener
|
|
|
12
14
|
import com.ziancube.backupcardsdk.ApduLogger
|
|
13
15
|
import com.ziancube.backupcardsdk.BackupCardSdk
|
|
14
16
|
import com.ziancube.backupcardsdk.NfcTouchListener
|
|
17
|
+
import com.ziancube.backupcardsdk.CardOperationResult
|
|
15
18
|
import com.ziancube.backupcardsdk.CardInfo
|
|
19
|
+
import com.ziancube.backupcardsdk.NfcWaitTimeoutException
|
|
20
|
+
import com.ziancube.reactnativebackupcardsdk.nfc.NfcExceptions
|
|
21
|
+
import com.ziancube.reactnativebackupcardsdk.nfc.NfcUtils
|
|
22
|
+
import com.ziancube.reactnativebackupcardsdk.utils.NfcPermissionUtils
|
|
16
23
|
import kotlinx.coroutines.CoroutineDispatcher
|
|
17
24
|
import kotlinx.coroutines.CoroutineScope
|
|
18
25
|
import kotlinx.coroutines.Dispatchers
|
|
@@ -21,47 +28,73 @@ import kotlinx.coroutines.cancel
|
|
|
21
28
|
import kotlinx.coroutines.launch
|
|
22
29
|
import kotlinx.coroutines.withContext
|
|
23
30
|
|
|
24
|
-
fun CardInfo.toWritableMap(): WritableMap {
|
|
25
|
-
val map = Arguments.createMap()
|
|
26
|
-
map.putString("serialNumber", serialNumber)
|
|
27
|
-
map.putInt("pinRetryCount", pinRetryCount ?: -1)
|
|
28
|
-
map.putBoolean("isNewCard", isNewCard ?: false)
|
|
29
|
-
return map
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
fun ReadableArray.toByteArray(): ByteArray {
|
|
33
|
-
val bytes = ByteArray(size())
|
|
34
|
-
for (i in 0 until size()) {
|
|
35
|
-
bytes[i] = getInt(i).toByte()
|
|
36
|
-
}
|
|
37
|
-
return bytes
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
fun ByteArray?.toWritableArrayOrNull(): WritableArray? {
|
|
41
|
-
if (this == null) return null
|
|
42
|
-
val array = Arguments.createArray()
|
|
43
|
-
for (b in this) {
|
|
44
|
-
array.pushInt(b.toInt() and 0xFF)
|
|
45
|
-
}
|
|
46
|
-
return array
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
|
|
50
31
|
class BackupCardSdkModule(val reactContext: ReactApplicationContext) :
|
|
51
32
|
NativeBackupCardSdkSpec(reactContext) ,LifecycleEventListener
|
|
52
33
|
{
|
|
53
|
-
private
|
|
34
|
+
private var backupCardSdk: BackupCardSdk? = null
|
|
35
|
+
private var boundActivity: Activity? = null
|
|
54
36
|
private val tag = "BackupCardSdkModule"
|
|
55
37
|
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
|
|
38
|
+
|
|
39
|
+
private val apduLogger =
|
|
40
|
+
object : ApduLogger {
|
|
41
|
+
override fun log(message: String, isSent: Boolean, isSuccess: Boolean) {
|
|
42
|
+
val params =
|
|
43
|
+
Arguments.createMap()
|
|
44
|
+
.apply {
|
|
45
|
+
putString("message", message)
|
|
46
|
+
putBoolean("isSent", isSent)
|
|
47
|
+
putBoolean("isSuccess", isSuccess)
|
|
48
|
+
}
|
|
49
|
+
.copy()
|
|
50
|
+
runCatching { emitOnApduLog(params) }
|
|
51
|
+
.onFailure { Log.w(tag, "Dropped apduLog event: JS callback is not ready", it) }
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private val nfcTouchListener =
|
|
56
|
+
object : NfcTouchListener {
|
|
57
|
+
override fun onTouch(isBackupCard: Boolean) {
|
|
58
|
+
val params =
|
|
59
|
+
Arguments.createMap()
|
|
60
|
+
.apply { putBoolean("isBackupCard", isBackupCard) }
|
|
61
|
+
.copy()
|
|
62
|
+
runCatching { emitOnNfcTouch(params) }
|
|
63
|
+
.onFailure { Log.w(tag, "Dropped nfcTouch event: JS callback is not ready", it) }
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
private fun ensureBackupCardSdk(activity: Activity?): BackupCardSdk? {
|
|
68
|
+
if (activity == null) return null
|
|
69
|
+
if (backupCardSdk != null && boundActivity === activity) return backupCardSdk
|
|
70
|
+
|
|
71
|
+
runCatching { backupCardSdk?.release() }
|
|
72
|
+
.onFailure { Log.e(tag, "Failed to release previous BackupCardSdk", it) }
|
|
73
|
+
|
|
74
|
+
boundActivity = activity
|
|
75
|
+
backupCardSdk = runCatching { BackupCardSdk(activity, apduLogger, nfcTouchListener) }
|
|
76
|
+
.onFailure { Log.e(tag, "Failed to initialize BackupCardSdk", it) }
|
|
77
|
+
.getOrNull()
|
|
78
|
+
return backupCardSdk
|
|
79
|
+
}
|
|
80
|
+
|
|
56
81
|
override fun invalidate() {
|
|
57
82
|
super.invalidate()
|
|
83
|
+
backupCardSdk?.cancelWaitForCardTag()
|
|
84
|
+
backupCardSdk?.release()
|
|
85
|
+
backupCardSdk = null
|
|
86
|
+
boundActivity = null
|
|
58
87
|
scope.cancel()
|
|
59
88
|
}
|
|
60
89
|
private val mActivityEventListener =
|
|
61
90
|
object : BaseActivityEventListener() {
|
|
62
91
|
override fun onNewIntent(intent: Intent) {
|
|
63
92
|
super.onNewIntent(intent)
|
|
64
|
-
|
|
93
|
+
runCatching {
|
|
94
|
+
backupCardSdk?.handleIntent(intent)
|
|
95
|
+
}.onFailure {
|
|
96
|
+
Log.e(tag, "Crash while handling NFC intent", it)
|
|
97
|
+
}
|
|
65
98
|
}
|
|
66
99
|
}
|
|
67
100
|
|
|
@@ -69,37 +102,76 @@ class BackupCardSdkModule(val reactContext: ReactApplicationContext) :
|
|
|
69
102
|
super.initialize()
|
|
70
103
|
Utils.init(reactContext)
|
|
71
104
|
Utils.getActivityLifecycle()
|
|
72
|
-
val activity = Utils.getTopActivity()
|
|
73
|
-
if (activity == null) {
|
|
74
|
-
return
|
|
75
|
-
}
|
|
76
|
-
val apduLogger =
|
|
77
|
-
object : ApduLogger {
|
|
78
|
-
override fun log(message: String, isSent: Boolean, isSuccess: Boolean) {
|
|
79
|
-
val params =
|
|
80
|
-
Arguments.createMap()
|
|
81
|
-
.apply {
|
|
82
|
-
putString("message", message)
|
|
83
|
-
putBoolean("isSent", isSent)
|
|
84
|
-
putBoolean("isSuccess", isSuccess)
|
|
85
|
-
}
|
|
86
|
-
.copy()
|
|
87
|
-
emitOnApduLog(params)
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
val nfcTouchListener =
|
|
91
|
-
object : NfcTouchListener {
|
|
92
|
-
override fun onTouch(isBackupCard: Boolean) {
|
|
93
|
-
val params =
|
|
94
|
-
Arguments.createMap()
|
|
95
|
-
.apply { putBoolean("isBackupCard", isBackupCard) }
|
|
96
|
-
.copy()
|
|
97
|
-
emitOnNfcTouch(params)
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
backupCardSdk = BackupCardSdk(activity, apduLogger, nfcTouchListener)
|
|
101
105
|
reactContext.addActivityEventListener(mActivityEventListener)
|
|
102
106
|
reactContext.addLifecycleEventListener(this)
|
|
107
|
+
ensureBackupCardSdk(Utils.getTopActivity())
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
private fun CardInfo.toCardInfoMap(): WritableMap {
|
|
111
|
+
val map = Arguments.createMap()
|
|
112
|
+
map.putString("serialNumber", serialNumber)
|
|
113
|
+
map.putInt("pinRetryCount", pinRetryCount ?: -1)
|
|
114
|
+
map.putBoolean("isNewCard", isNewCard ?: false)
|
|
115
|
+
val backup = isBackup
|
|
116
|
+
if (backup != null) {
|
|
117
|
+
map.putBoolean("isBackup", backup)
|
|
118
|
+
} else {
|
|
119
|
+
map.putNull("isBackup")
|
|
120
|
+
}
|
|
121
|
+
return map
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
private fun putOperationData(map: WritableMap, data: Any?) {
|
|
125
|
+
when (data) {
|
|
126
|
+
null -> map.putNull("data")
|
|
127
|
+
is Boolean -> map.putBoolean("data", data)
|
|
128
|
+
is Int -> map.putInt("data", data)
|
|
129
|
+
is Long -> map.putDouble("data", data.toDouble())
|
|
130
|
+
is Double -> map.putDouble("data", data)
|
|
131
|
+
is Float -> map.putDouble("data", data.toDouble())
|
|
132
|
+
is String -> map.putString("data", data)
|
|
133
|
+
is ByteArray -> map.putArray("data", data.asWritableArrayOrNull())
|
|
134
|
+
else -> map.putNull("data")
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
private fun CardOperationResult<*>.toCardOperationResultMap(): WritableMap {
|
|
139
|
+
val map = Arguments.createMap()
|
|
140
|
+
val cardError = error
|
|
141
|
+
val info = cardInfo
|
|
142
|
+
if (cardError != null) {
|
|
143
|
+
val errorMap = Arguments.createMap()
|
|
144
|
+
errorMap.putInt("code", cardError.code)
|
|
145
|
+
errorMap.putString("message", cardError.message)
|
|
146
|
+
map.putMap("error", errorMap)
|
|
147
|
+
} else {
|
|
148
|
+
map.putNull("error")
|
|
149
|
+
}
|
|
150
|
+
if (info != null) {
|
|
151
|
+
map.putMap("cardInfo", info.toCardInfoMap())
|
|
152
|
+
} else {
|
|
153
|
+
map.putNull("cardInfo")
|
|
154
|
+
}
|
|
155
|
+
map.putInt("resultCode", resultCode)
|
|
156
|
+
putOperationData(map, data)
|
|
157
|
+
return map
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
private fun ReadableArray.asByteArray(): ByteArray {
|
|
161
|
+
val bytes = ByteArray(size())
|
|
162
|
+
for (i in 0 until size()) {
|
|
163
|
+
bytes[i] = getInt(i).toByte()
|
|
164
|
+
}
|
|
165
|
+
return bytes
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
private fun ByteArray?.asWritableArrayOrNull(): WritableArray? {
|
|
169
|
+
if (this == null) return null
|
|
170
|
+
val array = Arguments.createArray()
|
|
171
|
+
for (b in this) {
|
|
172
|
+
array.pushInt(b.toInt() and 0xFF)
|
|
173
|
+
}
|
|
174
|
+
return array
|
|
103
175
|
}
|
|
104
176
|
|
|
105
177
|
companion object {
|
|
@@ -108,44 +180,125 @@ class BackupCardSdkModule(val reactContext: ReactApplicationContext) :
|
|
|
108
180
|
|
|
109
181
|
override fun getCardInfo(promise: Promise) =
|
|
110
182
|
promise.launchSuspend(
|
|
111
|
-
block = {
|
|
112
|
-
|
|
183
|
+
block = {
|
|
184
|
+
val sdk = ensureBackupCardSdk(Utils.getTopActivity())
|
|
185
|
+
?: throw IllegalStateException("No foreground activity available")
|
|
186
|
+
sdk.getCardInfo()
|
|
187
|
+
},
|
|
188
|
+
transform = { info -> info?.toCardInfoMap() }
|
|
113
189
|
)
|
|
114
190
|
|
|
191
|
+
override fun cancelNfcWait() {
|
|
192
|
+
backupCardSdk?.cancelWaitForCardTag()
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
override fun checkNFCPermission(promise: Promise) {
|
|
196
|
+
val activity = Utils.getTopActivity()
|
|
197
|
+
if (activity == null) {
|
|
198
|
+
promise.rejectNfc(NfcExceptions.InitializedException("No foreground activity"))
|
|
199
|
+
return
|
|
200
|
+
}
|
|
201
|
+
if (!NfcUtils.isNfcExits(activity)) {
|
|
202
|
+
promise.rejectNfc(NfcExceptions.NotExistsNFC())
|
|
203
|
+
return
|
|
204
|
+
}
|
|
205
|
+
if (!NfcUtils.isNfcEnable(activity)) {
|
|
206
|
+
promise.rejectNfc(NfcExceptions.NotEnableNFC())
|
|
207
|
+
return
|
|
208
|
+
}
|
|
209
|
+
var granted = false
|
|
210
|
+
NfcPermissionUtils.checkPermission(activity) { granted = true }
|
|
211
|
+
if (granted) {
|
|
212
|
+
promise.resolve(true)
|
|
213
|
+
} else {
|
|
214
|
+
promise.rejectNfc(NfcExceptions.NotNFCPermission())
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
override fun intoSetting() {
|
|
219
|
+
val activity = Utils.getTopActivity() ?: return
|
|
220
|
+
NfcUtils.intentToNfcSetting(activity)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
private fun Promise.rejectNfc(exception: NfcExceptions) {
|
|
224
|
+
val userInfo =
|
|
225
|
+
Arguments.createMap()
|
|
226
|
+
.apply {
|
|
227
|
+
putInt("code", exception.code)
|
|
228
|
+
putString("message", exception.message ?: "")
|
|
229
|
+
}
|
|
230
|
+
.copy()
|
|
231
|
+
reject("NFC_ERROR", exception.message, null, userInfo)
|
|
232
|
+
}
|
|
233
|
+
|
|
115
234
|
override fun resetCard(promise: Promise) =
|
|
116
235
|
promise.launchSuspend(
|
|
117
|
-
block = {
|
|
236
|
+
block = {
|
|
237
|
+
val sdk = ensureBackupCardSdk(Utils.getTopActivity())
|
|
238
|
+
?: throw IllegalStateException("No foreground activity available")
|
|
239
|
+
sdk.resetCard()
|
|
240
|
+
},
|
|
118
241
|
transform = { result -> result }
|
|
119
242
|
)
|
|
120
243
|
|
|
121
|
-
override fun activateCard(pwd: String, promise: Promise) =
|
|
244
|
+
override fun activateCard(pwd: String, serialNumber: String, promise: Promise) =
|
|
122
245
|
promise.launchSuspend(
|
|
123
|
-
block = {
|
|
124
|
-
|
|
246
|
+
block = {
|
|
247
|
+
val sdk = ensureBackupCardSdk(Utils.getTopActivity())
|
|
248
|
+
?: throw IllegalStateException("No foreground activity available")
|
|
249
|
+
sdk.activateCard(pwd, serialNumber)
|
|
250
|
+
},
|
|
251
|
+
transform = { result -> result.toCardOperationResultMap() }
|
|
125
252
|
)
|
|
126
253
|
|
|
127
254
|
override fun changePin(oldPin: String, newPin: String, promise: Promise) =
|
|
128
255
|
promise.launchSuspend(
|
|
129
|
-
block = {
|
|
256
|
+
block = {
|
|
257
|
+
val sdk = ensureBackupCardSdk(Utils.getTopActivity())
|
|
258
|
+
?: throw IllegalStateException("No foreground activity available")
|
|
259
|
+
sdk.changePin(oldPin, newPin)
|
|
260
|
+
},
|
|
130
261
|
transform = { result -> result }
|
|
131
262
|
)
|
|
132
263
|
|
|
133
264
|
override fun checkSlotEmpty(slotId: Double, pwd: String, promise: Promise) =
|
|
134
265
|
promise.launchSuspend(
|
|
135
|
-
block = {
|
|
136
|
-
|
|
266
|
+
block = {
|
|
267
|
+
val sdk = ensureBackupCardSdk(Utils.getTopActivity())
|
|
268
|
+
?: throw IllegalStateException("No foreground activity available")
|
|
269
|
+
sdk.checkSlotEmpty(slotId.toInt(), pwd)
|
|
270
|
+
},
|
|
271
|
+
transform = { result -> result.toCardOperationResultMap() }
|
|
137
272
|
)
|
|
138
273
|
|
|
139
274
|
override fun writeSlot(slotIndex: Double, data: ReadableArray, pwd: String, promise: Promise) =
|
|
140
275
|
promise.launchSuspend(
|
|
141
|
-
block = {
|
|
142
|
-
|
|
276
|
+
block = {
|
|
277
|
+
val sdk = ensureBackupCardSdk(Utils.getTopActivity())
|
|
278
|
+
?: throw IllegalStateException("No foreground activity available")
|
|
279
|
+
sdk.writeSlot(slotIndex.toInt(), data.asByteArray(), pwd)
|
|
280
|
+
},
|
|
281
|
+
transform = { result -> result.toCardOperationResultMap() }
|
|
143
282
|
)
|
|
144
283
|
|
|
145
284
|
override fun readSlot(slotIndex: Double, pwd: String, promise: Promise) =
|
|
146
285
|
promise.launchSuspend(
|
|
147
|
-
block = {
|
|
148
|
-
|
|
286
|
+
block = {
|
|
287
|
+
val sdk = ensureBackupCardSdk(Utils.getTopActivity())
|
|
288
|
+
?: throw IllegalStateException("No foreground activity available")
|
|
289
|
+
sdk.readSlot(slotIndex.toInt(), pwd)
|
|
290
|
+
},
|
|
291
|
+
transform = { result -> result.toCardOperationResultMap() }
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
override fun deleteSlot(slotIndex: Double, pwd: String, promise: Promise) =
|
|
295
|
+
promise.launchSuspend(
|
|
296
|
+
block = {
|
|
297
|
+
val sdk = ensureBackupCardSdk(Utils.getTopActivity())
|
|
298
|
+
?: throw IllegalStateException("No foreground activity available")
|
|
299
|
+
sdk.deleteSlot(slotIndex.toInt(), pwd)
|
|
300
|
+
},
|
|
301
|
+
transform = { result -> result.toCardOperationResultMap() }
|
|
149
302
|
)
|
|
150
303
|
|
|
151
304
|
|
|
@@ -154,7 +307,12 @@ class BackupCardSdkModule(val reactContext: ReactApplicationContext) :
|
|
|
154
307
|
dispatcher: CoroutineDispatcher = Dispatchers.IO,
|
|
155
308
|
block: suspend () -> T,
|
|
156
309
|
transform: (T) -> R,
|
|
157
|
-
errorCode: (Throwable) -> String = {
|
|
310
|
+
errorCode: (Throwable) -> String = { throwable ->
|
|
311
|
+
when (throwable) {
|
|
312
|
+
is NfcWaitTimeoutException -> "NFC_WAIT_TIMEOUT"
|
|
313
|
+
else -> "E_UNEXPECTED"
|
|
314
|
+
}
|
|
315
|
+
}
|
|
158
316
|
) {
|
|
159
317
|
scope.launch {
|
|
160
318
|
try {
|
|
@@ -170,14 +328,26 @@ class BackupCardSdkModule(val reactContext: ReactApplicationContext) :
|
|
|
170
328
|
}
|
|
171
329
|
|
|
172
330
|
override fun onHostResume() {
|
|
173
|
-
|
|
331
|
+
runCatching {
|
|
332
|
+
val sdk = ensureBackupCardSdk(Utils.getTopActivity())
|
|
333
|
+
sdk?.onActivityResumed()
|
|
334
|
+
if (sdk != null) {
|
|
335
|
+
Log.i(tag, "NFC foreground dispatch enabled automatically on app resume.")
|
|
336
|
+
} else {
|
|
337
|
+
Log.w(tag, "Skipped NFC foreground dispatch: no foreground activity.")
|
|
338
|
+
}
|
|
339
|
+
}.onFailure {
|
|
340
|
+
Log.e(tag, "Failed to enable NFC foreground dispatch on resume", it)
|
|
341
|
+
}
|
|
174
342
|
}
|
|
175
343
|
|
|
176
344
|
override fun onHostPause() {
|
|
177
|
-
backupCardSdk
|
|
345
|
+
runCatching { backupCardSdk?.onActivityPaused() }
|
|
346
|
+
.onFailure { Log.e(tag, "Failed to disable NFC foreground dispatch on pause", it) }
|
|
178
347
|
}
|
|
179
348
|
|
|
180
349
|
override fun onHostDestroy() {
|
|
181
|
-
backupCardSdk
|
|
350
|
+
runCatching { backupCardSdk?.onActivityDestroyed() }
|
|
351
|
+
.onFailure { Log.e(tag, "Failed to cleanup NFC on destroy", it) }
|
|
182
352
|
}
|
|
183
353
|
}
|
|
@@ -22,7 +22,7 @@ class BackupCardSdkPackage : BaseReactPackage() {
|
|
|
22
22
|
name = BackupCardSdkModule.NAME,
|
|
23
23
|
className = BackupCardSdkModule.NAME,
|
|
24
24
|
canOverrideExistingModule = false,
|
|
25
|
-
needsEagerInit =
|
|
25
|
+
needsEagerInit = true,
|
|
26
26
|
isCxxModule = false,
|
|
27
27
|
isTurboModule = true
|
|
28
28
|
)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
package com.ziancube.reactnativebackupcardsdk.nfc
|
|
2
|
+
|
|
3
|
+
sealed class NfcExceptions(val code: Int, override val message: String? = null) : Exception(message) {
|
|
4
|
+
class InitializedException(message: String? = null) : NfcExceptions(4001, message)
|
|
5
|
+
|
|
6
|
+
class NotExistsNFC(message: String? = null) : NfcExceptions(1001, message)
|
|
7
|
+
|
|
8
|
+
class NotEnableNFC(message: String? = null) : NfcExceptions(1002, message)
|
|
9
|
+
|
|
10
|
+
class NotNFCPermission(message: String? = null) : NfcExceptions(1003, message)
|
|
11
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
package com.ziancube.reactnativebackupcardsdk.nfc
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.content.Intent
|
|
5
|
+
import android.nfc.NfcAdapter
|
|
6
|
+
import android.provider.Settings
|
|
7
|
+
|
|
8
|
+
object NfcUtils {
|
|
9
|
+
fun isNfcExits(context: Context): Boolean {
|
|
10
|
+
return NfcAdapter.getDefaultAdapter(context) != null
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
fun isNfcEnable(context: Context): Boolean {
|
|
14
|
+
val nfcAdapter = NfcAdapter.getDefaultAdapter(context)
|
|
15
|
+
return nfcAdapter != null && nfcAdapter.isEnabled
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
fun intentToNfcSetting(context: Context): Boolean {
|
|
19
|
+
if (!isNfcExits(context)) {
|
|
20
|
+
return false
|
|
21
|
+
}
|
|
22
|
+
return try {
|
|
23
|
+
context.startActivity(Intent(Settings.ACTION_NFC_SETTINGS))
|
|
24
|
+
true
|
|
25
|
+
} catch (ex: Exception) {
|
|
26
|
+
ex.printStackTrace()
|
|
27
|
+
false
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
package com.ziancube.reactnativebackupcardsdk.utils
|
|
2
|
+
|
|
3
|
+
import android.app.AppOpsManager
|
|
4
|
+
import android.content.Context
|
|
5
|
+
import android.content.Intent
|
|
6
|
+
import android.net.Uri
|
|
7
|
+
import android.os.Build
|
|
8
|
+
import android.provider.Settings
|
|
9
|
+
import android.util.Log
|
|
10
|
+
import androidx.annotation.IntDef
|
|
11
|
+
import androidx.annotation.RequiresApi
|
|
12
|
+
|
|
13
|
+
object MiUtil {
|
|
14
|
+
private const val TAG = "BackupCardSdkMiUtil"
|
|
15
|
+
|
|
16
|
+
@IntDef(
|
|
17
|
+
value =
|
|
18
|
+
[
|
|
19
|
+
PermissionResult.PERMISSION_GRANTED,
|
|
20
|
+
PermissionResult.PERMISSION_DENIED,
|
|
21
|
+
PermissionResult.PERMISSION_ASK,
|
|
22
|
+
PermissionResult.PERMISSION_UNKNOWN,
|
|
23
|
+
]
|
|
24
|
+
)
|
|
25
|
+
@Retention(AnnotationRetention.SOURCE)
|
|
26
|
+
annotation class PermissionResult {
|
|
27
|
+
companion object {
|
|
28
|
+
const val PERMISSION_GRANTED = 0
|
|
29
|
+
const val PERMISSION_DENIED = -1
|
|
30
|
+
const val PERMISSION_ASK = 1
|
|
31
|
+
const val PERMISSION_UNKNOWN = 2
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@PermissionResult
|
|
36
|
+
@RequiresApi(Build.VERSION_CODES.KITKAT)
|
|
37
|
+
fun checkNfcPermission(context: Context): Int {
|
|
38
|
+
try {
|
|
39
|
+
val appOps = context.getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
|
|
40
|
+
val pkg = context.applicationContext.packageName
|
|
41
|
+
val uid = context.applicationInfo.uid
|
|
42
|
+
val appOpsClass = Class.forName(AppOpsManager::class.java.name)
|
|
43
|
+
val checkOpNoThrowMethod =
|
|
44
|
+
appOpsClass.getDeclaredMethod(
|
|
45
|
+
"checkOpNoThrow",
|
|
46
|
+
Integer.TYPE,
|
|
47
|
+
Integer.TYPE,
|
|
48
|
+
String::class.java,
|
|
49
|
+
)
|
|
50
|
+
val invoke = checkOpNoThrowMethod.invoke(appOps, 10016, uid, pkg) ?: return PermissionResult.PERMISSION_UNKNOWN
|
|
51
|
+
return when (invoke.toString()) {
|
|
52
|
+
"0" -> PermissionResult.PERMISSION_GRANTED
|
|
53
|
+
"1" -> PermissionResult.PERMISSION_DENIED
|
|
54
|
+
"5" -> PermissionResult.PERMISSION_ASK
|
|
55
|
+
else -> PermissionResult.PERMISSION_UNKNOWN
|
|
56
|
+
}
|
|
57
|
+
} catch (e: Exception) {
|
|
58
|
+
Log.d(TAG, "check nfc permission fail: ${e.message}")
|
|
59
|
+
}
|
|
60
|
+
return PermissionResult.PERMISSION_UNKNOWN
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
fun intentToAppSetting(context: Context): Boolean {
|
|
64
|
+
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
|
|
65
|
+
intent.data = Uri.fromParts("package", context.packageName, null)
|
|
66
|
+
return try {
|
|
67
|
+
context.startActivity(intent)
|
|
68
|
+
true
|
|
69
|
+
} catch (e: Exception) {
|
|
70
|
+
Log.d(TAG, "open app setting fail: ${e.message}")
|
|
71
|
+
false
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
package/android/src/main/java/com/ziancube/reactnativebackupcardsdk/utils/NfcPermissionUtils.kt
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
package com.ziancube.reactnativebackupcardsdk.utils
|
|
2
|
+
|
|
3
|
+
import android.app.Activity
|
|
4
|
+
import android.os.Build
|
|
5
|
+
|
|
6
|
+
object NfcPermissionUtils {
|
|
7
|
+
inline fun checkPermission(activity: Activity, doNext: () -> Unit): Int {
|
|
8
|
+
return if ("xiaomi".equals(Build.MANUFACTURER, ignoreCase = true)) {
|
|
9
|
+
checkMiuiPermission(activity, doNext)
|
|
10
|
+
} else {
|
|
11
|
+
doNext.invoke()
|
|
12
|
+
0
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
inline fun checkMiuiPermission(activity: Activity, doNext: () -> Unit): Int {
|
|
17
|
+
when (MiUtil.checkNfcPermission(activity)) {
|
|
18
|
+
MiUtil.PermissionResult.PERMISSION_GRANTED -> doNext.invoke()
|
|
19
|
+
else -> {}
|
|
20
|
+
}
|
|
21
|
+
return MiUtil.checkNfcPermission(activity)
|
|
22
|
+
}
|
|
23
|
+
}
|