This is an automated email from the ASF dual-hosted git repository. freeandnil pushed a commit to branch Feature/239-Android-Support in repository https://gitbox.apache.org/repos/asf/logging-log4net.git
commit 418062c39ad9c9945af7eeac100ef2ef65a72fe7 Author: Jan Friedrich <freeand...@apache.org> AuthorDate: Tue Apr 29 13:04:28 2025 +0200 #239 detect Android and use environment variables instead of AppSettings --- src/log4net.Tests/Util/SystemInfoTest.cs | 7 +++- src/log4net/Appender/AdoNetAppender.cs | 5 +-- src/log4net/Core/DefaultRepositorySelector.cs | 6 +-- src/log4net/Util/SystemInfo.cs | 47 ++++++++++++++++++---- .../modules/ROOT/pages/manual/configuration.adoc | 10 ++++- 5 files changed, 57 insertions(+), 18 deletions(-) diff --git a/src/log4net.Tests/Util/SystemInfoTest.cs b/src/log4net.Tests/Util/SystemInfoTest.cs index 8cd3fd75..9b9067c9 100644 --- a/src/log4net.Tests/Util/SystemInfoTest.cs +++ b/src/log4net.Tests/Util/SystemInfoTest.cs @@ -166,4 +166,9 @@ public void EqualsIgnoringCase_SameStringsDifferentCase_true() [Test] public void EqualsIgnoringCase_DifferentStrings_false() => Assert.That(SystemInfo.EqualsIgnoringCase("foo", "foobar"), Is.False); -} + + [Test] + [Platform(Include = "Win,Linux,MacOsX")] + public void IsAndoid() + => Assert.That(typeof(SystemInfo).GetProperty("IsAndroid", BindingFlags.Static | BindingFlags.NonPublic)?.GetValue(null), Is.False); +} \ No newline at end of file diff --git a/src/log4net/Appender/AdoNetAppender.cs b/src/log4net/Appender/AdoNetAppender.cs index 4453e39e..f720dfdf 100644 --- a/src/log4net/Appender/AdoNetAppender.cs +++ b/src/log4net/Appender/AdoNetAppender.cs @@ -449,10 +449,7 @@ protected override void SendBuffer(LoggingEvent[] events) /// Adds a parameter to the ordered list of command parameters. /// </para> /// </remarks> - public void AddParameter(AdoNetAppenderParameter parameter) - { - m_parameters.Add(parameter); - } + public void AddParameter(AdoNetAppenderParameter parameter) => m_parameters.Add(parameter); /// <summary> /// Writes the events to the database using the transaction specified. diff --git a/src/log4net/Core/DefaultRepositorySelector.cs b/src/log4net/Core/DefaultRepositorySelector.cs index f960a6e4..4cc14c88 100644 --- a/src/log4net/Core/DefaultRepositorySelector.cs +++ b/src/log4net/Core/DefaultRepositorySelector.cs @@ -469,10 +469,8 @@ public void AliasRepository(string repositoryAlias, ILoggerRepository repository /// Raises the <see cref="LoggerRepositoryCreatedEvent"/> event. /// </para> /// </remarks> - protected virtual void OnLoggerRepositoryCreatedEvent(ILoggerRepository repository) - { - LoggerRepositoryCreatedEvent?.Invoke(this, new LoggerRepositoryCreationEventArgs(repository)); - } + protected virtual void OnLoggerRepositoryCreatedEvent(ILoggerRepository repository) + => LoggerRepositoryCreatedEvent?.Invoke(this, new(repository)); /// <summary> /// Gets the repository name and repository type for the specified assembly. diff --git a/src/log4net/Util/SystemInfo.cs b/src/log4net/Util/SystemInfo.cs index 6c0f05b7..30b23fdc 100644 --- a/src/log4net/Util/SystemInfo.cs +++ b/src/log4net/Util/SystemInfo.cs @@ -36,6 +36,11 @@ public static class SystemInfo private const string DefaultNullText = "(null)"; private const string DefaultNotAvailableText = "NOT AVAILABLE"; + /// <summary> + /// Is OperatingSystem Android + /// </summary> + internal static bool IsAndroid { get; } = IsAndroidCore(); + /// <summary> /// Initialize default values for private static fields. /// </summary> @@ -68,6 +73,34 @@ static SystemInfo() NullText = nullText; } + private static bool IsAndroidCore() // https://stackoverflow.com/questions/47521008/how-can-i-distinguish-between-unix-and-android-on-netstandard-2-0 + { + if (Environment.OSVersion.Platform != PlatformID.Unix) + return false; + using System.Diagnostics.Process process = new() + { + StartInfo = new() + { + FileName = "getprop", + Arguments = "ro.build.user", + RedirectStandardOutput = true, + UseShellExecute = false, + CreateNoWindow = true + } + }; + + try + { + process.Start(); + string output = process.StandardOutput.ReadToEnd(); + return !string.IsNullOrEmpty(output); + } + catch (Exception ex) when (!ex.IsFatal()) + { + return false; + } + } + /// <summary> /// Gets the system dependent line terminator. /// </summary> @@ -414,10 +447,8 @@ public static string AssemblyFileName(Assembly myAssembly) /// then all the loaded assemblies will be searched for the type. /// </para> /// </remarks> - public static Type? GetTypeFromString(Type relativeType, string typeName, bool throwOnError, bool ignoreCase) - { - return GetTypeFromString(relativeType.EnsureNotNull().Assembly, typeName, throwOnError, ignoreCase); - } + public static Type? GetTypeFromString(Type relativeType, string typeName, bool throwOnError, bool ignoreCase) + => GetTypeFromString(relativeType.EnsureNotNull().Assembly, typeName, throwOnError, ignoreCase); /// <summary> /// Loads the type specified in the type string. @@ -438,10 +469,8 @@ public static string AssemblyFileName(Assembly myAssembly) /// in the assembly then all the loaded assemblies will be searched for the type. /// </para> /// </remarks> - public static Type? GetTypeFromString(string typeName, bool throwOnError, bool ignoreCase) - { - return GetTypeFromString(Assembly.GetCallingAssembly(), typeName, throwOnError, ignoreCase); - } + public static Type? GetTypeFromString(string typeName, bool throwOnError, bool ignoreCase) + => GetTypeFromString(Assembly.GetCallingAssembly(), typeName, throwOnError, ignoreCase); /// <summary> /// Loads the type specified in the type string. @@ -646,6 +675,8 @@ public static bool TryParse(string s, out short val) /// <returns>the value for the key, or <c>null</c></returns> public static string? GetAppSetting(string key) { + if (IsAndroid) + return Environment.GetEnvironmentVariable(key); // Android does not support config files try { return ConfigurationManager.AppSettings[key]; diff --git a/src/site/antora/modules/ROOT/pages/manual/configuration.adoc b/src/site/antora/modules/ROOT/pages/manual/configuration.adoc index ccb1c9bc..fff7d2db 100644 --- a/src/site/antora/modules/ROOT/pages/manual/configuration.adoc +++ b/src/site/antora/modules/ROOT/pages/manual/configuration.adoc @@ -349,7 +349,6 @@ The section must specify the `log4net.Config.Log4NetConfigurationSectionHandler, The following is a simple example configuration file that specifies the correct section handler to use for the `log4net` section. - [source,xml] ---- <configuration> @@ -427,6 +426,15 @@ The example shows how to embed configuration data in a .config file while allowi Since the .NET config parser throws errors for unregistered elements, the `log4net` section is registered using `System.Configuration.IgnoreSectionHandler`. This tells .NET to ignore the section, as it will be processed by log4net instead. +[#android] +== Android + +Android does not support `.config` files. + +Instead, you can set `AppSettings` values as environment variables for your process — this works only on Android. + +You must also load the `log4net` configuration manually, for example by reading it from an XML file at runtime. + [#configuration-syntax] == Configuration Syntax