diff --git a/android/app/src/main/kotlin/com/yubico/authenticator/FlutterLog.kt b/android/app/src/main/kotlin/com/yubico/authenticator/FlutterLog.kt new file mode 100644 index 00000000..6c428e63 --- /dev/null +++ b/android/app/src/main/kotlin/com/yubico/authenticator/FlutterLog.kt @@ -0,0 +1,63 @@ +package com.yubico.authenticator + +import androidx.lifecycle.lifecycleScope +import io.flutter.plugin.common.BinaryMessenger +import io.flutter.plugin.common.MethodChannel +import kotlinx.coroutines.launch + +class FlutterLog(messenger: BinaryMessenger, private val activity: MainActivity) { + + private var _channel = MethodChannel(messenger, "android.log.redirect") + + companion object { + private lateinit var instance: FlutterLog + + fun create(messenger: BinaryMessenger, activity: MainActivity) { + instance = FlutterLog(messenger, activity) + } + + fun t(message: String, error: String? = null) { + instance.log("t", message, error) + } + + fun d(message: String, error: String? = null) { + instance.log("d", message, error) + } + + fun i(message: String, error: String? = null) { + instance.log("i", message, error) + } + + fun w(message: String, error: String? = null) { + instance.log("w", message, error) + } + + fun e(message: String, error: String? = null) { + instance.log("e", message, error) + } + + fun wtf(message: String, error: String? = null) { + instance.log("wtf", message, error) + } + + fun v(message: String, error: String? = null) { + instance.log("v", message, error) + } + + } + + private fun log(level: String, message: String, error: String?) { + val params = mutableMapOf( + "level" to level, + "message" to message + ) + + if (error != null) { + params["error"] = error + } + + activity.lifecycleScope.launch { + _channel.invokeMethod("log", params) + } + } +} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/yubico/authenticator/MainActivity.kt b/android/app/src/main/kotlin/com/yubico/authenticator/MainActivity.kt index 0f323857..21cc8445 100644 --- a/android/app/src/main/kotlin/com/yubico/authenticator/MainActivity.kt +++ b/android/app/src/main/kotlin/com/yubico/authenticator/MainActivity.kt @@ -1,7 +1,6 @@ package com.yubico.authenticator import android.os.Bundle -import android.util.Log import androidx.activity.viewModels import androidx.lifecycle.lifecycleScope import com.yubico.authenticator.api.AppApiImpl @@ -31,17 +30,6 @@ class MainActivity : FlutterFragmentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - // simple logger - Logger.setLogger(object : Logger() { - override fun logDebug(message: String) { - Log.d("yubico-authenticator", message) - } - - override fun logError(message: String, throwable: Throwable) { - Log.e("yubico-authenticator", message, throwable) - } - }) - yubikit = YubiKitManager(this) viewModel.handleYubiKey.observe(this) { @@ -86,6 +74,8 @@ class MainActivity : FlutterFragmentActivity() { } } + + override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) @@ -97,6 +87,23 @@ class MainActivity : FlutterFragmentActivity() { Pigeon.OathApi.setup(messenger, OathApiImpl(viewModel)) Pigeon.AppApi.setup(messenger, AppApiImpl(viewModel)) Pigeon.HDialogApi.setup(messenger, HDialogApiImpl(viewModel)) + + + // simple logger for yubikit + Logger.setLogger(object : Logger() { + init { + FlutterLog.create(messenger, this@MainActivity) + } + + override fun logDebug(message: String) { + FlutterLog.d(message) + } + + override fun logError(message: String, throwable: Throwable) { + FlutterLog.e(message, throwable.message ?: throwable.toString()) + } + }) + } } diff --git a/lib/android/init.dart b/lib/android/init.dart index c6105b62..37341f97 100644 --- a/lib/android/init.dart +++ b/lib/android/init.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:logging/logging.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:yubico_authenticator/android/logger.dart'; import '../app/app.dart'; import '../app/models.dart'; @@ -21,6 +22,8 @@ import 'views/tap_request_dialog.dart'; final _log = Logger('android.init'); Future initialize() async { + AndroidLogger.initialize(); + Logger.root.onRecord.listen((record) { if (record.level >= Logger.root.level) { debugPrint('[${record.loggerName}] ${record.level}: ${record.message}'); diff --git a/lib/android/logger.dart b/lib/android/logger.dart new file mode 100644 index 00000000..c71b45d8 --- /dev/null +++ b/lib/android/logger.dart @@ -0,0 +1,32 @@ +import 'package:flutter/services.dart'; +import 'package:logging/logging.dart'; + +class AndroidLogger { + final _androidLogger = Logger('android.redirect'); + final MethodChannel _channel = const MethodChannel('android.log.redirect'); + + final levelMap = { + 't': Level.FINE, + 'd': Level.CONFIG, + 'i': Level.INFO, + 'w': Level.WARNING, + 'e': Level.SEVERE, + 'wtf': Level.SHOUT, + 'v': Level.ALL, + }; + + static AndroidLogger? instance; + static void initialize() { + instance = AndroidLogger(); + } + + AndroidLogger() { + _channel.setMethodCallHandler((call) async { + var level = call.arguments['level']; + var message = call.arguments['message']; + var error = call.arguments['error']; + _androidLogger.log(levelMap[level] ?? Level.INFO, message, error); + return 0; + }); + } +}