implemented getLogs on Android

This commit is contained in:
Adam Velebil 2022-05-11 15:47:35 +02:00
parent 87ad07fe7c
commit 89d632390a
No known key found for this signature in database
GPG Key ID: AC6D6B9D715FC084
6 changed files with 54 additions and 22 deletions

View File

@ -5,8 +5,13 @@ import io.flutter.plugin.common.MethodChannel
class FlutterLog(messenger: BinaryMessenger) {
private val _buffer = arrayListOf<String>()
private var _channel = MethodChannel(messenger, "android.log.redirect")
companion object {
const val MAX_BUFFER_SIZE = 1000
}
init {
_channel.setMethodCallHandler { call, result ->
@ -21,7 +26,7 @@ class FlutterLog(messenger: BinaryMessenger) {
if (level == null) {
loggerError("Invalid level for message from [$loggerName]: $levelValue")
} else if (loggerName != null && message != null) {
Log.log(level, loggerName, message, error)
log(level, loggerName, message, error)
result.success(null)
} else {
result.error("-1", "Invalid log parameters", null)
@ -35,6 +40,13 @@ class FlutterLog(messenger: BinaryMessenger) {
} else {
loggerError("Invalid log level requested: $levelArgValue")
}
result.success(null)
}
"getLogs" -> {
result.success(_buffer)
}
else -> {
result.notImplemented()
}
}
}
@ -44,6 +56,14 @@ class FlutterLog(messenger: BinaryMessenger) {
Log.LogLevel.values().firstOrNull { it.name == argValue?.uppercase() }
private fun loggerError(message: String) {
Log.e("FlutterLog", message, null)
log(Log.LogLevel.ERROR,"FlutterLog", message, null)
}
private fun log(level: Log.LogLevel, loggerName: String, message: String, error: String?) {
if (_buffer.size > MAX_BUFFER_SIZE) {
_buffer.removeAt(0)
}
_buffer.addAll(Log.log(level, loggerName, message, error))
}
}

View File

@ -47,12 +47,16 @@ object Log {
}
@Suppress("unused")
fun log(level: LogLevel, loggerName: String, message: String, error: String?) {
fun log(level: LogLevel, loggerName: String, message: String, error: String?) : List<String> {
if (level < this.level) {
return
return listOf()
}
val logMessage = "[$loggerName] ${level.name}: $message"
val lines = mutableListOf<String>()
val logMessage = "[$loggerName] ${level.name}: $message".also {
lines.add(it)
}
when (level) {
LogLevel.TRAFFIC -> Log.v(TAG, logMessage)
@ -63,8 +67,12 @@ object Log {
}
error?.let {
Log.e(TAG, "[$loggerName] ${level.name}: $error")
Log.e(TAG, "[$loggerName] ${level.name}: $error".also {
lines.add(it)
})
}
return lines
}
@Suppress("unused")

View File

@ -83,9 +83,8 @@ class LoggingPanel extends ConsumerWidget {
child: const Text('Copy log'),
onPressed: () async {
_log.info('Copying log to clipboard...');
final logs =
ref.read(logLevelProvider.notifier).getLogs().join('\n');
await Clipboard.setData(ClipboardData(text: logs));
final logs = await ref.read(logLevelProvider.notifier).getLogs();
await Clipboard.setData(ClipboardData(text: logs.join('\n')));
showMessage(context, 'Log copied to clipboard');
},
),

View File

@ -23,8 +23,6 @@ import 'qr_scanner/qr_scanner_provider.dart';
import 'state.dart';
import 'views/tap_request_dialog.dart';
final androidLogger = AndroidLogger();
Future<Widget> initialize() async {
if (kDebugMode) {
Logger.root.level = Levels.DEBUG;
@ -36,6 +34,7 @@ Future<Widget> initialize() async {
Application.oath,
]),
prefProvider.overrideWithValue(await SharedPreferences.getInstance()),
logLevelProvider.overrideWithProvider(androidLogProvider),
attachedDevicesProvider
.overrideWithProvider(androidAttachedDevicesProvider),
currentDeviceDataProvider.overrideWithProvider(androidDeviceDataProvider),
@ -56,14 +55,6 @@ Future<Widget> initialize() async {
// activates window state provider
ref.read(androidWindowStateProvider);
ref.listen(logLevelProvider, (oldLevel, newLevel) {
if (oldLevel != newLevel && newLevel is Level) {
androidLogger.setLogLevel(newLevel);
}
});
androidLogger.setLogLevel(Logger.root.level);
/// initializes global handler for dialogs
FDialogApi.setup(FDialogApiImpl(ref.watch(withContextProvider)));
return const MainPage();

View File

@ -1,12 +1,17 @@
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:logging/logging.dart';
import 'package:yubico_authenticator/app/logging.dart';
final _log = Logger('android.logger');
class AndroidLogger {
final androidLogProvider =
StateNotifierProvider<LogLevelNotifier, Level>((ref) => AndroidLogger());
class AndroidLogger extends LogLevelNotifier {
final MethodChannel _channel = const MethodChannel('android.log.redirect');
AndroidLogger() {
AndroidLogger() : super() {
Logger.root.onRecord.listen((record) {
if (record.level >= Logger.root.level) {
log(record);
@ -15,12 +20,21 @@ class AndroidLogger {
_log.info('Logging initialized, outputting to Android/logcat');
}
@override
void setLogLevel(Level level) {
super.setLogLevel(level);
_channel.invokeMethod('setLevel', {
'level': level.name,
});
}
@override
Future<List<String>> getLogs() async {
_log.debug('Getting logs...');
var buffer = await _channel.invokeMethod('getLogs', {});
return List.unmodifiable(buffer);
}
void log(LogRecord record) {
_channel.invokeMethod('log', {
'loggerName': record.loggerName,

View File

@ -60,7 +60,7 @@ class LogLevelNotifier extends StateNotifier<Level> {
Logger.root.level = level;
}
List<String> getLogs() {
Future<List<String>> getLogs() async {
return List.unmodifiable(_buffer);
}
}