-
Notifications
You must be signed in to change notification settings - Fork 51
/
MainActivity.kt
107 lines (94 loc) · 3.18 KB
/
MainActivity.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package com.hoc.node_auth
import android.util.Log
import com.google.crypto.tink.subtle.Base64
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import kotlinx.coroutines.*
class MainActivity : FlutterActivity() {
private lateinit var cryptoChannel: MethodChannel
private lateinit var mainScope: CoroutineScope
//region Lifecycle
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
Log.d("Flutter", "configureFlutterEngine flutterEngine=$flutterEngine $this")
mainScope = MainScope()
cryptoChannel = MethodChannel(
flutterEngine.dartExecutor.binaryMessenger,
CRYPTO_CHANNEL,
).apply { setMethodCallHandler(MethodCallHandlerImpl()) }
}
override fun cleanUpFlutterEngine(flutterEngine: FlutterEngine) {
super.cleanUpFlutterEngine(flutterEngine)
Log.d("Flutter", "cleanUpFlutterEngine flutterEngine=$flutterEngine $this")
cryptoChannel.setMethodCallHandler(null)
mainScope.cancel()
}
//endregion
private inner class MethodCallHandlerImpl : MethodChannel.MethodCallHandler {
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
when (call.method) {
ENCRYPT_METHOD -> encrypt(call, result)
DECRYPT_METHOD -> decrypt(call, result)
else -> result.notImplemented()
}
}
}
//region Handlers
private fun encrypt(
call: MethodCall,
result: MethodChannel.Result
) {
val plaintext = checkNotNull(call.arguments<String?>()) { "plaintext must be not null" }
mainScope.launch {
runCatching {
withContext(Dispatchers.IO) {
plaintext
.encodeToByteArray()
.let { myApp.aead.encrypt(it, null) }
.let { Base64.encode(it) }
}
}
.onSuccess { result.success(it) }
.onFailureExceptCancellationException {
Log.e("Flutter", "encrypt", it)
result.error(CRYPTO_ERROR_CODE, it.message, null)
}
}
}
private fun decrypt(
call: MethodCall,
result: MethodChannel.Result
) {
val ciphertext = checkNotNull(call.arguments<String?>()) { "ciphertext must be not null" }
mainScope.launch {
runCatching {
withContext(Dispatchers.IO) {
Base64
.decode(ciphertext, Base64.DEFAULT)
.let { myApp.aead.decrypt(it, null) }
.decodeToString()
}
}
.onSuccess { result.success(it) }
.onFailureExceptCancellationException {
Log.e("Flutter", "decrypt", it)
result.error(CRYPTO_ERROR_CODE, it.message, null)
}
}
}
//endregion
private companion object {
const val CRYPTO_CHANNEL = "com.hoc.node_auth/crypto"
const val CRYPTO_ERROR_CODE = "com.hoc.node_auth/crypto_error"
const val ENCRYPT_METHOD = "encrypt"
const val DECRYPT_METHOD = "decrypt"
}
}
private inline fun <T> Result<T>.onFailureExceptCancellationException(action: (throwable: Throwable) -> Unit): Result<T> {
return onFailure {
if (it is CancellationException) throw it
action(it)
}
}