@onekeyfe/react-native-lite-card 0.1.2
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/LICENSE +20 -0
- package/README.md +37 -0
- package/ReactNativeLiteCard.podspec +22 -0
- package/android/build.gradle +79 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/config/command.json +205 -0
- package/android/src/main/cpp/CMakeLists.txt +19 -0
- package/android/src/main/cpp/validation.c +227 -0
- package/android/src/main/cpp/validation.h +19 -0
- package/android/src/main/java/com/onekeyfe/reactnativelitecard/LoggerManager.kt +35 -0
- package/android/src/main/java/com/onekeyfe/reactnativelitecard/ReactNativeLiteCardModule.kt +420 -0
- package/android/src/main/java/com/onekeyfe/reactnativelitecard/ReactNativeLiteCardPackage.kt +33 -0
- package/android/src/main/java/com/onekeyfe/reactnativelitecard/keys/KeysNativeProvider.kt +13 -0
- package/android/src/main/java/com/onekeyfe/reactnativelitecard/nfc/Exceptions.kt +58 -0
- package/android/src/main/java/com/onekeyfe/reactnativelitecard/nfc/NfcUtils.kt +142 -0
- package/android/src/main/java/com/onekeyfe/reactnativelitecard/nfc/broadcast/NfcStatusChangeBroadcastReceiver.kt +56 -0
- package/android/src/main/java/com/onekeyfe/reactnativelitecard/nfc/gpchannel/GPChannelNatives.kt +32 -0
- package/android/src/main/java/com/onekeyfe/reactnativelitecard/onekeyLite/NfcConstant.kt +38 -0
- package/android/src/main/java/com/onekeyfe/reactnativelitecard/onekeyLite/OnekeyLiteCard.kt +236 -0
- package/android/src/main/java/com/onekeyfe/reactnativelitecard/onekeyLite/entitys/APDUParam.kt +17 -0
- package/android/src/main/java/com/onekeyfe/reactnativelitecard/onekeyLite/entitys/CardInfo.java +84 -0
- package/android/src/main/java/com/onekeyfe/reactnativelitecard/onekeyLite/entitys/CardResponse.java +37 -0
- package/android/src/main/java/com/onekeyfe/reactnativelitecard/onekeyLite/entitys/CardState.kt +10 -0
- package/android/src/main/java/com/onekeyfe/reactnativelitecard/onekeyLite/entitys/ParsedCertInfo.java +39 -0
- package/android/src/main/java/com/onekeyfe/reactnativelitecard/onekeyLite/entitys/SecureChanelParam.java +113 -0
- package/android/src/main/java/com/onekeyfe/reactnativelitecard/onekeyLite/entitys/SendResponse.kt +26 -0
- package/android/src/main/java/com/onekeyfe/reactnativelitecard/onekeyLite/nfc/CommandGenerator.kt +178 -0
- package/android/src/main/java/com/onekeyfe/reactnativelitecard/onekeyLite/nfc/Connection.kt +439 -0
- package/android/src/main/java/com/onekeyfe/reactnativelitecard/onekeyLite/nfc/GPCAPDUGenerator.kt +56 -0
- package/android/src/main/java/com/onekeyfe/reactnativelitecard/utils/EventUtils.kt +14 -0
- package/android/src/main/java/com/onekeyfe/reactnativelitecard/utils/GpsUtil.kt +38 -0
- package/android/src/main/java/com/onekeyfe/reactnativelitecard/utils/HexUtils.java +93 -0
- package/android/src/main/java/com/onekeyfe/reactnativelitecard/utils/LogUtil.kt +11 -0
- package/android/src/main/java/com/onekeyfe/reactnativelitecard/utils/MiUtil.kt +93 -0
- package/android/src/main/java/com/onekeyfe/reactnativelitecard/utils/NfcPermissionUtils.kt +24 -0
- package/android/src/main/java/com/onekeyfe/reactnativelitecard/utils/Utils.java +437 -0
- package/android/src/main/jniLibs/arm64-v8a/libgpchannelNDK.so +0 -0
- package/android/src/main/jniLibs/armeabi-v7a/libgpchannelNDK.so +0 -0
- package/ios/Classes/OKLiteCommand/OKLiteCommandModal.h +39 -0
- package/ios/Classes/OKLiteCommand/OKLiteCommandModal.m +143 -0
- package/ios/Classes/OKLiteCommand/OKLiteCommandTool.h +28 -0
- package/ios/Classes/OKLiteCommand/OKLiteCommandTool.m +53 -0
- package/ios/Classes/OKNFCBridge.h +28 -0
- package/ios/Classes/OKNFCBridge.mm +221 -0
- package/ios/Classes/OKNFCLiteDefine.h +108 -0
- package/ios/Classes/OKNFTLite/OKLiteProtocol.h +37 -0
- package/ios/Classes/OKNFTLite/OKLiteV1.h +41 -0
- package/ios/Classes/OKNFTLite/OKLiteV1.m +609 -0
- package/ios/Classes/OKNFTLite/OKLiteV2.h +17 -0
- package/ios/Classes/OKNFTLite/OKLiteV2.m +132 -0
- package/ios/Classes/OKNFTLite/OKNFCManager.h +40 -0
- package/ios/Classes/OKNFTLite/OKNFCManager.m +330 -0
- package/ios/Classes/Utils/NFCConfig.h +19 -0
- package/ios/Classes/Utils/NFCConfig.m +18 -0
- package/ios/Classes/Utils/NSData+OKNFCHexData.h +17 -0
- package/ios/Classes/Utils/NSData+OKNFCHexData.m +24 -0
- package/ios/Classes/Utils/NSData+StringToData.h +12 -0
- package/ios/Classes/Utils/NSData+StringToData.m +25 -0
- package/ios/Classes/Utils/NSString+OKAdd.h +14 -0
- package/ios/Classes/Utils/NSString+OKAdd.m +40 -0
- package/ios/Classes/Utils/NSString+OKNFCHexStr.h +18 -0
- package/ios/Classes/Utils/NSString+OKNFCHexStr.m +38 -0
- package/ios/Classes/Utils/OKNFCUtility.h +18 -0
- package/ios/Classes/Utils/OKNFCUtility.m +22 -0
- package/ios/Classes/Utils/OKTools.h +17 -0
- package/ios/Classes/Utils/OKTools.m +21 -0
- package/ios/GPChannelSDKCore.xcframework/Info.plist +52 -0
- package/ios/GPChannelSDKCore.xcframework/ios-arm64/GPChannelSDKCore.framework/GPChannelSDKCore +0 -0
- package/ios/GPChannelSDKCore.xcframework/ios-arm64/GPChannelSDKCore.framework/Headers/GPChannelSDK.h +315 -0
- package/ios/GPChannelSDKCore.xcframework/ios-arm64/GPChannelSDKCore.framework/Headers/GPChannelSDKCore.h +19 -0
- package/ios/GPChannelSDKCore.xcframework/ios-arm64/GPChannelSDKCore.framework/Info.plist +0 -0
- package/ios/GPChannelSDKCore.xcframework/ios-arm64/GPChannelSDKCore.framework/Modules/module.modulemap +7 -0
- package/ios/GPChannelSDKCore.xcframework/ios-arm64/GPChannelSDKCore.framework/_CodeSignature/CodeResources +147 -0
- package/ios/GPChannelSDKCore.xcframework/ios-arm64_x86_64-simulator/GPChannelSDKCore.framework/GPChannelSDKCore +0 -0
- package/ios/GPChannelSDKCore.xcframework/ios-arm64_x86_64-simulator/GPChannelSDKCore.framework/Headers/GPChannelSDK.h +315 -0
- package/ios/GPChannelSDKCore.xcframework/ios-arm64_x86_64-simulator/GPChannelSDKCore.framework/Headers/GPChannelSDKCore.h +19 -0
- package/ios/GPChannelSDKCore.xcframework/ios-arm64_x86_64-simulator/GPChannelSDKCore.framework/Info.plist +0 -0
- package/ios/GPChannelSDKCore.xcframework/ios-arm64_x86_64-simulator/GPChannelSDKCore.framework/Modules/module.modulemap +7 -0
- package/ios/GPChannelSDKCore.xcframework/ios-arm64_x86_64-simulator/GPChannelSDKCore.framework/_CodeSignature/CodeResources +147 -0
- package/ios/ReactNativeLiteCard.h +5 -0
- package/ios/ReactNativeLiteCard.mm +222 -0
- package/lib/module/NativeReactNativeLiteCard.js +25 -0
- package/lib/module/NativeReactNativeLiteCard.js.map +1 -0
- package/lib/module/index.js +71 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/NativeReactNativeLiteCard.d.ts +59 -0
- package/lib/typescript/src/NativeReactNativeLiteCard.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +23 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/package.json +168 -0
- package/src/NativeReactNativeLiteCard.ts +112 -0
- package/src/index.tsx +94 -0
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
package com.onekeyfe.reactnativelitecard
|
|
2
|
+
|
|
3
|
+
import android.content.Intent
|
|
4
|
+
import android.nfc.NfcAdapter
|
|
5
|
+
import android.nfc.Tag
|
|
6
|
+
import android.nfc.tech.IsoDep
|
|
7
|
+
import android.util.Log
|
|
8
|
+
import androidx.annotation.IntDef
|
|
9
|
+
import androidx.fragment.app.FragmentActivity
|
|
10
|
+
import kotlinx.coroutines.*
|
|
11
|
+
import kotlinx.coroutines.channels.Channel
|
|
12
|
+
import com.facebook.react.bridge.Callback
|
|
13
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
14
|
+
import com.facebook.react.module.annotations.ReactModule
|
|
15
|
+
import so.onekey.app.wallet.lite.nfc.NFCExceptions
|
|
16
|
+
import so.onekey.app.wallet.lite.nfc.NfcUtils
|
|
17
|
+
import so.onekey.app.wallet.lite.onekeyLite.OneKeyLiteCard
|
|
18
|
+
import so.onekey.app.wallet.lite.onekeyLite.entitys.CardState
|
|
19
|
+
import so.onekey.app.wallet.lite.utils.NfcPermissionUtils
|
|
20
|
+
import so.onekey.app.wallet.lite.utils.Utils
|
|
21
|
+
import java.util.concurrent.atomic.AtomicInteger
|
|
22
|
+
import com.facebook.react.bridge.Arguments
|
|
23
|
+
import com.facebook.react.bridge.BaseActivityEventListener
|
|
24
|
+
import com.facebook.react.bridge.LifecycleEventListener
|
|
25
|
+
import com.facebook.react.bridge.WritableMap
|
|
26
|
+
import so.onekey.app.wallet.lite.nfc.broadcast.NfcStatusChangeBroadcastReceiver
|
|
27
|
+
import java.util.concurrent.Executors.newFixedThreadPool
|
|
28
|
+
|
|
29
|
+
private val NFCDispatcher = newFixedThreadPool(1).asCoroutineDispatcher()
|
|
30
|
+
public fun NFCScope(): CoroutineScope = CoroutineScope(SupervisorJob() + NFCDispatcher)
|
|
31
|
+
|
|
32
|
+
@ReactModule(name = ReactNativeLiteCardModule.NAME)
|
|
33
|
+
class ReactNativeLiteCardModule(reactContext: ReactApplicationContext) :
|
|
34
|
+
NativeReactNativeLiteCardSpec(reactContext), LifecycleEventListener, CoroutineScope by NFCScope() {
|
|
35
|
+
|
|
36
|
+
companion object {
|
|
37
|
+
const val NAME = "ReactNativeLiteCard"
|
|
38
|
+
private val TAG = ReactNativeLiteCardModule::class.simpleName
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@IntDef(NFCState.Dead, NFCState.Started)
|
|
42
|
+
annotation class NFCState {
|
|
43
|
+
companion object {
|
|
44
|
+
const val Dead = -1
|
|
45
|
+
const val Started = 0
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
override fun getName(): String {
|
|
50
|
+
return NAME
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
private val mNFCConnectedChannel = Channel<IsoDep?>(1)
|
|
54
|
+
private var lastIsoDep: IsoDep? = null
|
|
55
|
+
private val mNFCState = AtomicInteger(NFCState.Dead)
|
|
56
|
+
private val mShowDialogNumber = AtomicInteger(0)
|
|
57
|
+
private var mCurrentCardState: CardState? = null
|
|
58
|
+
|
|
59
|
+
private val mActivityEventListener = object : BaseActivityEventListener() {
|
|
60
|
+
override fun onNewIntent(intent: Intent) {
|
|
61
|
+
super.onNewIntent(intent)
|
|
62
|
+
val action = intent.action
|
|
63
|
+
if (action == null) {
|
|
64
|
+
return
|
|
65
|
+
}
|
|
66
|
+
if ((action == NfcAdapter.ACTION_NDEF_DISCOVERED)
|
|
67
|
+
|| action == NfcAdapter.ACTION_TECH_DISCOVERED
|
|
68
|
+
|| action == NfcAdapter.ACTION_TAG_DISCOVERED
|
|
69
|
+
) {
|
|
70
|
+
val tags = intent.getParcelableExtra<Tag>(NfcAdapter.EXTRA_TAG)
|
|
71
|
+
val isoDep: IsoDep? = IsoDep.get(tags)
|
|
72
|
+
if (isoDep == null) {
|
|
73
|
+
// 未知设备
|
|
74
|
+
val dataMap = Arguments.createMap().apply {
|
|
75
|
+
putString("type", "unknown")
|
|
76
|
+
}
|
|
77
|
+
emitOnNFCActiveConnection(dataMap)
|
|
78
|
+
Log.d(TAG, "Unknown device")
|
|
79
|
+
return
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
Log.d(TAG, isoDep.toString())
|
|
83
|
+
launch(Dispatchers.IO) {
|
|
84
|
+
mNFCConnectedChannel.trySend(isoDep)
|
|
85
|
+
try {
|
|
86
|
+
// 处理主动触发 NFC
|
|
87
|
+
delay(100)
|
|
88
|
+
if (!mNFCConnectedChannel.isEmpty) {
|
|
89
|
+
Log.e(TAG, "There is no way to use NFC")
|
|
90
|
+
// mNFCConnectedChannel.receive()
|
|
91
|
+
val startRequest = OneKeyLiteCard.initRequest(isoDep)
|
|
92
|
+
val dataMap = Arguments.createMap().apply {
|
|
93
|
+
putInt("code", -1)
|
|
94
|
+
putString("type", "OneKey_Lite")
|
|
95
|
+
putString("serialNum", startRequest.serialNum)
|
|
96
|
+
putBoolean("isNewCard", startRequest.isNewCard)
|
|
97
|
+
putBoolean("hasBackup", startRequest.hasBackup)
|
|
98
|
+
}
|
|
99
|
+
emitOnNFCActiveConnection(dataMap)
|
|
100
|
+
}
|
|
101
|
+
} catch (e: Exception) {
|
|
102
|
+
e.printStackTrace()
|
|
103
|
+
// 未知设备或连接失败
|
|
104
|
+
val dataMap = Arguments.createMap().apply {
|
|
105
|
+
putInt("code", -1)
|
|
106
|
+
putString("type", "unknown")
|
|
107
|
+
}
|
|
108
|
+
emitOnNFCActiveConnection(dataMap)
|
|
109
|
+
emitOnNFCActiveConnection(dataMap)
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
init {
|
|
117
|
+
reactContext.addLifecycleEventListener(this)
|
|
118
|
+
reactContext.addActivityEventListener(mActivityEventListener)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
private fun releaseDevice() {
|
|
122
|
+
if (mShowDialogNumber.get() <= 0) return
|
|
123
|
+
|
|
124
|
+
mCurrentCardState = null
|
|
125
|
+
val decrementAndGet = mShowDialogNumber.decrementAndGet()
|
|
126
|
+
|
|
127
|
+
// 关闭连接结束 ui
|
|
128
|
+
emitOnNFCUIEvent(Arguments.createMap().also {
|
|
129
|
+
it.putInt("code", 3)
|
|
130
|
+
it.putString("message", "close_connect_ui")
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
// 还有需要处理的 NFC 事件
|
|
134
|
+
if (decrementAndGet > 0) {
|
|
135
|
+
// 展示连接 ui
|
|
136
|
+
emitOnNFCUIEvent(Arguments.createMap().also {
|
|
137
|
+
it.putInt("code", 1)
|
|
138
|
+
it.putString("message", "show_connect_ui")
|
|
139
|
+
})
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
@Throws(NFCExceptions::class)
|
|
144
|
+
private suspend fun acquireDevice(): IsoDep? {
|
|
145
|
+
// 展示连接 ui
|
|
146
|
+
emitOnNFCUIEvent(Arguments.createMap().also {
|
|
147
|
+
it.putInt("code", 1)
|
|
148
|
+
it.putString("message", "show_connect_ui")
|
|
149
|
+
})
|
|
150
|
+
mShowDialogNumber.incrementAndGet()
|
|
151
|
+
val tryReceiveResult = mNFCConnectedChannel.tryReceive()
|
|
152
|
+
|
|
153
|
+
fun IsoDep?.isSafeConnected(): Boolean {
|
|
154
|
+
return runCatching { this?.isConnected ?: false }.getOrDefault(false)
|
|
155
|
+
}
|
|
156
|
+
var receiveIsoDep: IsoDep? = null
|
|
157
|
+
|
|
158
|
+
if (tryReceiveResult.isSuccess) {
|
|
159
|
+
receiveIsoDep = tryReceiveResult.getOrNull()
|
|
160
|
+
if (!receiveIsoDep.isSafeConnected()) {
|
|
161
|
+
receiveIsoDep = null
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (receiveIsoDep == null && lastIsoDep.isSafeConnected()) {
|
|
166
|
+
receiveIsoDep = lastIsoDep
|
|
167
|
+
}
|
|
168
|
+
if (receiveIsoDep == null) {
|
|
169
|
+
receiveIsoDep = mNFCConnectedChannel.receive()
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
lastIsoDep = receiveIsoDep
|
|
173
|
+
if (receiveIsoDep == null) {
|
|
174
|
+
// 取消连接
|
|
175
|
+
releaseDevice()
|
|
176
|
+
} else {
|
|
177
|
+
val initChannelRequest = OneKeyLiteCard.initRequest(receiveIsoDep)
|
|
178
|
+
|
|
179
|
+
mCurrentCardState = initChannelRequest
|
|
180
|
+
|
|
181
|
+
// 展示连接结束 ui
|
|
182
|
+
emitOnNFCUIEvent(Arguments.createMap().also {
|
|
183
|
+
it.putInt("code", 2)
|
|
184
|
+
it.putString("message", "connected")
|
|
185
|
+
})
|
|
186
|
+
}
|
|
187
|
+
return receiveIsoDep
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
private suspend fun <T> handleOperation(
|
|
191
|
+
callback: Callback?,
|
|
192
|
+
execute: (isoDep: IsoDep) -> T
|
|
193
|
+
) {
|
|
194
|
+
val topActivity = Utils.getTopActivity() ?: return
|
|
195
|
+
NfcPermissionUtils.checkPermission(topActivity) {
|
|
196
|
+
try {
|
|
197
|
+
Log.d(TAG, "NFC permission check success")
|
|
198
|
+
val isoDep = acquireDevice() ?: return
|
|
199
|
+
val executeResult = execute(isoDep)
|
|
200
|
+
callback?.invoke(null, executeResult, mCurrentCardState.createArguments())
|
|
201
|
+
} catch (e: NFCExceptions) {
|
|
202
|
+
Log.e(TAG, "NFC device execute error", e)
|
|
203
|
+
callback?.invoke(e.createArguments(), null, mCurrentCardState.createArguments())
|
|
204
|
+
} finally {
|
|
205
|
+
releaseDevice()
|
|
206
|
+
}
|
|
207
|
+
return
|
|
208
|
+
}
|
|
209
|
+
// 没有 NFC 使用权限
|
|
210
|
+
Log.d(TAG, "NFC device not permission")
|
|
211
|
+
callback?.invoke(NFCExceptions.NotNFCPermission().createArguments(), null, null)
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
private fun CardState?.createArguments(): WritableMap {
|
|
215
|
+
val map = Arguments.createMap()
|
|
216
|
+
if (this == null) return map
|
|
217
|
+
map.putBoolean("hasBackup", this.hasBackup)
|
|
218
|
+
map.putBoolean("isNewCard", this.isNewCard)
|
|
219
|
+
map.putString("serialNum", this.serialNum)
|
|
220
|
+
map.putInt("pinRetryCount", this.pinRetryCount)
|
|
221
|
+
return map
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
private fun NFCExceptions?.createArguments(): WritableMap {
|
|
225
|
+
val map = Arguments.createMap()
|
|
226
|
+
if (this == null) return map
|
|
227
|
+
map.putInt("code", this.code)
|
|
228
|
+
map.putString("message", this.message)
|
|
229
|
+
return map
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
override fun getLiteInfo(callback: Callback?) {
|
|
233
|
+
launch {
|
|
234
|
+
Log.d(TAG, "getLiteInfo")
|
|
235
|
+
handleOperation<Any>(callback) { isoDep ->
|
|
236
|
+
Log.e(TAG, "getLiteInfo Obtain the device")
|
|
237
|
+
val cardInfo = OneKeyLiteCard.getCardInfo(isoDep)
|
|
238
|
+
Log.e(TAG, "getLiteInfo result $cardInfo")
|
|
239
|
+
cardInfo.createArguments()
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
override fun checkNFCPermission(callback: Callback?) {
|
|
245
|
+
val topActivity = Utils.getTopActivity()
|
|
246
|
+
if (topActivity == null) {
|
|
247
|
+
callback?.invoke(NFCExceptions.InitializedException().createArguments(), null, null)
|
|
248
|
+
return
|
|
249
|
+
}
|
|
250
|
+
val isNfcExists = NfcUtils.isNfcExits(topActivity)
|
|
251
|
+
if (!isNfcExists) {
|
|
252
|
+
// 没有 NFC 设备
|
|
253
|
+
Log.d(TAG, "NFC device not found")
|
|
254
|
+
callback?.invoke(NFCExceptions.NotExistsNFC().createArguments(), null, null)
|
|
255
|
+
return
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
val isNfcEnable = NfcUtils.isNfcEnable(topActivity)
|
|
259
|
+
if (!isNfcEnable) {
|
|
260
|
+
// 没有打开 NFC 开关
|
|
261
|
+
Log.d(TAG, "NFC device not enable")
|
|
262
|
+
callback?.invoke(NFCExceptions.NotEnableNFC().createArguments(), null, null)
|
|
263
|
+
return
|
|
264
|
+
}
|
|
265
|
+
NfcPermissionUtils.checkPermission(topActivity) {
|
|
266
|
+
callback?.invoke(null, null, null)
|
|
267
|
+
return
|
|
268
|
+
}
|
|
269
|
+
// 没有 NFC 使用权限
|
|
270
|
+
Log.d(TAG, "NFC device not permission")
|
|
271
|
+
callback?.invoke(NFCExceptions.NotNFCPermission().createArguments(), null, null)
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
override fun setMnemonic(
|
|
275
|
+
mnemonic: String?,
|
|
276
|
+
pwd: String?,
|
|
277
|
+
overwrite: Boolean,
|
|
278
|
+
callback: Callback?
|
|
279
|
+
) {
|
|
280
|
+
launch {
|
|
281
|
+
handleOperation(callback) { isoDep ->
|
|
282
|
+
Log.e(TAG, "setMnemonic Obtain the device")
|
|
283
|
+
val isSuccess =
|
|
284
|
+
OneKeyLiteCard.setMnemonic(
|
|
285
|
+
mCurrentCardState,
|
|
286
|
+
isoDep,
|
|
287
|
+
mnemonic,
|
|
288
|
+
pwd,
|
|
289
|
+
overwrite
|
|
290
|
+
)
|
|
291
|
+
if (!isSuccess) throw NFCExceptions.ExecFailureException()
|
|
292
|
+
Log.e(TAG, "setMnemonic result success")
|
|
293
|
+
true
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
override fun getMnemonicWithPin(
|
|
299
|
+
pwd: String,
|
|
300
|
+
callback: Callback?
|
|
301
|
+
) {
|
|
302
|
+
launch {
|
|
303
|
+
Log.d(TAG, "getMnemonicWithPin")
|
|
304
|
+
handleOperation(callback) { isoDep ->
|
|
305
|
+
Log.e(TAG, "getMnemonicWithPin Obtain the device")
|
|
306
|
+
OneKeyLiteCard.getMnemonicWithPin(mCurrentCardState, isoDep, pwd)
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
override fun changePin(
|
|
312
|
+
oldPin: String,
|
|
313
|
+
newPin: String,
|
|
314
|
+
callback: Callback?
|
|
315
|
+
) {
|
|
316
|
+
launch {
|
|
317
|
+
Log.d(TAG, "changePin")
|
|
318
|
+
handleOperation(callback) { isoDep ->
|
|
319
|
+
Log.e(TAG, "changePin Obtain the device")
|
|
320
|
+
OneKeyLiteCard.changPin(mCurrentCardState, isoDep, oldPin, newPin)
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
override fun reset(callback: Callback?) {
|
|
326
|
+
launch {
|
|
327
|
+
Log.d(TAG, "reset")
|
|
328
|
+
handleOperation(callback) { isoDep ->
|
|
329
|
+
Log.e(TAG, "reset Obtain the device")
|
|
330
|
+
val isSuccess = OneKeyLiteCard.reset(isoDep)
|
|
331
|
+
if (!isSuccess) throw NFCExceptions.ExecFailureException()
|
|
332
|
+
Log.e(TAG, "reset result success")
|
|
333
|
+
true
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
override fun cancel() {
|
|
339
|
+
if (mNFCConnectedChannel.isEmpty) {
|
|
340
|
+
mNFCConnectedChannel.trySend(null)
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
override fun intoSetting() {
|
|
345
|
+
launch {
|
|
346
|
+
Log.d(TAG, "intoSetting")
|
|
347
|
+
Utils.getTopActivity()?.let {
|
|
348
|
+
NfcUtils.intentToNfcSetting(it)
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
private val mNfcStateBroadcastReceiver by lazy {
|
|
354
|
+
object : NfcStatusChangeBroadcastReceiver() {
|
|
355
|
+
override fun onCardPayMode() {
|
|
356
|
+
super.onCardPayMode()
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
override fun onNfcOff() {
|
|
360
|
+
super.onNfcOff()
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
override fun onNfcOn() {
|
|
364
|
+
super.onNfcOn()
|
|
365
|
+
Utils.getTopActivity()?.let {
|
|
366
|
+
launch(Dispatchers.IO) {
|
|
367
|
+
OneKeyLiteCard.startNfc(it as FragmentActivity) {}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
override fun onNfcTurningOff() {
|
|
373
|
+
super.onNfcTurningOff()
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
override fun onNfcTurningOn() {
|
|
377
|
+
super.onNfcTurningOn()
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
override fun onHostResume() {
|
|
384
|
+
Utils.getTopActivity()?.let {
|
|
385
|
+
launch(Dispatchers.IO) {
|
|
386
|
+
if (it !is FragmentActivity) return@launch
|
|
387
|
+
try {
|
|
388
|
+
OneKeyLiteCard.startNfc(it) {
|
|
389
|
+
mNFCState.set(NFCState.Started)
|
|
390
|
+
|
|
391
|
+
Log.d(TAG, "NFC starting success")
|
|
392
|
+
}
|
|
393
|
+
} catch (e: Exception) {
|
|
394
|
+
Log.e(TAG, "startNfc failed", e)
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
override fun onHostPause() {
|
|
401
|
+
Utils.getTopActivity()?.let {
|
|
402
|
+
launch(Dispatchers.IO) {
|
|
403
|
+
try {
|
|
404
|
+
OneKeyLiteCard.stopNfc(it as FragmentActivity)
|
|
405
|
+
mNFCState.set(NFCState.Dead)
|
|
406
|
+
Log.d(TAG, "NFC 已关闭")
|
|
407
|
+
} catch (e: Exception) {
|
|
408
|
+
Log.e(TAG, "stopNfc failed", e)
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
override fun onHostDestroy() {
|
|
415
|
+
try {
|
|
416
|
+
Utils.getTopActivity()?.unregisterReceiver(mNfcStateBroadcastReceiver)
|
|
417
|
+
} catch (ignore: Exception) {
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
package com.onekeyfe.reactnativelitecard
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.BaseReactPackage
|
|
4
|
+
import com.facebook.react.bridge.NativeModule
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.module.model.ReactModuleInfo
|
|
7
|
+
import com.facebook.react.module.model.ReactModuleInfoProvider
|
|
8
|
+
import java.util.HashMap
|
|
9
|
+
|
|
10
|
+
class ReactNativeLiteCardPackage : BaseReactPackage() {
|
|
11
|
+
override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
|
|
12
|
+
return if (name == ReactNativeLiteCardModule.NAME) {
|
|
13
|
+
ReactNativeLiteCardModule(reactContext)
|
|
14
|
+
} else {
|
|
15
|
+
null
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
|
|
20
|
+
return ReactModuleInfoProvider {
|
|
21
|
+
val moduleInfos: MutableMap<String, ReactModuleInfo> = HashMap()
|
|
22
|
+
moduleInfos[ReactNativeLiteCardModule.NAME] = ReactModuleInfo(
|
|
23
|
+
ReactNativeLiteCardModule.NAME,
|
|
24
|
+
ReactNativeLiteCardModule.NAME,
|
|
25
|
+
false, // canOverrideExistingModule
|
|
26
|
+
false, // needsEagerInit
|
|
27
|
+
false, // isCxxModule
|
|
28
|
+
true // isTurboModule
|
|
29
|
+
)
|
|
30
|
+
moduleInfos
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
package so.onekey.app.wallet.lite.nfc
|
|
2
|
+
|
|
3
|
+
sealed class NFCExceptions(val code: Int, override val message: String? = null) : Exception(message) {
|
|
4
|
+
fun toJson(): String {
|
|
5
|
+
return """{"code":$code,"message":"$message"}"""
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
// 初始化异常
|
|
9
|
+
class InitChannelException(message: String? = null) : NFCExceptions(1000, message)
|
|
10
|
+
|
|
11
|
+
// 没有 NFC 设备
|
|
12
|
+
class NotExistsNFC(message: String? = null) : NFCExceptions(1001, message)
|
|
13
|
+
|
|
14
|
+
// 没有开启 NFC 设备
|
|
15
|
+
class NotEnableNFC(message: String? = null) : NFCExceptions(1002, message)
|
|
16
|
+
|
|
17
|
+
// 没有使用 NFC 的权限
|
|
18
|
+
class NotNFCPermission(message: String? = null) : NFCExceptions(1003, message)
|
|
19
|
+
|
|
20
|
+
// 连接失败
|
|
21
|
+
class ConnectionFailException(message: String? = null) : NFCExceptions(2001, message)
|
|
22
|
+
|
|
23
|
+
// 操作中断(可能是连接问题)
|
|
24
|
+
class InterruptException(message: String? = null) : NFCExceptions(2002, message)
|
|
25
|
+
|
|
26
|
+
// 连接设备不匹配
|
|
27
|
+
class DeviceMismatchException(message: String? = null) : NFCExceptions(2003, message)
|
|
28
|
+
|
|
29
|
+
// 用户主动取消
|
|
30
|
+
class UserCancelExceptions(message: String? = null) : NFCExceptions(2004, message)
|
|
31
|
+
|
|
32
|
+
// 密码错误
|
|
33
|
+
class PasswordWrongException(message: String? = null) : NFCExceptions(3001, message)
|
|
34
|
+
|
|
35
|
+
// 输入密码为空
|
|
36
|
+
class InputPasswordEmptyException(message: String? = null) : NFCExceptions(3002, message)
|
|
37
|
+
|
|
38
|
+
// 未设置过密码
|
|
39
|
+
class PasswordEmptyException(message: String? = null) : NFCExceptions(3003, message)
|
|
40
|
+
|
|
41
|
+
// 设置初始化密码错误
|
|
42
|
+
class InitPasswordException(message: String? = null) : NFCExceptions(3004, message)
|
|
43
|
+
|
|
44
|
+
// 密码重试次数太多已经锁死
|
|
45
|
+
class CardLockException(message: String? = null) : NFCExceptions(3005, message)
|
|
46
|
+
|
|
47
|
+
// 密码重试次数太多已经自动重制卡片
|
|
48
|
+
class UpperErrorAutoResetException(message: String? = null) : NFCExceptions(3006, message)
|
|
49
|
+
|
|
50
|
+
// 未知的命令执行失败
|
|
51
|
+
class ExecFailureException(message: String? = null) : NFCExceptions(4000, message)
|
|
52
|
+
|
|
53
|
+
// 已经备份过内容
|
|
54
|
+
class InitializedException(message: String? = null) : NFCExceptions(4001, message)
|
|
55
|
+
|
|
56
|
+
// 没有备份过内容
|
|
57
|
+
class NotInitializedException(message: String? = null) : NFCExceptions(4002, message)
|
|
58
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
package so.onekey.app.wallet.lite.nfc
|
|
2
|
+
|
|
3
|
+
import android.app.Activity
|
|
4
|
+
import android.app.PendingIntent
|
|
5
|
+
import android.content.Context
|
|
6
|
+
import android.content.Intent
|
|
7
|
+
import android.content.IntentFilter
|
|
8
|
+
import android.nfc.NfcAdapter
|
|
9
|
+
import android.nfc.tech.*
|
|
10
|
+
import android.os.Build
|
|
11
|
+
import android.provider.Settings
|
|
12
|
+
import so.onekey.app.wallet.lite.utils.MiUtil
|
|
13
|
+
|
|
14
|
+
object NfcUtils {
|
|
15
|
+
|
|
16
|
+
@JvmField
|
|
17
|
+
var mNfcAdapter: NfcAdapter? = null
|
|
18
|
+
|
|
19
|
+
@JvmField
|
|
20
|
+
var mIntentFilter: Array<IntentFilter>? = null
|
|
21
|
+
|
|
22
|
+
@JvmField
|
|
23
|
+
var mPendingIntent: PendingIntent? = null
|
|
24
|
+
|
|
25
|
+
@JvmField
|
|
26
|
+
var mTechList: Array<Array<String>>? = null
|
|
27
|
+
|
|
28
|
+
private fun getPendingIntent(activity: Activity): PendingIntent? {
|
|
29
|
+
val intent = Intent(activity, activity.javaClass)
|
|
30
|
+
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
|
31
|
+
var flag = 0
|
|
32
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
33
|
+
flag = PendingIntent.FLAG_MUTABLE
|
|
34
|
+
} else {
|
|
35
|
+
flag = PendingIntent.FLAG_UPDATE_CURRENT
|
|
36
|
+
}
|
|
37
|
+
return PendingIntent.getActivity(activity, 0, intent, flag)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
private fun getIntentFilters(): Array<IntentFilter> {
|
|
41
|
+
return arrayOf(
|
|
42
|
+
IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED, "*/*"),
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
private fun getTechLists(): Array<Array<String>> {
|
|
47
|
+
return arrayOf(
|
|
48
|
+
arrayOf(NfcA::class.java.name),
|
|
49
|
+
arrayOf(IsoDep::class.java.name)
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@JvmStatic
|
|
54
|
+
fun init(activity: Activity): NfcAdapter? {
|
|
55
|
+
mNfcAdapter = NfcAdapter.getDefaultAdapter(activity)
|
|
56
|
+
mTechList = getTechLists()
|
|
57
|
+
mPendingIntent = getPendingIntent(activity)
|
|
58
|
+
mIntentFilter = getIntentFilters()
|
|
59
|
+
return mNfcAdapter
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* 判断手机是否具备NFC功能.
|
|
64
|
+
*
|
|
65
|
+
* @param context [Context]
|
|
66
|
+
* @return `true`: 具备 `false`: 不具备
|
|
67
|
+
*/
|
|
68
|
+
fun isNfcExits(context: Context): Boolean {
|
|
69
|
+
val nfcAdapter = NfcAdapter.getDefaultAdapter(context)
|
|
70
|
+
return nfcAdapter != null
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* 判断手机NFC是否开启.
|
|
75
|
+
*
|
|
76
|
+
* OPPO A37m 发现必须同时开启NFC以及Android Beam才可以使用
|
|
77
|
+
* 20180108 发现OPPO单独打开NFC即可读取标签,不清楚是否是系统更新
|
|
78
|
+
*
|
|
79
|
+
* @param context [Context]
|
|
80
|
+
* @return `true`: 已开启 `false`: 未开启
|
|
81
|
+
*/
|
|
82
|
+
fun isNfcEnable(context: Context): Boolean {
|
|
83
|
+
val nfcAdapter = NfcAdapter.getDefaultAdapter(context)
|
|
84
|
+
return nfcAdapter != null && nfcAdapter.isEnabled
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* 判断手机是否具备Android Beam.
|
|
89
|
+
*
|
|
90
|
+
* @param context [Context]
|
|
91
|
+
* @return `true`:具备 `false`:不具备
|
|
92
|
+
*/
|
|
93
|
+
fun isAndroidBeamExits(context: Context): Boolean {
|
|
94
|
+
return Build.VERSION.SDK_INT < Build.VERSION_CODES.Q && isNfcExits(context)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* 跳转至系统NFC设置界面.
|
|
99
|
+
*
|
|
100
|
+
* @param context [Context]
|
|
101
|
+
* @return `true` 跳转成功 <br></br> `false` 跳转失败
|
|
102
|
+
*/
|
|
103
|
+
fun intentToNfcSetting(context: Context): Boolean {
|
|
104
|
+
if (isNfcExits(context)) {
|
|
105
|
+
return toIntent(context, Settings.ACTION_NFC_SETTINGS)
|
|
106
|
+
}
|
|
107
|
+
return false
|
|
108
|
+
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* 跳转至系统NFC Android Beam设置界面,同页面基本都有NFC开关.
|
|
113
|
+
*
|
|
114
|
+
* @param context [Context]
|
|
115
|
+
* @return `true` 跳转成功 <br></br> `false` 跳转失败
|
|
116
|
+
*/
|
|
117
|
+
fun intentToNfcShare(context: Context): Boolean {
|
|
118
|
+
return if (isAndroidBeamExits(context)) {
|
|
119
|
+
toIntent(context, Settings.ACTION_NFCSHARING_SETTINGS)
|
|
120
|
+
} else false
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* 跳转方法.
|
|
125
|
+
*
|
|
126
|
+
* @param context [Context]
|
|
127
|
+
* @param action 意图
|
|
128
|
+
* @return 是否跳转成功 `true ` 成功<br></br>`false`失败
|
|
129
|
+
*/
|
|
130
|
+
private fun toIntent(context: Context, action: String): Boolean {
|
|
131
|
+
try {
|
|
132
|
+
val intent = Intent(action)
|
|
133
|
+
context.startActivity(intent)
|
|
134
|
+
} catch (ex: Exception) {
|
|
135
|
+
ex.printStackTrace()
|
|
136
|
+
return false
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return true
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
}
|