@onekeyfe/react-native-lite-card 1.0.0
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/android/build.gradle +102 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +3 -0
- package/android/src/main/assets/config/command.json +205 -0
- package/android/src/main/cpp/CMakeLists.txt +15 -0
- package/android/src/main/cpp/validation.c +227 -0
- package/android/src/main/cpp/validation.h +19 -0
- package/android/src/main/java/so/onekey/app/wallet/LoggerManager.kt +35 -0
- package/android/src/main/java/so/onekey/app/wallet/OKLiteManager.kt +399 -0
- package/android/src/main/java/so/onekey/app/wallet/OKLitePackage.kt +16 -0
- package/android/src/main/java/so/onekey/app/wallet/keys/KeysNativeProvider.kt +13 -0
- package/android/src/main/java/so/onekey/app/wallet/nfc/Exceptions.kt +58 -0
- package/android/src/main/java/so/onekey/app/wallet/nfc/NfcUtils.kt +151 -0
- package/android/src/main/java/so/onekey/app/wallet/nfc/broadcast/NfcStatusChangeBroadcastReceiver.kt +56 -0
- package/android/src/main/java/so/onekey/app/wallet/nfc/gpchannel/GPChannelNatives.kt +32 -0
- package/android/src/main/java/so/onekey/app/wallet/onekeyLite/NfcConstant.kt +38 -0
- package/android/src/main/java/so/onekey/app/wallet/onekeyLite/OnekeyLiteCard.kt +241 -0
- package/android/src/main/java/so/onekey/app/wallet/onekeyLite/entitys/APDUParam.kt +17 -0
- package/android/src/main/java/so/onekey/app/wallet/onekeyLite/entitys/CardInfo.java +84 -0
- package/android/src/main/java/so/onekey/app/wallet/onekeyLite/entitys/CardResponse.java +37 -0
- package/android/src/main/java/so/onekey/app/wallet/onekeyLite/entitys/CardState.kt +10 -0
- package/android/src/main/java/so/onekey/app/wallet/onekeyLite/entitys/ParsedCertInfo.java +39 -0
- package/android/src/main/java/so/onekey/app/wallet/onekeyLite/entitys/SecureChanelParam.java +113 -0
- package/android/src/main/java/so/onekey/app/wallet/onekeyLite/entitys/SendResponse.kt +26 -0
- package/android/src/main/java/so/onekey/app/wallet/onekeyLite/nfc/CommandGenerator.kt +178 -0
- package/android/src/main/java/so/onekey/app/wallet/onekeyLite/nfc/Connection.kt +430 -0
- package/android/src/main/java/so/onekey/app/wallet/onekeyLite/nfc/GPCAPDUGenerator.kt +56 -0
- package/android/src/main/java/so/onekey/app/wallet/utils/EventUtils.kt +14 -0
- package/android/src/main/java/so/onekey/app/wallet/utils/GpsUtil.kt +38 -0
- package/android/src/main/java/so/onekey/app/wallet/utils/HexUtils.java +93 -0
- package/android/src/main/java/so/onekey/app/wallet/utils/LogUtil.kt +11 -0
- package/android/src/main/java/so/onekey/app/wallet/utils/MiUtil.kt +93 -0
- package/android/src/main/java/so/onekey/app/wallet/utils/NfcPermissionUtils.kt +24 -0
- package/android/src/main/java/so/onekey/app/wallet/utils/Utils.java +433 -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/OKLiteManager.h +17 -0
- package/ios/Classes/OKLiteManager.m +222 -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 +602 -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.framework/GPChannelSDKCore +0 -0
- package/ios/GPChannelSDKCore.framework/Headers/GPChannelSDK.h +315 -0
- package/ios/GPChannelSDKCore.framework/Headers/GPChannelSDKCore.h +19 -0
- package/ios/GPChannelSDKCore.framework/Info.plist +0 -0
- package/ios/GPChannelSDKCore.framework/Modules/module.modulemap +7 -0
- package/ios/GPChannelSDKCore.framework/_CodeSignature/CodeResources +147 -0
- package/keys/keys.c +51 -0
- package/keys/keys.h +4 -0
- package/lib/commonjs/index.js +114 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/types.js +27 -0
- package/lib/commonjs/types.js.map +1 -0
- package/lib/module/index.js +108 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/types.js +21 -0
- package/lib/module/types.js.map +1 -0
- package/lib/typescript/src/index.d.ts +35 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +31 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/package.json +166 -0
- package/react-native-lite-card.podspec +42 -0
- package/src/index.ts +154 -0
- package/src/types.ts +37 -0
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
package so.onekey.app.wallet
|
|
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 com.facebook.react.bridge.*
|
|
11
|
+
import com.facebook.react.modules.core.DeviceEventManagerModule.RCTDeviceEventEmitter
|
|
12
|
+
import kotlinx.coroutines.*
|
|
13
|
+
import kotlinx.coroutines.channels.Channel
|
|
14
|
+
import so.onekey.app.wallet.nfc.NFCExceptions
|
|
15
|
+
import so.onekey.app.wallet.nfc.NfcUtils
|
|
16
|
+
import so.onekey.app.wallet.nfc.broadcast.NfcStatusChangeBroadcastReceiver
|
|
17
|
+
import so.onekey.app.wallet.onekeyLite.OneKeyLiteCard
|
|
18
|
+
import so.onekey.app.wallet.onekeyLite.entitys.CardState
|
|
19
|
+
import so.onekey.app.wallet.utils.NfcPermissionUtils
|
|
20
|
+
import so.onekey.app.wallet.utils.Utils
|
|
21
|
+
import java.util.concurrent.Executors
|
|
22
|
+
import java.util.concurrent.atomic.AtomicInteger
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
public fun NFCScope(): CoroutineScope = CoroutineScope(SupervisorJob() + NFCDispatcher)
|
|
26
|
+
private val NFCDispatcher = Executors.newFixedThreadPool(1).asCoroutineDispatcher()
|
|
27
|
+
|
|
28
|
+
class OKLiteManager(private val context: ReactApplicationContext) :
|
|
29
|
+
ReactContextBaseJavaModule(context), LifecycleEventListener, CoroutineScope by NFCScope() {
|
|
30
|
+
companion object {
|
|
31
|
+
private val TAG = OKLiteManager::class.simpleName
|
|
32
|
+
|
|
33
|
+
// NFC UI 事件
|
|
34
|
+
private const val NFC_UI_EVENT = "nfc_ui_event"
|
|
35
|
+
|
|
36
|
+
// NFC 主动连接
|
|
37
|
+
private const val NFC_ACTIVE_CONNECTION = "nfc_active_connection"
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@IntDef(NFCState.Dead, NFCState.Started)
|
|
41
|
+
annotation class NFCState {
|
|
42
|
+
companion object {
|
|
43
|
+
const val Dead = -1
|
|
44
|
+
const val Started = 0
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
private val mNFCConnectedChannel = Channel<IsoDep?>(1)
|
|
49
|
+
private val mNFCState = AtomicInteger(NFCState.Dead)
|
|
50
|
+
private val mShowDialogNumber = AtomicInteger(0)
|
|
51
|
+
private var mCurrentCardState: CardState? = null
|
|
52
|
+
|
|
53
|
+
private val mActivityEventListener = object : BaseActivityEventListener() {
|
|
54
|
+
override fun onNewIntent(intent: Intent?) {
|
|
55
|
+
super.onNewIntent(intent)
|
|
56
|
+
val action = intent?.action
|
|
57
|
+
if ((action == NfcAdapter.ACTION_NDEF_DISCOVERED)
|
|
58
|
+
|| action == NfcAdapter.ACTION_TECH_DISCOVERED
|
|
59
|
+
|| action == NfcAdapter.ACTION_TAG_DISCOVERED
|
|
60
|
+
) {
|
|
61
|
+
val tags = intent.getParcelableExtra<Tag>(NfcAdapter.EXTRA_TAG)
|
|
62
|
+
val isoDep: IsoDep? = IsoDep.get(tags)
|
|
63
|
+
if (isoDep == null) {
|
|
64
|
+
// 未知设备
|
|
65
|
+
val dataMap = Arguments.createMap().apply {
|
|
66
|
+
putString("type", "unknown")
|
|
67
|
+
}
|
|
68
|
+
sendEvent(context, NFC_ACTIVE_CONNECTION, dataMap)
|
|
69
|
+
Log.d(TAG, "Unknown device")
|
|
70
|
+
return
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
Log.d(TAG, isoDep.toString())
|
|
74
|
+
launch(Dispatchers.IO) {
|
|
75
|
+
mNFCConnectedChannel.trySend(isoDep)
|
|
76
|
+
try {
|
|
77
|
+
// 处理主动触发 NFC
|
|
78
|
+
delay(100)
|
|
79
|
+
if (!mNFCConnectedChannel.isEmpty) {
|
|
80
|
+
Log.e(TAG, "There is no way to use NFC")
|
|
81
|
+
mNFCConnectedChannel.receive()
|
|
82
|
+
val startRequest = OneKeyLiteCard.initRequest(isoDep)
|
|
83
|
+
val dataMap = Arguments.createMap().apply {
|
|
84
|
+
putInt("code", -1)
|
|
85
|
+
putString("type", "OneKey_Lite")
|
|
86
|
+
putString("serialNum", startRequest.serialNum)
|
|
87
|
+
putBoolean("isNewCard", startRequest.isNewCard)
|
|
88
|
+
putBoolean("hasBackup", startRequest.hasBackup)
|
|
89
|
+
}
|
|
90
|
+
sendEvent(context, NFC_ACTIVE_CONNECTION, dataMap)
|
|
91
|
+
}
|
|
92
|
+
} catch (e: Exception) {
|
|
93
|
+
e.printStackTrace()
|
|
94
|
+
// 未知设备或连接失败
|
|
95
|
+
val dataMap = Arguments.createMap().apply {
|
|
96
|
+
putInt("code", -1)
|
|
97
|
+
putString("type", "unknown")
|
|
98
|
+
}
|
|
99
|
+
sendEvent(context, NFC_ACTIVE_CONNECTION, dataMap)
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
init {
|
|
107
|
+
context.addLifecycleEventListener(this)
|
|
108
|
+
context.addActivityEventListener(mActivityEventListener)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
override fun getName() = "OKLiteManager"
|
|
112
|
+
|
|
113
|
+
override fun initialize() {
|
|
114
|
+
super.initialize()
|
|
115
|
+
Utils.init(context)
|
|
116
|
+
Utils.getActivityLifecycle()
|
|
117
|
+
Utils.getTopActivity()?.registerReceiver(
|
|
118
|
+
mNfcStateBroadcastReceiver,
|
|
119
|
+
NfcStatusChangeBroadcastReceiver.nfcBroadcastReceiverIntentFilter
|
|
120
|
+
)
|
|
121
|
+
Utils.getTopActivity()?.let {
|
|
122
|
+
launch(Dispatchers.IO) {
|
|
123
|
+
OneKeyLiteCard.startNfc(it as FragmentActivity) {}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
override fun onHostResume() {
|
|
130
|
+
Utils.getTopActivity()?.let {
|
|
131
|
+
launch(Dispatchers.IO) {
|
|
132
|
+
if (it !is FragmentActivity) return@launch
|
|
133
|
+
try {
|
|
134
|
+
OneKeyLiteCard.startNfc(it) {
|
|
135
|
+
mNFCState.set(NFCState.Started)
|
|
136
|
+
|
|
137
|
+
Log.d(TAG, "NFC starting success")
|
|
138
|
+
}
|
|
139
|
+
} catch (e: Exception) {
|
|
140
|
+
Log.e(TAG, "startNfc failed", e)
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
override fun onHostPause() {
|
|
147
|
+
Utils.getTopActivity()?.let {
|
|
148
|
+
launch(Dispatchers.IO) {
|
|
149
|
+
try {
|
|
150
|
+
OneKeyLiteCard.stopNfc(it as FragmentActivity)
|
|
151
|
+
mNFCState.set(NFCState.Dead)
|
|
152
|
+
Log.d(TAG, "NFC 已关闭")
|
|
153
|
+
} catch (e: Exception) {
|
|
154
|
+
Log.e(TAG, "stopNfc failed", e)
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
override fun onHostDestroy() {
|
|
161
|
+
try {
|
|
162
|
+
Utils.getTopActivity()?.unregisterReceiver(mNfcStateBroadcastReceiver)
|
|
163
|
+
} catch (ignore: Exception) {
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
private val mNfcStateBroadcastReceiver by lazy {
|
|
168
|
+
object : NfcStatusChangeBroadcastReceiver() {
|
|
169
|
+
override fun onCardPayMode() {
|
|
170
|
+
super.onCardPayMode()
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
override fun onNfcOff() {
|
|
174
|
+
super.onNfcOff()
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
override fun onNfcOn() {
|
|
178
|
+
super.onNfcOn()
|
|
179
|
+
Utils.getTopActivity()?.let {
|
|
180
|
+
launch(Dispatchers.IO) {
|
|
181
|
+
OneKeyLiteCard.startNfc(it as FragmentActivity) {}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
override fun onNfcTurningOff() {
|
|
187
|
+
super.onNfcTurningOff()
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
override fun onNfcTurningOn() {
|
|
191
|
+
super.onNfcTurningOn()
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
private fun sendEvent(
|
|
197
|
+
reactContext: ReactContext,
|
|
198
|
+
eventName: String,
|
|
199
|
+
params: WritableMap
|
|
200
|
+
) {
|
|
201
|
+
reactContext
|
|
202
|
+
.getJSModule(RCTDeviceEventEmitter::class.java)
|
|
203
|
+
.emit(eventName, params)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
@Throws(NFCExceptions::class)
|
|
207
|
+
private suspend fun acquireDevice(): IsoDep? {
|
|
208
|
+
// 展示连接 ui
|
|
209
|
+
sendEvent(context, NFC_UI_EVENT, Arguments.createMap().also {
|
|
210
|
+
it.putInt("code", 1)
|
|
211
|
+
it.putString("message", "show_connect_ui")
|
|
212
|
+
})
|
|
213
|
+
mShowDialogNumber.incrementAndGet()
|
|
214
|
+
if (!mNFCConnectedChannel.isEmpty) {
|
|
215
|
+
mNFCConnectedChannel.tryReceive()
|
|
216
|
+
}
|
|
217
|
+
val receiveIsoDep = mNFCConnectedChannel.receive()
|
|
218
|
+
mCurrentCardState = null
|
|
219
|
+
if (receiveIsoDep == null) {
|
|
220
|
+
// 取消连接
|
|
221
|
+
releaseDevice()
|
|
222
|
+
} else {
|
|
223
|
+
val initChannelRequest = OneKeyLiteCard.initRequest(receiveIsoDep)
|
|
224
|
+
|
|
225
|
+
mCurrentCardState = initChannelRequest
|
|
226
|
+
|
|
227
|
+
// 展示连接结束 ui
|
|
228
|
+
sendEvent(context, NFC_UI_EVENT, Arguments.createMap().also {
|
|
229
|
+
it.putInt("code", 2)
|
|
230
|
+
it.putString("message", "connected")
|
|
231
|
+
})
|
|
232
|
+
}
|
|
233
|
+
return receiveIsoDep
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
private fun releaseDevice() {
|
|
237
|
+
if (mShowDialogNumber.get() <= 0) return
|
|
238
|
+
|
|
239
|
+
mCurrentCardState = null
|
|
240
|
+
val decrementAndGet = mShowDialogNumber.decrementAndGet()
|
|
241
|
+
|
|
242
|
+
// 关闭连接结束 ui
|
|
243
|
+
sendEvent(context, NFC_UI_EVENT, Arguments.createMap().also {
|
|
244
|
+
it.putInt("code", 3)
|
|
245
|
+
it.putString("message", "close_connect_ui")
|
|
246
|
+
})
|
|
247
|
+
|
|
248
|
+
// 还有需要处理的 NFC 事件
|
|
249
|
+
if (decrementAndGet > 0) {
|
|
250
|
+
// 展示连接 ui
|
|
251
|
+
sendEvent(context, NFC_UI_EVENT, Arguments.createMap().also {
|
|
252
|
+
it.putInt("code", 1)
|
|
253
|
+
it.putString("message", "show_connect_ui")
|
|
254
|
+
})
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
private suspend fun <T> handleOperation(
|
|
259
|
+
callback: Callback,
|
|
260
|
+
execute: (isoDep: IsoDep) -> T
|
|
261
|
+
) {
|
|
262
|
+
val topActivity = Utils.getTopActivity()
|
|
263
|
+
if (topActivity == null) {
|
|
264
|
+
callback.invoke(NFCExceptions.InitializedException().createArguments(), null, null)
|
|
265
|
+
return
|
|
266
|
+
}
|
|
267
|
+
val isNfcExists = NfcUtils.isNfcExits(topActivity)
|
|
268
|
+
if (!isNfcExists) {
|
|
269
|
+
// 没有 NFC 设备
|
|
270
|
+
Log.d(TAG, "NFC device not found")
|
|
271
|
+
callback.invoke(NFCExceptions.NotExistsNFC().createArguments(), null, null)
|
|
272
|
+
return
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
val isNfcEnable = NfcUtils.isNfcEnable(topActivity)
|
|
276
|
+
if (!isNfcEnable) {
|
|
277
|
+
// 没有打开 NFC 开关
|
|
278
|
+
Log.d(TAG, "NFC device not enable")
|
|
279
|
+
callback.invoke(NFCExceptions.NotEnableNFC().createArguments(), null, null)
|
|
280
|
+
return
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
NfcPermissionUtils.checkPermission(topActivity) {
|
|
284
|
+
try {
|
|
285
|
+
Log.d(TAG, "NFC permission check success")
|
|
286
|
+
val isoDep = acquireDevice() ?: return
|
|
287
|
+
val executeResult = execute(isoDep)
|
|
288
|
+
callback.invoke(null, executeResult, mCurrentCardState.createArguments())
|
|
289
|
+
} catch (e: NFCExceptions) {
|
|
290
|
+
Log.e(TAG, "NFC device execute error", e)
|
|
291
|
+
callback.invoke(e.createArguments(), null, mCurrentCardState.createArguments())
|
|
292
|
+
} finally {
|
|
293
|
+
releaseDevice()
|
|
294
|
+
}
|
|
295
|
+
return
|
|
296
|
+
}
|
|
297
|
+
// 没有 NFC 使用权限
|
|
298
|
+
Log.d(TAG, "NFC device not permission")
|
|
299
|
+
callback.invoke(NFCExceptions.NotNFCPermission().createArguments(), null, null)
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
private fun CardState?.createArguments(): WritableMap {
|
|
303
|
+
val map = Arguments.createMap()
|
|
304
|
+
if (this == null) return map
|
|
305
|
+
map.putBoolean("hasBackup", this.hasBackup)
|
|
306
|
+
map.putBoolean("isNewCard", this.isNewCard)
|
|
307
|
+
map.putString("serialNum", this.serialNum)
|
|
308
|
+
map.putInt("pinRetryCount", this.pinRetryCount)
|
|
309
|
+
return map
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
private fun NFCExceptions?.createArguments(): WritableMap {
|
|
313
|
+
val map = Arguments.createMap()
|
|
314
|
+
if (this == null) return map
|
|
315
|
+
map.putInt("code", this.code)
|
|
316
|
+
map.putString("message", this.message)
|
|
317
|
+
return map
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
@ReactMethod
|
|
321
|
+
fun cancel() {
|
|
322
|
+
if (mNFCConnectedChannel.isEmpty) {
|
|
323
|
+
mNFCConnectedChannel.trySend(null)
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
@ReactMethod
|
|
328
|
+
fun getCardName(callback: Callback) = launch {
|
|
329
|
+
Log.d(TAG, "getCardName")
|
|
330
|
+
handleOperation(callback) { isoDep ->
|
|
331
|
+
Log.e(TAG, "getCardName Obtain the device")
|
|
332
|
+
val cardName = OneKeyLiteCard.getCardName(isoDep)
|
|
333
|
+
Log.e(TAG, "getCardName result $cardName")
|
|
334
|
+
cardName
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
@ReactMethod
|
|
339
|
+
fun getLiteInfo(callback: Callback) = launch {
|
|
340
|
+
Log.d(TAG, "getLiteInfo")
|
|
341
|
+
handleOperation(callback) { isoDep ->
|
|
342
|
+
Log.e(TAG, "getLiteInfo Obtain the device")
|
|
343
|
+
val cardInfo = OneKeyLiteCard.getCardInfo(isoDep)
|
|
344
|
+
Log.e(TAG, "getLiteInfo result $cardInfo")
|
|
345
|
+
cardInfo.createArguments()
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
@ReactMethod
|
|
350
|
+
fun setMnemonic(mnemonic: String, pwd: String, overwrite: Boolean, callback: Callback) =
|
|
351
|
+
launch {
|
|
352
|
+
handleOperation(callback) { isoDep ->
|
|
353
|
+
Log.e(TAG, "setMnemonic Obtain the device")
|
|
354
|
+
val isSuccess =
|
|
355
|
+
OneKeyLiteCard.setMnemonic(mCurrentCardState, isoDep, mnemonic, pwd, overwrite)
|
|
356
|
+
if (!isSuccess) throw NFCExceptions.ExecFailureException()
|
|
357
|
+
Log.e(TAG, "setMnemonic result success")
|
|
358
|
+
true
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
@ReactMethod
|
|
363
|
+
fun getMnemonicWithPin(pwd: String, callback: Callback) = launch {
|
|
364
|
+
Log.d(TAG, "getMnemonicWithPin")
|
|
365
|
+
handleOperation(callback) { isoDep ->
|
|
366
|
+
Log.e(TAG, "getMnemonicWithPin Obtain the device")
|
|
367
|
+
OneKeyLiteCard.getMnemonicWithPin(mCurrentCardState, isoDep, pwd)
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
@ReactMethod
|
|
372
|
+
fun changePin(oldPwd: String, newPwd: String, callback: Callback) = launch {
|
|
373
|
+
Log.d(TAG, "changePin")
|
|
374
|
+
handleOperation(callback) { isoDep ->
|
|
375
|
+
Log.e(TAG, "changePin Obtain the device")
|
|
376
|
+
OneKeyLiteCard.changPin(mCurrentCardState, isoDep, oldPwd, newPwd)
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
@ReactMethod
|
|
381
|
+
fun reset(callback: Callback) = launch {
|
|
382
|
+
Log.d(TAG, "reset")
|
|
383
|
+
handleOperation(callback) { isoDep ->
|
|
384
|
+
Log.e(TAG, "reset Obtain the device")
|
|
385
|
+
val isSuccess = OneKeyLiteCard.reset(isoDep)
|
|
386
|
+
if (!isSuccess) throw NFCExceptions.ExecFailureException()
|
|
387
|
+
Log.e(TAG, "reset result success")
|
|
388
|
+
true
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
@ReactMethod
|
|
393
|
+
fun intoSetting() = launch {
|
|
394
|
+
Log.d(TAG, "intoSetting")
|
|
395
|
+
Utils.getTopActivity()?.let {
|
|
396
|
+
NfcUtils.intentToNfcSetting(it)
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
package so.onekey.app.wallet
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.ReactPackage
|
|
4
|
+
import com.facebook.react.bridge.NativeModule
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.uimanager.ViewManager
|
|
7
|
+
|
|
8
|
+
class OKLitePackage : ReactPackage {
|
|
9
|
+
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> =
|
|
10
|
+
listOf<NativeModule>(
|
|
11
|
+
OKLiteManager(reactContext),
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
override fun createViewManagers(reactContext: ReactApplicationContext) =
|
|
15
|
+
emptyList<ViewManager<*, *>>()
|
|
16
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
package so.onekey.app.wallet.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,151 @@
|
|
|
1
|
+
package so.onekey.app.wallet.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.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 ("Smartisan".equals(Build.MANUFACTURER, true)) {
|
|
105
|
+
if (intentToNfcShare(context)) {
|
|
106
|
+
return true
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if ("xiaomi".equals(Build.MANUFACTURER, true)) {
|
|
110
|
+
MiUtil.intentToAppSetting(context)
|
|
111
|
+
return true
|
|
112
|
+
}
|
|
113
|
+
if (isNfcExits(context)) {
|
|
114
|
+
return toIntent(context, Settings.ACTION_NFC_SETTINGS)
|
|
115
|
+
}
|
|
116
|
+
return false
|
|
117
|
+
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* 跳转至系统NFC Android Beam设置界面,同页面基本都有NFC开关.
|
|
122
|
+
*
|
|
123
|
+
* @param context [Context]
|
|
124
|
+
* @return `true` 跳转成功 <br></br> `false` 跳转失败
|
|
125
|
+
*/
|
|
126
|
+
fun intentToNfcShare(context: Context): Boolean {
|
|
127
|
+
return if (isAndroidBeamExits(context)) {
|
|
128
|
+
toIntent(context, Settings.ACTION_NFCSHARING_SETTINGS)
|
|
129
|
+
} else false
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* 跳转方法.
|
|
134
|
+
*
|
|
135
|
+
* @param context [Context]
|
|
136
|
+
* @param action 意图
|
|
137
|
+
* @return 是否跳转成功 `true ` 成功<br></br>`false`失败
|
|
138
|
+
*/
|
|
139
|
+
private fun toIntent(context: Context, action: String): Boolean {
|
|
140
|
+
try {
|
|
141
|
+
val intent = Intent(action)
|
|
142
|
+
context.startActivity(intent)
|
|
143
|
+
} catch (ex: Exception) {
|
|
144
|
+
ex.printStackTrace()
|
|
145
|
+
return false
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return true
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
}
|
package/android/src/main/java/so/onekey/app/wallet/nfc/broadcast/NfcStatusChangeBroadcastReceiver.kt
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
package so.onekey.app.wallet.nfc.broadcast
|
|
2
|
+
|
|
3
|
+
import android.content.BroadcastReceiver
|
|
4
|
+
import android.content.Context
|
|
5
|
+
import android.content.Intent
|
|
6
|
+
import android.content.IntentFilter
|
|
7
|
+
import android.nfc.NfcAdapter
|
|
8
|
+
import android.util.Log
|
|
9
|
+
|
|
10
|
+
open class NfcStatusChangeBroadcastReceiver : BroadcastReceiver() {
|
|
11
|
+
|
|
12
|
+
override fun onReceive(context: Context, intent: Intent) {
|
|
13
|
+
val action = intent.action
|
|
14
|
+
if (NfcAdapter.ACTION_ADAPTER_STATE_CHANGED == action) {
|
|
15
|
+
val state =
|
|
16
|
+
intent.getIntExtra(NfcAdapter.EXTRA_ADAPTER_STATE, NfcAdapter.STATE_OFF)
|
|
17
|
+
|
|
18
|
+
Log.e(TAG, "nfc state broadcast receiver, state is $state")
|
|
19
|
+
when (state) {
|
|
20
|
+
NfcAdapter.STATE_OFF -> onNfcOff()
|
|
21
|
+
NfcAdapter.STATE_ON -> onNfcOn()
|
|
22
|
+
NfcAdapter.STATE_TURNING_OFF -> onNfcTurningOff()
|
|
23
|
+
NfcAdapter.STATE_TURNING_ON -> onNfcTurningOn()
|
|
24
|
+
5 -> onCardPayMode() //samsumg return 5 that minds card pay mode
|
|
25
|
+
else -> onNfcOff()
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
protected open fun onNfcTurningOn() {
|
|
31
|
+
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
protected open fun onNfcTurningOff() {
|
|
35
|
+
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
protected open fun onNfcOn() {
|
|
39
|
+
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
protected open fun onNfcOff() {
|
|
43
|
+
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
protected open fun onCardPayMode() {
|
|
47
|
+
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
companion object {
|
|
51
|
+
val TAG: String = NfcStatusChangeBroadcastReceiver::class.java.simpleName
|
|
52
|
+
|
|
53
|
+
val nfcBroadcastReceiverIntentFilter: IntentFilter
|
|
54
|
+
get() = IntentFilter("android.nfc.action.ADAPTER_STATE_CHANGED")
|
|
55
|
+
}
|
|
56
|
+
}
|